From e25b0e49f5fd4b82633d114cfabb7fcf9f4b5b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Pannetier?= Date: Mon, 11 Dec 2023 13:51:14 +0000 Subject: [PATCH 001/332] reintroduced requirement for status check --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 021876d..01caa81 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -67,6 +67,8 @@ To report a bug, please [open an issue](https://github.com/RangeShifter/RangeShi Please do check if a related issue has already open on one of the other interfaces ([here](https://github.com/RangeShifter/RangeShifter_batch/issues) for the batch interface or [here](https://github.com/RangeShifter/RangeShiftR-package-dev) for the R package interface). To propose a bug fix (thank you!!), please create and work on your own branch or fork, from either `main` or `develop` (preferred), and open a pull request when your fix is ready to be merged into the original branch. +As a prerequisite for merging, please ensure that your version passes status check (that is, RScore can still build, and all unit tests are still satisfied). This can be seen in the Actions panel for every commit and at the bottom of the pull request. + Maintainers will review the pull request, possibly request changes, and eventually integrate the bug fix into RScore, and update the subtrees to bring the fix to all interfaces. #### New features From cbe9b3dbb48fe455067328d2e3b921f55531a46a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 8 Jan 2024 10:11:53 +0100 Subject: [PATCH 002/332] skeleton for population unit tests --- Community.cpp | 2 +- Main.cpp | 2 ++ Population.cpp | 26 +++++++++++++++++++++++++- Population.h | 4 ++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/Community.cpp b/Community.cpp index 286dc6a..61b2c54 100644 --- a/Community.cpp +++ b/Community.cpp @@ -454,7 +454,7 @@ void Community::emigration(void) void Community::dispersal(short landIx, short nextseason) #else void Community::dispersal(short landIx) -#endif // SEASONAL || RS_RCPP +#endif // RS_RCPP { #if RSDEBUG int t0, t1, t2; diff --git a/Main.cpp b/Main.cpp index 42f783b..1d632ff 100644 --- a/Main.cpp +++ b/Main.cpp @@ -34,6 +34,7 @@ #include "RSrandom.h" #include "Utils.h" #include "Parameters.h" +#include "Population.h" #include "Landscape.h" #include "Species.h" #include "SubCommunity.h" @@ -44,6 +45,7 @@ void run_unit_tests() { cout << "******* Unit test output *******" << endl; testRSrandom(); testIndividual(); + testPopulation(); cout << endl << "************************" << endl; } diff --git a/Population.cpp b/Population.cpp index 3dbb6a2..60c231c 100644 --- a/Population.cpp +++ b/Population.cpp @@ -57,7 +57,8 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) pPatch = pPch; // record the new population in the patch patchPopn pp; - pp.pSp = (intptr)pSpecies; pp.pPop = (intptr)this; + pp.pSp = (intptr)pSpecies; + pp.pPop = (intptr)this; pPatch->addPopn(pp); demogrParams dem = pSpecies->getDemogr(); @@ -1671,3 +1672,26 @@ void Population::outGenetics(const int rep, const int year, const int landNr) //--------------------------------------------------------------------------- +#if RSDEBUG +void testPopulation() +{ + int resol{ 1 }; + int nInds{ 10 }; + Species* pSpecies; + Patch* pPatch; + Population p; + assert(p.getNInds() == 0); + // disperser disp; + // p.extractDisperser + /* + short nStages; // 0 + short nSexes; // 0 + Species *pSpecies; // NULL // pointer to the species + Patch *pPatch; // NULL // pointer to the patch + int nInds[NSTAGES][NSEXES]; // undef // no. of individuals in each stage/sex + std::vector inds; // undef // all individuals in population except ... + std::vector juvs; // undef + */ + cout << "All tests for Population have run." << endl; +} +#endif // RSDEBUG diff --git a/Population.h b/Population.h index fd1fa66..02eb08e 100644 --- a/Population.h +++ b/Population.h @@ -240,6 +240,10 @@ extern RSrandom *pRandom; extern ofstream DEBUGLOG; #endif +#if RSDEBUG +void testPopulation(); +#endif + //--------------------------------------------------------------------------- #endif From e895b80d7e4890c95859585eaf411331e8b6efd7 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 11 Jan 2024 11:35:32 +0000 Subject: [PATCH 003/332] rm unmatched declarations --- Landscape.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Landscape.h b/Landscape.h index 2a414cc..8ee3231 100644 --- a/Landscape.h +++ b/Landscape.h @@ -459,11 +459,6 @@ class Landscape{ int, // landscape index number (always 0 if landscape is not dynamic) int // landscape no. ); - void drawGradient(void); // Draw environmental gradient map - void drawGlobalStoch( // Draw environmental stochasticity time-series - int // no. of years - ); - void resetVisits(void); void outVisits(int,int); // save SMS path visits map to raster text file From 0e5f367411e225a6c9a760b76d501c057b18a533 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 11 Jan 2024 18:05:58 +0000 Subject: [PATCH 004/332] progress on generating a simple test landscape --- Individual.cpp | 54 +++++- Landscape.cpp | 2 +- Patch.cpp | 443 +++++++++++++++++++++++++------------------------ Patch.h | 102 ++++++------ 4 files changed, 322 insertions(+), 279 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index cb6c5f8..917ba82 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -950,12 +950,13 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, } } // randomise the position of the individual inside the cell + // so x and y are a corner of the cell? xrand = (double)loc.x + pRandom->Random() * 0.999; yrand = (double)loc.y + pRandom->Random() * 0.999; + // draw factor r1 0 < r1 <= 1 r1 = 0.0000001 + pRandom->Random() * (1.0 - 0.0000001); - // dist = (-1.0*meandist)*std::log(r1); - dist = (-1.0 * meandist) * log(r1); // for LINUX_CLUSTER + dist = (-1.0 * meandist) * log(r1); rndangle = pRandom->Random() * 2.0 * PI; nx = xrand + dist * sin(rndangle); @@ -967,6 +968,7 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, #endif loopsteps++; } while (loopsteps < 1000 && + // keep drawing if out of bounds of landscape or same cell ((!absorbing && (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY)) || (!usefullkernel && newX == loc.x && newY == loc.y)) @@ -997,7 +999,7 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, } } } - else { + else { // exceeded 1000 attempts patch = 0; patchNum = -1; } @@ -1006,6 +1008,7 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, if (loopsteps < 1000) { if (pCell == 0) { // beyond absorbing boundary or in no-data cell + // this should never be true?? pCurrCell = 0; status = 6; dispersing = 0; @@ -1033,7 +1036,7 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, } } } - else { + else { // exceeded 1000 attempts status = 6; dispersing = 0; } @@ -1831,9 +1834,6 @@ void testIndividual() { short moveType = 1; Individual ind(pCell, pPatch, stg, age, repInt, probmale, uses_movt_process, moveType); - // An individual can move to a neighbouring cell - //ind.moveto(); - // Gets its sex drawn from pmale // Can age or develop @@ -1849,6 +1849,46 @@ void testIndividual() { // Disperses // Emigrates // Transfers + // Kernel transfer + { + // Set up landscape + Landscape ls; + landParams ls_params; + ls_params.dimX = ls_params.dimY = 10; + ls.setLandParams(ls_params, true); + + // Set up species for habitat codes + Species sp; + sp.createHabK(1); + sp.setHabK(0, 100.0); // one habitat with K = 100 + + ls.setCellArray(); + Cell* pC1 = new Cell(51, 21, 0, 0); + Patch* pPch = ls.newPatch(0); + ls.addCellToPatch(pC1, pPch); + // add C1 to cell array? + + // Add cells + ls.setCellArray(); + ls.addNewCellToLand(51, 21, 0); + ls.addNewCellToLand(58, 28, 0); + ls.allocatePatches(&sp); + + ls.getPatchData(); + Individual ind(pCell, pPatch, 1, 0, 0, 0.0, false, 0); + + // Arrival cell + + // An individual with a small dispersal distance is unlikely to reach a distant cell + + // An individual with a large dispersal distance should be able to reach a distant cell + + // If no cell is available beyond initial cell, individual should die + + // + + } + // Individual::moveKernel(Landscape * pLandscape, Species * pSpecies, const short repType, const bool absorbing) // Settles // Survives diff --git a/Landscape.cpp b/Landscape.cpp index ea6d734..71600d5 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -882,7 +882,7 @@ void Landscape::updateCarryingCapacity(Species* pSpecies, int yr, short landIx) int npatches = (int)patches.size(); for (int i = 0; i < npatches; i++) { if (patches[i]->getPatchNum() != 0) { // not matrix patch - patches[i]->setCarryingCapacity(pSpecies, landlimits, + patches[i]->calculateKXY(pSpecies, landlimits, getGlobalStoch(yr), nHab, rasterType, landIx, gradK); } } diff --git a/Patch.cpp b/Patch.cpp index 60421c4..1361a67 100644 --- a/Patch.cpp +++ b/Patch.cpp @@ -1,47 +1,47 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Patch.h" //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -Patch::Patch(int seqnum,int num) +Patch::Patch(int seqnum, int num) { -patchSeqNum = seqnum; patchNum = num; nCells = 0; -xMin = yMin = 999999999; xMax = yMax = 0; x = y = 0; -subCommPtr = 0; -localK = 0.0; -for (int sex = 0; sex < NSEXES; sex++) { - nTemp[sex] = 0; -} -changed = false; + patchSeqNum = seqnum; patchNum = num; nCells = 0; + xMin = yMin = 999999999; xMax = yMax = 0; x = y = 0; + subCommPtr = 0; + localK = 0.0; + for (int sex = 0; sex < NSEXES; sex++) { + nTemp[sex] = 0; + } + changed = false; } Patch::~Patch() { -cells.clear(); -popns.clear(); + cells.clear(); + popns.clear(); } int Patch::getSeqNum(void) { return patchSeqNum; } @@ -51,68 +51,68 @@ int Patch::getPatchNum(void) { return patchNum; } int Patch::getNCells(void) { return nCells; } patchLimits Patch::getLimits(void) { -patchLimits p; -p.xMin = xMin; p.xMax = xMax; p.yMin = yMin; p.yMax = yMax; -return p; + patchLimits p; + p.xMin = xMin; p.xMax = xMax; p.yMin = yMin; p.yMax = yMax; + return p; } // Does the patch fall (partially) within a specified rectangle? -bool Patch::withinLimits(patchLimits rect){ -locn loc; -if (xMin <= rect.xMax && xMax >= rect.xMin && yMin <= rect.yMax && yMax >= rect.yMin) { - // patch is within the rectangle UNLESS it is irregular in shape and lies at a corner - // of the rectangle - if ((xMin >= rect.xMin && xMax <= rect.xMax) - || (yMin >= rect.yMin && yMax <= rect.yMax)) { - // patch lies within or along an edge of the initialistaion rectangle - return true; - } - else { - // check for any cell of the patch lying within the rectangle - int ncells = (int)cells.size(); - for (int i = 0; i < ncells; i++) { - loc = getCellLocn(i); - if (loc.x >= rect.xMin && loc.x <= rect.xMax - && loc.y >= rect.yMin && loc.y <= rect.yMax) { - // cell lies within the rectangle - return true; - } +bool Patch::withinLimits(patchLimits rect) { + locn loc; + if (xMin <= rect.xMax && xMax >= rect.xMin && yMin <= rect.yMax && yMax >= rect.yMin) { + // patch is within the rectangle UNLESS it is irregular in shape and lies at a corner + // of the rectangle + if ((xMin >= rect.xMin && xMax <= rect.xMax) + || (yMin >= rect.yMin && yMax <= rect.yMax)) { + // patch lies within or along an edge of the initialistaion rectangle + return true; + } + else { + // check for any cell of the patch lying within the rectangle + int ncells = (int)cells.size(); + for (int i = 0; i < ncells; i++) { + loc = getCellLocn(i); + if (loc.x >= rect.xMin && loc.x <= rect.xMax + && loc.y >= rect.yMin && loc.y <= rect.yMax) { + // cell lies within the rectangle + return true; } } } -return false; + } + return false; } // Reset minimum and maximum co-ordinates of the patch if it has been changed void Patch::resetLimits(void) { -if (changed) { - // remove any deleted cells - std::vector newcells; // for all retained and added cells - int ncells = (int)cells.size(); - for (int i = 0; i < ncells; i++) { - if (cells[i] != NULL) { - newcells.push_back(cells[i]); + if (changed) { + // remove any deleted cells + std::vector newcells; // for all retained and added cells + int ncells = (int)cells.size(); + for (int i = 0; i < ncells; i++) { + if (cells[i] != NULL) { + newcells.push_back(cells[i]); + } } + cells.clear(); + cells = newcells; + // reset patch limits + locn loc; + xMin = yMin = 999999999; xMax = yMax = 0; + ncells = (int)cells.size(); + for (int i = 0; i < ncells; i++) { + loc = getCellLocn(i); + if (loc.x < xMin) xMin = loc.x; + if (loc.x > xMax) xMax = loc.x; + if (loc.y < yMin) yMin = loc.y; + if (loc.y > yMax) yMax = loc.y; + } + changed = false; } - cells.clear(); - cells = newcells; - // reset patch limits - locn loc; - xMin = yMin = 999999999; xMax = yMax = 0; - ncells = (int)cells.size(); - for (int i = 0; i < ncells; i++) { - loc = getCellLocn(i); - if (loc.x < xMin) xMin = loc.x; - if (loc.x > xMax) xMax = loc.x; - if (loc.y < yMin) yMin = loc.y; - if (loc.y > yMax) yMax = loc.y; - } - changed = false; -} } // Add a cell to the patch -void Patch::addCell(Cell* pCell,int x,int y) { +void Patch::addCell(Cell* pCell, int x, int y) { cells.push_back(pCell); nCells++; if (x < xMin) xMin = x; @@ -123,126 +123,125 @@ void Patch::addCell(Cell* pCell,int x,int y) { // Calculate the total carrying capacity (no. of individuals) and // centroid co-ordinates of the patch -void Patch::setCarryingCapacity(Species *pSpecies,patchLimits landlimits, - float epsGlobal,short nHab,short rasterType,short landIx,bool gradK) { -envStochParams env = paramsStoch->getStoch(); -//Cell *pCell; -locn loc; -int xsum,ysum; -short hx; -float k,q,envval; - -localK = 0.0; // no. of suitable cells (unadjusted K > 0) in the patch -int nsuitable = 0; -double mean; +void Patch::calculateKXY(Species* pSpecies, patchLimits landlimits, + float epsGlobal, short nHab, short rasterType, short landIx, bool gradK) { + envStochParams env = paramsStoch->getStoch(); + locn loc; + int xsum, ysum; + short hx; + float k, q, envval; + + localK = 0.0; // no. of suitable cells (unadjusted K > 0) in the patch + int nsuitable = 0; + double mean; #if RSDEBUG -//DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum -// << " xMin=" << xMin << " yMin=" << yMin << " xMax=" << xMax << " yMax=" << yMax -// << endl; + //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum + // << " xMin=" << xMin << " yMin=" << yMin << " xMax=" << xMax << " yMax=" << yMax + // << endl; #endif -if (xMin > landlimits.xMax || xMax < landlimits.xMin -|| yMin > landlimits.yMax || yMax < landlimits.yMin) { - // patch lies wholely outwith current landscape limits - // NB the next statement is unnecessary, as localK has been set to zero above - // retained only for consistency in standard variant - localK = 0.0; + if (xMin > landlimits.xMax || xMax < landlimits.xMin + || yMin > landlimits.yMax || yMax < landlimits.yMin) { + // patch lies wholely outwith current landscape limits + // NB the next statement is unnecessary, as localK has been set to zero above + // retained only for consistency in standard variant + localK = 0.0; #if RSDEBUG -//DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum -// << " localK=" << localK -// << endl; + //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum + // << " localK=" << localK + // << endl; #endif - return; -} - -int ncells = (int)cells.size(); -xsum = ysum = 0; -for (int i = 0; i < ncells; i++) { - if (gradK) // gradient in carrying capacity - envval = cells[i]->getEnvVal(); // environmental gradient value - else envval = 1.0; // no gradient effect - if (env.stoch && env.inK) { // environmental stochasticity in K - if (env.local) { -// pCell = getRandomCell(); -// if (pCell != 0) envval += pCell->getEps(); - envval += cells[i]->getEps(); - } - else { // global stochasticity - envval += epsGlobal; - } + return; } - switch (rasterType) { - case 0: // habitat codes - hx = cells[i]->getHabIndex(landIx); - k = pSpecies->getHabK(hx); - if (k > 0.0) { - nsuitable++; - localK += envval * k; - } - break; - case 1: // cover % - k = 0.0; - for (int j = 0; j < nHab; j++) { // loop through cover layers - q = cells[i]->getHabitat(j); - k += q * pSpecies->getHabK(j) / 100.0f; - } - if (k > 0.0) { - nsuitable++; - localK += envval * k; + + int ncells = (int)cells.size(); + xsum = ysum = 0; + for (int i = 0; i < ncells; i++) { + if (gradK) // gradient in carrying capacity + envval = cells[i]->getEnvVal(); // environmental gradient value + else envval = 1.0; // no gradient effect + if (env.stoch && env.inK) { // environmental stochasticity in K + if (env.local) { + // pCell = getRandomCell(); + // if (pCell != 0) envval += pCell->getEps(); + envval += cells[i]->getEps(); + } + else { // global stochasticity + envval += epsGlobal; + } } - break; - case 2: // habitat quality - q = cells[i]->getHabitat(landIx); - if (q > 0.0) { - nsuitable++; - localK += envval * pSpecies->getHabK(0) * q / 100.0f; + switch (rasterType) { + case 0: // habitat codes + hx = cells[i]->getHabIndex(landIx); + k = pSpecies->getHabK(hx); + if (k > 0.0) { + nsuitable++; + localK += envval * k; + } + break; + case 1: // cover % + k = 0.0; + for (int j = 0; j < nHab; j++) { // loop through cover layers + q = cells[i]->getHabitat(j); + k += q * pSpecies->getHabK(j) / 100.0f; + } + if (k > 0.0) { + nsuitable++; + localK += envval * k; + } + break; + case 2: // habitat quality + q = cells[i]->getHabitat(landIx); + if (q > 0.0) { + nsuitable++; + localK += envval * pSpecies->getHabK(0) * q / 100.0f; + } + break; } - break; - } #if RSDEBUG -//DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum -// << " i=" << i << " hx=" << hx << " q=" << q << " k=" << k << " localK=" << localK -// << endl; + //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum + // << " i=" << i << " hx=" << hx << " q=" << q << " k=" << k << " localK=" << localK + // << endl; #endif - loc = cells[i]->getLocn(); - xsum += loc.x; ysum += loc.y; -} + loc = cells[i]->getLocn(); + xsum += loc.x; ysum += loc.y; + } #if RSDEBUG -//DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum -// << " epsGlobal=" << epsGlobal << " localK=" << localK -// << endl; + //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum + // << " epsGlobal=" << epsGlobal << " localK=" << localK + // << endl; #endif // calculate centroid co-ordinates -if (ncells > 0) { - mean = (double)xsum / (double)ncells; - x = (int)(mean + 0.5); - mean = (double)ysum / (double)ncells; - y = (int)(mean + 0.5); -} -if (env.stoch && env.inK) { // environmental stochasticity in K - // apply min and max limits to K over the whole patch - // NB limits have been stored as N/cell rather than N/ha - float limit; - limit = pSpecies->getMinMax(0) * (float)nsuitable; - if (localK < limit) localK = limit; + if (ncells > 0) { + mean = (double)xsum / (double)ncells; + x = (int)(mean + 0.5); + mean = (double)ysum / (double)ncells; + y = (int)(mean + 0.5); + } + if (env.stoch && env.inK) { // environmental stochasticity in K + // apply min and max limits to K over the whole patch + // NB limits have been stored as N/cell rather than N/ha + float limit; + limit = pSpecies->getMinMax(0) * (float)nsuitable; + if (localK < limit) localK = limit; #if RSDEBUG -//DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum -// << " limit=" << limit << " localK=" << localK -// << endl; + //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum + // << " limit=" << limit << " localK=" << localK + // << endl; #endif - limit = pSpecies->getMinMax(1) * (float)nsuitable; - if (localK > limit) localK = limit; + limit = pSpecies->getMinMax(1) * (float)nsuitable; + if (localK > limit) localK = limit; #if RSDEBUG -//DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum -// << " limit=" << limit << " localK=" << localK -// << endl; + //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum + // << " limit=" << limit << " localK=" << localK + // << endl; #endif -} + } #if RSDEBUG -//DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum -// << " localK=" << localK -// << endl; + //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum + // << " localK=" << localK + // << endl; #endif } @@ -251,103 +250,107 @@ float Patch::getK(void) { return localK; } // Return co-ordinates of a specified cell locn Patch::getCellLocn(int ix) { -locn loc; loc.x = -666; loc.y = -666; -int ncells = (int)cells.size(); -if (ix >= 0 && ix < ncells) { - loc = cells[ix]->getLocn(); -} -return loc; + locn loc; loc.x = -666; loc.y = -666; + int ncells = (int)cells.size(); + if (ix >= 0 && ix < ncells) { + loc = cells[ix]->getLocn(); + } + return loc; } // Return pointer to a specified cell -Cell* Patch::getCell(int ix) { -int ncells = (int)cells.size(); -if (ix >= 0 && ix < ncells) return cells[ix]; -else return 0; +Cell* Patch::getCell(int ix) { + int ncells = (int)cells.size(); + if (ix >= 0 && ix < ncells) return cells[ix]; + else return 0; } // Return co-ordinates of patch centroid locn Patch::getCentroid(void) { -locn loc; loc.x = x; loc.y = y; -return loc; + locn loc; loc.x = x; loc.y = y; + return loc; } // Select a Cell within the Patch at random, and return pointer to it // For a cell-based model, this will be the only Cell Cell* Patch::getRandomCell(void) { -Cell *pCell = 0; -int ix; -int ncells = (int)cells.size(); -if (ncells > 0) { - if (ncells == 1) ix = 0; - else ix = pRandom->IRandom(0,ncells-1); - pCell = cells[ix]; -} -return pCell; + Cell* pCell = 0; + int ix; + int ncells = (int)cells.size(); + if (ncells > 0) { + if (ncells == 1) ix = 0; + else ix = pRandom->IRandom(0, ncells - 1); + pCell = cells[ix]; + } + return pCell; } // Remove a cell from the patch void Patch::removeCell(Cell* pCell) { -int ncells = (int)cells.size(); -for (int i = 0; i < ncells; i++) { - if (pCell == cells[i]) { - cells[i] = NULL; i = ncells; - nCells--; - changed = true; + int ncells = (int)cells.size(); + for (int i = 0; i < ncells; i++) { + if (pCell == cells[i]) { + cells[i] = NULL; i = ncells; + nCells--; + changed = true; + } } } -} void Patch::setSubComm(intptr sc) -{ subCommPtr = sc; } +{ + subCommPtr = sc; +} // Get pointer to corresponding Sub-community (cast as an integer) intptr Patch::getSubComm(void) -{ return subCommPtr; } +{ + return subCommPtr; +} void Patch::addPopn(patchPopn pop) { -popns.push_back(pop); + popns.push_back(pop); } // Return pointer (cast as integer) to the Population of the specified Species intptr Patch::getPopn(intptr sp) { -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { - if (popns[i].pSp == sp) return popns[i].pPop; -} -return 0; + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { + if (popns[i].pSp == sp) return popns[i].pPop; + } + return 0; } void Patch::resetPopn(void) { -popns.clear(); + popns.clear(); } void Patch::resetPossSettlers(void) { -for (int sex = 0; sex < NSEXES; sex++) { - nTemp[sex] = 0; -} + for (int sex = 0; sex < NSEXES; sex++) { + nTemp[sex] = 0; + } } // Record the presence of a potential settler within the Patch -void Patch::incrPossSettler(Species *pSpecies,int sex) { +void Patch::incrPossSettler(Species* pSpecies, int sex) { #if RSDEBUG -//DEBUGLOG << "Patch::incrPossSettler(): 5555: patchNum = " << patchNum -// << " sex = " << sex << endl; + //DEBUGLOG << "Patch::incrPossSettler(): 5555: patchNum = " << patchNum + // << " sex = " << sex << endl; #endif // NOTE: THE FOLLOWING OPERATION WILL NEED TO BE MADE SPECIES-SPECIFIC... -if (sex >= 0 && sex < NSEXES) { - nTemp[sex]++; -} + if (sex >= 0 && sex < NSEXES) { + nTemp[sex]++; + } } // Get number of a potential settlers within the Patch -int Patch::getPossSettlers(Species *pSpecies,int sex) { +int Patch::getPossSettlers(Species* pSpecies, int sex) { #if RSDEBUG -//DEBUGLOG << "Patch::getPossSettlers(): 5555: patchNum = " << patchNum -// << " sex = " << sex << endl; + //DEBUGLOG << "Patch::getPossSettlers(): 5555: patchNum = " << patchNum + // << " sex = " << sex << endl; #endif // NOTE: THE FOLLOWING OPERATION WILL NEED TO BE MADE SPECIES-SPECIFIC... -if (sex >= 0 && sex < NSEXES) return nTemp[sex]; -else return 0; + if (sex >= 0 && sex < NSEXES) return nTemp[sex]; + else return 0; } //--------------------------------------------------------------------------- diff --git a/Patch.h b/Patch.h index 2f086d7..e435850 100644 --- a/Patch.h +++ b/Patch.h @@ -1,66 +1,66 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ -RangeShifter v2.0 Patch -Implements the class: Patch + /*------------------------------------------------------------------------------ -A patch is a collection of one or more Cells in the the gridded Landscape, -which together provide the area in which a single demographic unit of a Species, -i.e. a Population, can reproduce. One or more Populations (of different Species) -form a Sub-community associated with the Patch. + RangeShifter v2.0 Patch -There is no requirement that all the Cells be adjacent, although in practice -that would usually be the case. + Implements the class: Patch -Each Patch must have a unique positive integer id number supplied by the user, -and the matrix, i.e. any part of the landscape which is not a breeding patch, -is represented by Patch 0. However, as patch numbers need not be sequential, -an internal sequential number is also applied. + A patch is a collection of one or more Cells in the the gridded Landscape, + which together provide the area in which a single demographic unit of a Species, + i.e. a Population, can reproduce. One or more Populations (of different Species) + form a Sub-community associated with the Patch. -For a 'cell-based model', the user supplies no patch numbers, and a separate -Patch is generated internally for each Cell, i.e. the 'cell-based model' is a -special case of the 'patch-based model' in which each Patch has a single Cell. -Moreover, there is also the 'matrix' Patch 0, which has no cells, but which -holds the disperser population whilst its Individuals are in transit. + There is no requirement that all the Cells be adjacent, although in practice + that would usually be the case. -In a true patch-based model, each Patch hold a list of its constituent Cells, -EXCEPT for the matrix Patch 0. This is because that list would be extremely -long for a very large landscape in which suitable patches are small and/or rare, -and removing Cells from it if the landscape is dynamic would be inefficient. + Each Patch must have a unique positive integer id number supplied by the user, + and the matrix, i.e. any part of the landscape which is not a breeding patch, + is represented by Patch 0. However, as patch numbers need not be sequential, + an internal sequential number is also applied. -For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. -and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. -Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 + For a 'cell-based model', the user supplies no patch numbers, and a separate + Patch is generated internally for each Cell, i.e. the 'cell-based model' is a + special case of the 'patch-based model' in which each Patch has a single Cell. + Moreover, there is also the 'matrix' Patch 0, which has no cells, but which + holds the disperser population whilst its Individuals are in transit. -Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + In a true patch-based model, each Patch hold a list of its constituent Cells, + EXCEPT for the matrix Patch 0. This is because that list would be extremely + long for a very large landscape in which suitable patches are small and/or rare, + and removing Cells from it if the landscape is dynamic would be inefficient. -Last updated: 25 June 2021 by Steve Palmer + For full details of RangeShifter, please see: + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. + and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial + eco-evolutionary dynamics and species’ responses to environmental changes. + Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 -------------------------------------------------------------------------------*/ + Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + + Last updated: 25 June 2021 by Steve Palmer + + ------------------------------------------------------------------------------*/ #ifndef PatchH #define PatchH @@ -83,13 +83,13 @@ using namespace std; //--------------------------------------------------------------------------- struct patchLimits { - int xMin,xMax,yMin,yMax; + int xMin, xMax, yMin, yMax; }; struct patchPopn { - intptr pSp,pPop; // pointers to Species and Population cast as integers + intptr pSp, pPop; // pointers to Species and Population cast as integers }; -class Patch{ +class Patch { public: Patch( int, // internal sequential number @@ -106,7 +106,7 @@ class Patch{ void resetLimits(void); // Reset minimum and maximum co-ordinates of the patch void addCell( Cell*, // pointer to the Cell to be added to the Patch - int,int // x (column) and y (row) co-ordinates of the Cell + int, int // x (column) and y (row) co-ordinates of the Cell ); locn getCellLocn( // Return co-ordinates of a specified cell int // index no. of the Cell within the vector cells @@ -139,7 +139,7 @@ class Patch{ Species*, // pointer to the Species int // sex of the settlers ); - void setCarryingCapacity( // Calculate total Patch carrying capacity (no. of inds) + void calculateKXY( // Calculate total Patch carrying capacity (no. of inds) Species*, // pointer to the Species patchLimits, // current min and max limits of landscape float, // global stochasticity value (epsilon) for the current year @@ -150,19 +150,19 @@ class Patch{ ); float getK(void); // dummy function for batch version - void drawCells(float,int,rgb); + void drawCells(float, int, rgb); - private: +private: int patchSeqNum;// sequential patch number - patch 0 is reserved for the inter-patch matrix int patchNum; // patch number as supplied by the user (not forced to be sequential) int nCells; // no. of cells in the patch - int xMin,xMax,yMin,yMax; // min and max cell co-ordinates - int x,y; // centroid co-ordinates (approx.) + int xMin, xMax, yMin, yMax; // min and max cell co-ordinates + int x, y; // centroid co-ordinates (approx.) intptr subCommPtr; // pointer (cast as integer) to sub-community associated with the patch // NOTE: FOR MULTI-SPECIES MODEL, PATCH WILL NEED TO STORE K FOR EACH SPECIES float localK; // patch carrying capacity (individuals) bool changed; -// NOTE: THE FOLLOWING ARRAY WILL NEED TO BE MADE SPECIES-SPECIFIC... + // NOTE: THE FOLLOWING ARRAY WILL NEED TO BE MADE SPECIES-SPECIFIC... short nTemp[NSEXES]; // no. of potential settlers in each sex std::vector cells; @@ -172,8 +172,8 @@ class Patch{ //--------------------------------------------------------------------------- -extern paramStoch *paramsStoch; -extern RSrandom *pRandom; +extern paramStoch* paramsStoch; +extern RSrandom* pRandom; #if RSDEBUG extern ofstream DEBUGLOG; From f03fcc4b7563be72b614cee121c6d6e22c97b36d Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 12 Jan 2024 13:36:22 +0000 Subject: [PATCH 005/332] skeleton for testing landscape --- Landscape.cpp | 15 +++++++++++++++ Landscape.h | 4 ++++ Main.cpp | 1 + 3 files changed, 20 insertions(+) diff --git a/Landscape.cpp b/Landscape.cpp index 71600d5..c931f4f 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -786,6 +786,15 @@ void Landscape::addNewCellToLand(int x, int y, int hab) { cells[y][x] = new Cell(x, y, 0, hab); } +void Landscape::addCellToLand(Cell* c) { + if (cells == 0) throw runtime_error("Landscape cells member is uninitialised."); + locn l; + if (c->getHabitat(0) < 0.0) + throw logic_error("Cannot add no-data cell to landscape."); + l = c->getLocn(); + cells[l.y][l.x] = c; +} + void Landscape::addNewCellToPatch(Patch* pPatch, int x, int y, float q) { if (q < 0.0) { // no-data cell - no Cell created cells[y][x] = 0; @@ -2635,6 +2644,12 @@ void Landscape::outVisits(int rep, int landNr) { //--------------------------------------------------------------------------- +#if RSDEBUG +void testLandscape() { + // test coordinate system +} +#endif // RSDEBUG + //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- diff --git a/Landscape.h b/Landscape.h index 8ee3231..9d1d1a5 100644 --- a/Landscape.h +++ b/Landscape.h @@ -254,6 +254,9 @@ class Landscape{ int, // y co-ordinate int // habitat class no. ); + void addCellToLand( + Cell* // cell to add to landscape + ); void addCellToPatch( Cell*, // pointer to Cell Patch* // pointer to Patch @@ -543,6 +546,7 @@ extern RSrandom *pRandom; #if RSDEBUG extern ofstream DEBUGLOG; extern void DebugGUI(string); +void testLandscape(); #endif extern void MemoLine(string); diff --git a/Main.cpp b/Main.cpp index 1d632ff..6e96c44 100644 --- a/Main.cpp +++ b/Main.cpp @@ -44,6 +44,7 @@ using namespace std; void run_unit_tests() { cout << "******* Unit test output *******" << endl; testRSrandom(); + testLandscape(); testIndividual(); testPopulation(); cout << endl << "************************" << endl; From 7127146f4a25dbb84e6f3eb3c98b90cc39b5088a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 12 Jan 2024 14:04:20 +0000 Subject: [PATCH 006/332] implement try-catch --- Main.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Main.cpp b/Main.cpp index 6e96c44..6172b8a 100644 --- a/Main.cpp +++ b/Main.cpp @@ -91,7 +91,15 @@ int _tmain(int argc, _TCHAR* argv[]) return 1; # else assert(0.1 > 0.0); // assert does run correctly - run_unit_tests(); + try { + run_unit_tests(); + } + catch (const runtime_error& e) { + cerr << e.what(); + } + catch (const logic_error& e) { + cerr << e.what(); + } cout << "All tests have completed." << endl; return 0; // if tests succeed, we are happy # endif // NDEBUG From 3f4ac87d44419a6335bd8cd976437b2b75c3a50c Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 12 Jan 2024 15:14:34 +0000 Subject: [PATCH 007/332] intialise individual on landscape --- Cell.cpp | 2 +- Individual.cpp | 21 ++++++++++----------- Landscape.cpp | 7 +++---- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/Cell.cpp b/Cell.cpp index 1c0f937..cd4973c 100644 --- a/Cell.cpp +++ b/Cell.cpp @@ -90,7 +90,7 @@ else habIxx[ix] = 0; } int Cell::getHabIndex(int ix) { -if (ix < 0 || ix >= (int)habIxx.size()) +if (ix < 0 || ix >= habIxx.size()) // nodata cell OR should not occur, but treat as such return -1; else return habIxx[ix]; diff --git a/Individual.cpp b/Individual.cpp index 917ba82..dd4aa80 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1851,10 +1851,12 @@ void testIndividual() { // Transfers // Kernel transfer { + // Landscape ls = createLandscapeFromCells(ls_params, cells, pSp); + // Set up landscape Landscape ls; landParams ls_params; - ls_params.dimX = ls_params.dimY = 10; + ls_params.dimX = ls_params.dimY = 100; ls.setLandParams(ls_params, true); // Set up species for habitat codes @@ -1862,20 +1864,17 @@ void testIndividual() { sp.createHabK(1); sp.setHabK(0, 100.0); // one habitat with K = 100 - ls.setCellArray(); - Cell* pC1 = new Cell(51, 21, 0, 0); - Patch* pPch = ls.newPatch(0); - ls.addCellToPatch(pC1, pPch); - // add C1 to cell array? - // Add cells ls.setCellArray(); - ls.addNewCellToLand(51, 21, 0); - ls.addNewCellToLand(58, 28, 0); + vector cells{new Cell(1, 1, 0, 0), new Cell(98, 98, 0, 0)}; + for (auto c : cells) { + ls.addCellToLand(c); + } ls.allocatePatches(&sp); - ls.getPatchData(); - Individual ind(pCell, pPatch, 1, 0, 0, 0.0, false, 0); + Cell* c = new Cell(1, 1, 0, 0); + Patch* p = (Patch*)cells[0]->getPatch(); + Individual ind(cells[0], p, 1, 0, 0, 0.0, false, 0); // Arrival cell diff --git a/Landscape.cpp b/Landscape.cpp index c931f4f..5a0b712 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -788,10 +788,9 @@ void Landscape::addNewCellToLand(int x, int y, int hab) { void Landscape::addCellToLand(Cell* c) { if (cells == 0) throw runtime_error("Landscape cells member is uninitialised."); - locn l; - if (c->getHabitat(0) < 0.0) - throw logic_error("Cannot add no-data cell to landscape."); - l = c->getLocn(); + if (c->getHabIndex(0) < 0.0) + throw logic_error("Can't add no-data cell to landscape."); + locn l = c->getLocn(); cells[l.y][l.x] = c; } From 528de117762d0ab1724344372666e95b0bec1dd5 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 12 Jan 2024 17:40:26 +0000 Subject: [PATCH 008/332] progress towards first moveKernel test --- Individual.cpp | 59 +++++++++++++++++++++++++++++++++++--------------- Individual.h | 5 ++++- Landscape.cpp | 20 +++++++++++++++++ Landscape.h | 1 + Population.cpp | 2 +- 5 files changed, 67 insertions(+), 20 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index dd4aa80..2b0108c 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -864,8 +864,7 @@ void Individual::moveto(Cell* newCell) { // Move to a new cell by sampling a dispersal distance from a single or double // negative exponential kernel // Returns 1 if still dispersing (including having found a potential patch), otherwise 0 -int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, - const short repType, const bool absorbing) +int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, const bool absorbing) { intptr patch; @@ -1815,7 +1814,9 @@ double cauchy(double location, double scale) { //--------------------------------------------------------------------------- #if RSDEBUG - +Cell* Individual::getCurrCell() const { + return pCurrCell; +} void testIndividual() { @@ -1851,30 +1852,52 @@ void testIndividual() { // Transfers // Kernel transfer { - // Landscape ls = createLandscapeFromCells(ls_params, cells, pSp); - - // Set up landscape - Landscape ls; + // Simple cell-based landscape layout + // oo + // oo landParams ls_params; - ls_params.dimX = ls_params.dimY = 100; - ls.setLandParams(ls_params, true); - + ls_params.dimX = ls_params.dimY = 2; + vector cells{ new Cell(0, 0, 0, 0), new Cell(1, 1, 0, 0) }; // Set up species for habitat codes Species sp; sp.createHabK(1); sp.setHabK(0, 100.0); // one habitat with K = 100 - // Add cells - ls.setCellArray(); - vector cells{new Cell(1, 1, 0, 0), new Cell(98, 98, 0, 0)}; - for (auto c : cells) { - ls.addCellToLand(c); - } - ls.allocatePatches(&sp); + // Landscape ls = createLandscapeFromCells(cells, ls_params, sp); + Landscape ls; + ls.setLandParams(ls_params, true); + // Add cells + ls.setCellArray(); + for (auto c : cells) { + ls.addCellToLand(c); + } + ls.allocatePatches(&sp); - Cell* c = new Cell(1, 1, 0, 0); Patch* p = (Patch*)cells[0]->getPatch(); Individual ind(cells[0], p, 1, 0, 0, 0.0, false, 0); + Cell* init_cell = ind.getCurrCell(); + + // ind.status + // land.resol + // species.trfrKernTraits.meanDist1 + // species.useFullKernel + // pathData *path; ? + // land.minX etc. dimX dimY + // patch.localK + // bool species.stageStruct + // species trfrMortParams m; m.fixedMort = fixedMort; m.mortAlpha = mortAlpha; m.mortBeta = mortBeta; + + int isDispersing = ind.moveKernel(&ls, &sp, false); + + // After movement, individual should be... + // in a different cell + Cell* curr_cell = ind.getCurrCell(); + // not in a no-data cell + assert(curr_cell != 0); + assert(curr_cell != init_cell); + // (non-absorbing) still within landscape boundaries + + // Arrival cell diff --git a/Individual.h b/Individual.h index bdc4ecb..5d2366c 100644 --- a/Individual.h +++ b/Individual.h @@ -196,7 +196,6 @@ class Individual { int moveKernel( Landscape*, // pointer to Landscape Species*, // pointer to Species - const short, // reproduction type (see Species) const bool // absorbing boundaries? ); // Make a single movement step according to a mechanistic movement model @@ -252,6 +251,10 @@ class Individual { const int // year ); #endif +#if RSDEBUG + // Testing utilities + Cell* getCurrCell() const; +#endif private: int indId; diff --git a/Landscape.cpp b/Landscape.cpp index 5a0b712..970f2ba 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -2644,8 +2644,28 @@ void Landscape::outVisits(int rep, int landNr) { //--------------------------------------------------------------------------- #if RSDEBUG +// Debug only: shortcut setup utilities + +Landscape createLandscapeFromCells(vector cells, const landParams& lp, Species sp) { + // Set up landscape + Landscape ls; + ls.setLandParams(lp, true); + // Add cells + ls.setCellArray(); + for (auto c : cells) { + ls.addCellToLand(c); + } + ls.allocatePatches(&sp); + return ls; +} + void testLandscape() { // test coordinate system + Landscape ls; + landParams ls_params; + ls_params.dimX = ls_params.dimY = 100; + ls.setLandParams(ls_params, true); + } #endif // RSDEBUG diff --git a/Landscape.h b/Landscape.h index 9d1d1a5..e55940a 100644 --- a/Landscape.h +++ b/Landscape.h @@ -546,6 +546,7 @@ extern RSrandom *pRandom; #if RSDEBUG extern ofstream DEBUGLOG; extern void DebugGUI(string); +Landscape createLandscapeFromCells(vector cells, const landParams& lp, Species sp); void testLandscape(); #endif diff --git a/Population.cpp b/Population.cpp index 60c231c..616a0dd 100644 --- a/Population.cpp +++ b/Population.cpp @@ -849,7 +849,7 @@ int Population::transfer(Landscape* pLandscape, short landIx) disperser = inds[i]->moveStep(pLandscape, pSpecies, landIx, sim.absorbing); } else { - disperser = inds[i]->moveKernel(pLandscape, pSpecies, reptype, sim.absorbing); + disperser = inds[i]->moveKernel(pLandscape, pSpecies, sim.absorbing); } ndispersers += disperser; if (disperser) { From 9a693caea387c8b920132be18cb5006ba2ba7364 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Sun, 14 Jan 2024 12:43:56 +0000 Subject: [PATCH 009/332] fix indentation and spacing --- Cell.cpp | 206 +-- Cell.h | 62 +- Community.cpp | 2512 ++++++++++++++-------------- FractalGenerator.cpp | 336 ++-- FractalGenerator.h | 54 +- Genome.cpp | 780 ++++----- Genome.h | 78 +- Individual.cpp | 3541 ++++++++++++++++++++------------------- Individual.h | 102 +- Landscape.cpp | 3778 +++++++++++++++++++++--------------------- Landscape.h | 164 +- Model.cpp | 3580 +++++++++++++++++++-------------------- Model.h | 64 +- Parameters.cpp | 456 ++--- Parameters.h | 114 +- Patch.cpp | 444 ++--- Patch.h | 100 +- Population.cpp | 3354 ++++++++++++++++++------------------- Population.h | 80 +- RSrandom.cpp | 310 ++-- RSrandom.h | 120 +- RandomCheck.cpp | 36 +- RandomCheck.h | 24 +- Species.cpp | 2022 +++++++++++----------- Species.h | 110 +- SubCommunity.cpp | 1770 ++++++++++---------- SubCommunity.h | 80 +- 27 files changed, 12149 insertions(+), 12128 deletions(-) diff --git a/Cell.cpp b/Cell.cpp index 1c0f937..2f8c1b3 100644 --- a/Cell.cpp +++ b/Cell.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Cell.h" @@ -30,101 +30,101 @@ // Cell functions -Cell::Cell(int xx,int yy,intptr patch,int hab) +Cell::Cell(int xx, int yy, intptr patch, int hab) { -x = xx; y = yy; -pPatch = patch; -envVal = 1.0; // default - no effect of any gradient -envDev = eps = 0.0; -habIxx.push_back(hab); + x = xx; y = yy; + pPatch = patch; + envVal = 1.0; // default - no effect of any gradient + envDev = eps = 0.0; + habIxx.push_back(hab); #if RSDEBUG -//DebugGUI(("Cell::Cell(): this=" + Int2Str((int)this) -// + " x=" + Int2Str(x) + " y=" + Int2Str(y) -// + " habIndex=" + Int2Str(habIndex) -//).c_str()); + //DebugGUI(("Cell::Cell(): this=" + Int2Str((int)this) + // + " x=" + Int2Str(x) + " y=" + Int2Str(y) + // + " habIndex=" + Int2Str(habIndex) + //).c_str()); #endif -visits = 0; -smsData = 0; + visits = 0; + smsData = 0; } -Cell::Cell(int xx,int yy,intptr patch,float hab) +Cell::Cell(int xx, int yy, intptr patch, float hab) { -x = xx; y = yy; -pPatch = patch; -envVal = 1.0; // default - no effect of any gradient -envDev = eps = 0.0; -habitats.push_back(hab); -visits = 0; -smsData = 0; + x = xx; y = yy; + pPatch = patch; + envVal = 1.0; // default - no effect of any gradient + envDev = eps = 0.0; + habitats.push_back(hab); + visits = 0; + smsData = 0; } Cell::~Cell() { #if RSDEBUG -//DEBUGLOG << "Cell::~Cell(): this = " << this << " smsData = " << smsData << endl; + //DEBUGLOG << "Cell::~Cell(): this = " << this << " smsData = " << smsData << endl; #endif -habIxx.clear(); -habitats.clear(); -if (smsData != 0) { - if (smsData->effcosts != 0) delete smsData->effcosts; - delete smsData; -} + habIxx.clear(); + habitats.clear(); + if (smsData != 0) { + if (smsData->effcosts != 0) delete smsData->effcosts; + delete smsData; + } #if RSDEBUG -//DEBUGLOG << "Cell::~Cell(): deleted" << endl; + //DEBUGLOG << "Cell::~Cell(): deleted" << endl; #endif } void Cell::setHabIndex(short hx) { #if RSDEBUG -//DebugGUI(("Cell::setHabIndex(): this=" + Int2Str((int)this) -// + " x=" + Int2Str(x) + " y=" + Int2Str(y) -// + " habIx=" + Int2Str(habIx) -//).c_str()); + //DebugGUI(("Cell::setHabIndex(): this=" + Int2Str((int)this) + // + " x=" + Int2Str(x) + " y=" + Int2Str(y) + // + " habIx=" + Int2Str(habIx) + //).c_str()); #endif -if (hx < 0) habIxx.push_back(0); -else habIxx.push_back(hx); + if (hx < 0) habIxx.push_back(0); + else habIxx.push_back(hx); } -void Cell::changeHabIndex(short ix,short hx) { -if (ix >= 0 && ix < (short)habIxx.size() && hx >= 0) habIxx[ix] = hx; -else habIxx[ix] = 0; +void Cell::changeHabIndex(short ix, short hx) { + if (ix >= 0 && ix < (short)habIxx.size() && hx >= 0) habIxx[ix] = hx; + else habIxx[ix] = 0; } int Cell::getHabIndex(int ix) { -if (ix < 0 || ix >= (int)habIxx.size()) - // nodata cell OR should not occur, but treat as such - return -1; -else return habIxx[ix]; + if (ix < 0 || ix >= (int)habIxx.size()) + // nodata cell OR should not occur, but treat as such + return -1; + else return habIxx[ix]; } int Cell::nHabitats(void) { -int nh = (int)habIxx.size(); -if ((int)habitats.size() > nh) nh = (int)habitats.size(); -return nh; + int nh = (int)habIxx.size(); + if ((int)habitats.size() > nh) nh = (int)habitats.size(); + return nh; } void Cell::setHabitat(float q) { -if (q >= 0.0 && q <= 100.0) habitats.push_back(q); -else habitats.push_back(0.0); + if (q >= 0.0 && q <= 100.0) habitats.push_back(q); + else habitats.push_back(0.0); } float Cell::getHabitat(int ix) { -if (ix < 0 || ix >= (int)habitats.size()) - // nodata cell OR should not occur, but treat as such - return -1.0; -else return habitats[ix]; + if (ix < 0 || ix >= (int)habitats.size()) + // nodata cell OR should not occur, but treat as such + return -1.0; + else return habitats[ix]; } void Cell::setPatch(intptr p) { -pPatch = p; + pPatch = p; } intptr Cell::getPatch(void) { #if RSDEBUG -//DebugGUI(("Cell::getPatch(): this=" + Int2Str((int)this) -// + " x=" + Int2Str(x) + " y=" + Int2Str(y) -// + " habIxx[0]=" + Int2Str(habIxx[0]) + " pPatch=" + Int2Str(pPatch) -//).c_str()); + //DebugGUI(("Cell::getPatch(): this=" + Int2Str((int)this) + // + " x=" + Int2Str(x) + " y=" + Int2Str(y) + // + " habIxx[0]=" + Int2Str(habIxx[0]) + " pPatch=" + Int2Str(pPatch) + //).c_str()); #endif -return pPatch; + return pPatch; } locn Cell::getLocn(void) { locn q; q.x = x; q.y = y; return q; } @@ -134,13 +134,13 @@ void Cell::setEnvDev(float d) { envDev = d; } float Cell::getEnvDev(void) { return envDev; } void Cell::setEnvVal(float e) { -if (e >= 0.0) envVal = e; + if (e >= 0.0) envVal = e; } float Cell::getEnvVal(void) { return envVal; } -void Cell::updateEps(float ac,float randpart) { -eps = eps*ac + randpart; +void Cell::updateEps(float ac, float randpart) { + eps = eps * ac + randpart; } float Cell::getEps(void) { return eps; } @@ -148,54 +148,54 @@ float Cell::getEps(void) { return eps; } // Functions to handle costs for SMS int Cell::getCost(void) { -int c; -if (smsData == 0) c = 0; // costs not yet set up -else c = smsData->cost; -return c; + int c; + if (smsData == 0) c = 0; // costs not yet set up + else c = smsData->cost; + return c; } void Cell::setCost(int c) { -if (smsData == 0) { - smsData = new smscosts; - smsData->effcosts = 0; -} -smsData->cost = c; + if (smsData == 0) { + smsData = new smscosts; + smsData->effcosts = 0; + } + smsData->cost = c; } // Reset the cost and the effective cost of the cell void Cell::resetCost(void) { -if (smsData != 0) { resetEffCosts(); delete smsData; } -smsData = 0; + if (smsData != 0) { resetEffCosts(); delete smsData; } + smsData = 0; } array3x3f Cell::getEffCosts(void) { -array3x3f a; -if (smsData == 0 || smsData->effcosts == 0) { // effective costs have not been calculated - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - a.cell[i][j] = -1.0; + array3x3f a; + if (smsData == 0 || smsData->effcosts == 0) { // effective costs have not been calculated + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + a.cell[i][j] = -1.0; + } } } -} -else - a = *smsData->effcosts; -return a; + else + a = *smsData->effcosts; + return a; } -void Cell::setEffCosts(array3x3f a) { -if (smsData->effcosts == 0) smsData->effcosts = new array3x3f; -*smsData->effcosts = a; +void Cell::setEffCosts(array3x3f a) { + if (smsData->effcosts == 0) smsData->effcosts = new array3x3f; + *smsData->effcosts = a; } // Reset the effective cost, but not the cost, of the cell void Cell::resetEffCosts(void) { -if (smsData != 0) { - if (smsData->effcosts != 0) { - delete smsData->effcosts; - smsData->effcosts = 0; + if (smsData != 0) { + if (smsData->effcosts != 0) { + delete smsData->effcosts; + smsData->effcosts = 0; + } } } -} void Cell::resetVisits(void) { visits = 0; } void Cell::incrVisits(void) { visits++; } @@ -205,8 +205,8 @@ unsigned long int Cell::getVisits(void) { return visits; } // Initial species distribution cell functions -DistCell::DistCell(int xx,int yy) { -x = xx; y = yy; initialise = false; +DistCell::DistCell(int xx, int yy) { + x = xx; y = yy; initialise = false; } DistCell::~DistCell() { @@ -214,18 +214,18 @@ DistCell::~DistCell() { } void DistCell::setCell(bool init) { -initialise = init; + initialise = init; } bool DistCell::toInitialise(locn loc) { -if (loc.x == x && loc.y == y) return initialise; -else return false; + if (loc.x == x && loc.y == y) return initialise; + else return false; } bool DistCell::selected(void) { return initialise; } locn DistCell::getLocn(void) { -locn loc; loc.x = x; loc.y = y; return loc; + locn loc; loc.x = x; loc.y = y; return loc; } //--------------------------------------------------------------------------- diff --git a/Cell.h b/Cell.h index 5382a1e..02d9368 100644 --- a/Cell.h +++ b/Cell.h @@ -1,46 +1,46 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ -RangeShifter v2.0 Cell -Implements the following classes: + /*------------------------------------------------------------------------------ -Cell - Landscape cell + RangeShifter v2.0 Cell -DistCell - Initial species distribution cell + Implements the following classes: -For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. -and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. -Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 + Cell - Landscape cell -Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + DistCell - Initial species distribution cell -Last updated: 14 January 2021 by Steve Palmer + For full details of RangeShifter, please see: + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. + and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial + eco-evolutionary dynamics and species’ responses to environmental changes. + Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 -------------------------------------------------------------------------------*/ + Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + + Last updated: 14 January 2021 by Steve Palmer + + ------------------------------------------------------------------------------*/ #ifndef CellH #define CellH @@ -53,11 +53,11 @@ using namespace std; //--------------------------------------------------------------------------- struct array3x3f { float cell[3][3]; }; // neighbourhood cell array (SMS) -struct smscosts { int cost; array3x3f *effcosts; }; // cell costs for SMS +struct smscosts { int cost; array3x3f* effcosts; }; // cell costs for SMS // Landscape cell -class Cell{ +class Cell { public: Cell( // Constructor for habitat codes int, // x co-ordinate @@ -122,20 +122,20 @@ class Cell{ unsigned long int getVisits(void); private: - int x,y; // cell co-ordinates + int x, y; // cell co-ordinates intptr pPatch; // pointer (cast as integer) to the Patch to which cell belongs // NOTE: THE FOLLOWING ENVIRONMENTAL VARIABLES COULD BE COMBINED IN A STRUCTURE // AND ACCESSED BY A POINTER ... float envVal; // environmental value, representing one of: - // gradient in K, r or extinction probability + // gradient in K, r or extinction probability float envDev; // local environmental deviation (static, in range -1.0 to +1.0) float eps; // local environmental stochasticity (epsilon) (dynamic, from N(0,std)) unsigned long int visits; // no. of times square is visited by dispersers - smscosts *smsData; + smscosts* smsData; vector habIxx; // habitat indices (rasterType=0) - // NB initially, habitat codes are loaded, then converted to index nos. - // once landscape is fully loaded + // NB initially, habitat codes are loaded, then converted to index nos. + // once landscape is fully loaded vector habitats; // habitat proportions (rasterType=1) or quality (rasterType=2) }; @@ -143,7 +143,7 @@ class Cell{ // Initial species distribution cell -class DistCell{ +class DistCell { public: DistCell( int, // x co-ordinate @@ -160,7 +160,7 @@ class DistCell{ locn getLocn(void); private: - int x,y; // cell co-ordinates + int x, y; // cell co-ordinates bool initialise; // cell is to be initialised }; diff --git a/Community.cpp b/Community.cpp index 12b190c..222b97d 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Community.h" @@ -28,574 +28,574 @@ ofstream outrange; -ofstream outoccup,outsuit; +ofstream outoccup, outsuit; ofstream outtraitsrows; //--------------------------------------------------------------------------- -Community::Community(Landscape *pLand) { -pLandscape = pLand; -indIx = 0; +Community::Community(Landscape* pLand) { + pLandscape = pLand; + indIx = 0; } Community::~Community(void) { -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - delete subComms[i]; -} -subComms.clear(); + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + delete subComms[i]; + } + subComms.clear(); } -SubCommunity* Community::addSubComm(Patch *pPch,int num) { -int nsubcomms = (int)subComms.size(); -subComms.push_back(new SubCommunity(pPch,num)); -return subComms[nsubcomms]; +SubCommunity* Community::addSubComm(Patch* pPch, int num) { + int nsubcomms = (int)subComms.size(); + subComms.push_back(new SubCommunity(pPch, num)); + return subComms[nsubcomms]; } -void Community::initialise(Species *pSpecies,int year) +void Community::initialise(Species* pSpecies, int year) { -int nsubcomms,npatches,ndistcells,spratio,patchnum,rr = 0; -locn distloc; -patchData pch; -patchLimits limits; -intptr ppatch,subcomm; -std::vector subcomms; -std::vector selected; -SubCommunity *pSubComm; -Patch *pPatch; -Cell *pCell; -landParams ppLand = pLandscape->getLandParams(); -initParams init = paramsInit->getInit(); + int nsubcomms, npatches, ndistcells, spratio, patchnum, rr = 0; + locn distloc; + patchData pch; + patchLimits limits; + intptr ppatch, subcomm; + std::vector subcomms; + std::vector selected; + SubCommunity* pSubComm; + Patch* pPatch; + Cell* pCell; + landParams ppLand = pLandscape->getLandParams(); + initParams init = paramsInit->getInit(); -nsubcomms = (int)subComms.size(); + nsubcomms = (int)subComms.size(); -spratio = ppLand.spResol / ppLand.resol; + spratio = ppLand.spResol / ppLand.resol; #if RSDEBUG -DEBUGLOG << endl << "Community::initialise(): this=" << this - << " seedType=" << init.seedType << " freeType=" << init.freeType - << " minSeedX=" << init.minSeedX << " minSeedY=" << init.minSeedY - << " maxSeedX=" << init.maxSeedX << " maxSeedY=" << init.maxSeedY - << " indsFile=" << init.indsFile - << " nsubcomms=" << nsubcomms << " spratio=" << spratio - << endl; + DEBUGLOG << endl << "Community::initialise(): this=" << this + << " seedType=" << init.seedType << " freeType=" << init.freeType + << " minSeedX=" << init.minSeedX << " minSeedY=" << init.minSeedY + << " maxSeedX=" << init.maxSeedX << " maxSeedY=" << init.maxSeedY + << " indsFile=" << init.indsFile + << " nsubcomms=" << nsubcomms << " spratio=" << spratio + << endl; #endif -switch (init.seedType) { - -case 0: // free initialisation - - switch (init.freeType) { - - case 0: // random - // determine no. of patches / cells within the specified initialisation limits - // and record their corresponding sub-communities in a list - // parallel list records which have been selected - npatches = pLandscape->patchCount(); - limits.xMin = init.minSeedX; limits.xMax = init.maxSeedX; - limits.yMin = init.minSeedY; limits.yMax = init.maxSeedY; - for (int i = 0; i < npatches; i++) { - pch = pLandscape->getPatchData(i); - if (pch.pPatch->withinLimits(limits)) { - if (ppLand.patchModel) { - if (pch.pPatch->getPatchNum() != 0) { - subcomms.push_back(pch.pPatch->getSubComm()); - selected.push_back(false); + switch (init.seedType) { + + case 0: // free initialisation + + switch (init.freeType) { + + case 0: // random + // determine no. of patches / cells within the specified initialisation limits + // and record their corresponding sub-communities in a list + // parallel list records which have been selected + npatches = pLandscape->patchCount(); + limits.xMin = init.minSeedX; limits.xMax = init.maxSeedX; + limits.yMin = init.minSeedY; limits.yMax = init.maxSeedY; + for (int i = 0; i < npatches; i++) { + pch = pLandscape->getPatchData(i); + if (pch.pPatch->withinLimits(limits)) { + if (ppLand.patchModel) { + if (pch.pPatch->getPatchNum() != 0) { + subcomms.push_back(pch.pPatch->getSubComm()); + selected.push_back(false); + } } - } - else { // cell-based model - is cell(patch) suitable - if (pch.pPatch->getK() > 0.0) - { - subcomms.push_back(pch.pPatch->getSubComm()); - selected.push_back(false); + else { // cell-based model - is cell(patch) suitable + if (pch.pPatch->getK() > 0.0) + { + subcomms.push_back(pch.pPatch->getSubComm()); + selected.push_back(false); + } } } } - } - // select specified no. of patches/cells at random - npatches = (int)subcomms.size(); - if (init.nSeedPatches > npatches/2) { // use backwards selection method - for (int i = 0; i < npatches; i++) selected[i] = true; - for (int i = 0; i < (npatches-init.nSeedPatches); i++) { - do { - rr = pRandom->IRandom(0,npatches-1); - } while (!selected[rr]); - selected[rr] = false; + // select specified no. of patches/cells at random + npatches = (int)subcomms.size(); + if (init.nSeedPatches > npatches / 2) { // use backwards selection method + for (int i = 0; i < npatches; i++) selected[i] = true; + for (int i = 0; i < (npatches - init.nSeedPatches); i++) { + do { + rr = pRandom->IRandom(0, npatches - 1); + } while (!selected[rr]); + selected[rr] = false; + } } - } - else { // use forwards selection method - for (int i = 0; i < init.nSeedPatches; i++) { - do { - rr = pRandom->IRandom(0,npatches-1); - } while (selected[rr]); - selected[rr] = true; + else { // use forwards selection method + for (int i = 0; i < init.nSeedPatches; i++) { + do { + rr = pRandom->IRandom(0, npatches - 1); + } while (selected[rr]); + selected[rr] = true; + } } - } - // selected sub-communities for initialisation - for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->setInitial(false); - } - for (int i = 0; i < npatches; i++) { - if (selected[i]) { - pSubComm = (SubCommunity*)subcomms[i]; - pSubComm->setInitial(true); + // selected sub-communities for initialisation + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->setInitial(false); } - } - break; + for (int i = 0; i < npatches; i++) { + if (selected[i]) { + pSubComm = (SubCommunity*)subcomms[i]; + pSubComm->setInitial(true); + } + } + break; - case 1: // all suitable patches/cells - npatches = pLandscape->patchCount(); - limits.xMin = init.minSeedX; limits.xMax = init.maxSeedX; - limits.yMin = init.minSeedY; limits.yMax = init.maxSeedY; - for (int i = 0; i < npatches; i++) { - pch = pLandscape->getPatchData(i); - if (pch.pPatch->withinLimits(limits)) { - patchnum = pch.pPatch->getPatchNum(); - if (patchnum != 0) { - if (pch.pPatch->getK() > 0.0) - { // patch is suitable - subcomm = pch.pPatch->getSubComm(); - if (subcomm == 0) { - // create a sub-community in the patch - pSubComm = addSubComm(pch.pPatch,patchnum); - } - else { - pSubComm = (SubCommunity*)subcomm; + case 1: // all suitable patches/cells + npatches = pLandscape->patchCount(); + limits.xMin = init.minSeedX; limits.xMax = init.maxSeedX; + limits.yMin = init.minSeedY; limits.yMax = init.maxSeedY; + for (int i = 0; i < npatches; i++) { + pch = pLandscape->getPatchData(i); + if (pch.pPatch->withinLimits(limits)) { + patchnum = pch.pPatch->getPatchNum(); + if (patchnum != 0) { + if (pch.pPatch->getK() > 0.0) + { // patch is suitable + subcomm = pch.pPatch->getSubComm(); + if (subcomm == 0) { + // create a sub-community in the patch + pSubComm = addSubComm(pch.pPatch, patchnum); + } + else { + pSubComm = (SubCommunity*)subcomm; + } + pSubComm->setInitial(true); } - pSubComm->setInitial(true); } } } - } - - break; - case 2: // manually selected patches/cells - break; - - } // end of switch (init.freeType) - nsubcomms = (int)subComms.size(); - for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->initialise(pLandscape,pSpecies); - } - break; - -case 1: // from species distribution - if (ppLand.spDist) - { - // deselect all existing sub-communities - for (int i = 0; i < nsubcomms; i++) { - subComms[i]->setInitial(false); - } - // initialise from loaded species distribution - switch (init.spDistType) { - case 0: // all presence cells - pLandscape->setDistribution(pSpecies,0); // activate all patches - break; - case 1: // some randomly selected presence cells - pLandscape->setDistribution(pSpecies,init.nSpDistPatches); // activate random patches break; - case 2: // manually selected presence cells - // cells have already been identified - no further action here + + case 2: // manually selected patches/cells break; + + } // end of switch (init.freeType) + nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->initialise(pLandscape, pSpecies); } + break; - // THE FOLLOWING WILL HAVE TO BE CHANGED FOR MULTIPLE SPECIES... - ndistcells = pLandscape->distCellCount(0); - for (int i = 0; i < ndistcells; i++) { - distloc = pLandscape->getSelectedDistnCell(0,i); - if (distloc.x >= 0) { // distribution cell is selected - // process each landscape cell within the distribution cell - for (int x = 0; x < spratio; x++) { - for (int y = 0; y < spratio; y++) { - pCell = pLandscape->findCell(distloc.x*spratio+x,distloc.y*spratio+y); - if (pCell != 0) { // not a no-data cell - ppatch = pCell->getPatch(); - if (ppatch != 0) { - pPatch = (Patch*)ppatch; - if (pPatch->getSeqNum() != 0) { // not the matrix patch - subcomm = pPatch->getSubComm(); - if (subcomm != 0) { - pSubComm = (SubCommunity*)subcomm; - pSubComm->setInitial(true); - } - } + case 1: // from species distribution + if (ppLand.spDist) + { + // deselect all existing sub-communities + for (int i = 0; i < nsubcomms; i++) { + subComms[i]->setInitial(false); + } + // initialise from loaded species distribution + switch (init.spDistType) { + case 0: // all presence cells + pLandscape->setDistribution(pSpecies, 0); // activate all patches + break; + case 1: // some randomly selected presence cells + pLandscape->setDistribution(pSpecies, init.nSpDistPatches); // activate random patches + break; + case 2: // manually selected presence cells + // cells have already been identified - no further action here + break; + } + + // THE FOLLOWING WILL HAVE TO BE CHANGED FOR MULTIPLE SPECIES... + ndistcells = pLandscape->distCellCount(0); + for (int i = 0; i < ndistcells; i++) { + distloc = pLandscape->getSelectedDistnCell(0, i); + if (distloc.x >= 0) { // distribution cell is selected + // process each landscape cell within the distribution cell + for (int x = 0; x < spratio; x++) { + for (int y = 0; y < spratio; y++) { + pCell = pLandscape->findCell(distloc.x * spratio + x, distloc.y * spratio + y); + if (pCell != 0) { // not a no-data cell + ppatch = pCell->getPatch(); + if (ppatch != 0) { + pPatch = (Patch*)ppatch; + if (pPatch->getSeqNum() != 0) { // not the matrix patch + subcomm = pPatch->getSubComm(); + if (subcomm != 0) { + pSubComm = (SubCommunity*)subcomm; + pSubComm->setInitial(true); + } + } + } } } } } } + + nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->initialise(pLandscape, pSpecies); + } } - - nsubcomms = (int)subComms.size(); - for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->initialise(pLandscape,pSpecies); + else { + // WHAT HAPPENS IF INITIAL DISTRIBUTION IS NOT LOADED ??? .... + // should not occur - take no action - no initialisation will occur } - } - else { - // WHAT HAPPENS IF INITIAL DISTRIBUTION IS NOT LOADED ??? .... - // should not occur - take no action - no initialisation will occur - } - break; + break; -case 2: // initial individuals in specified patches/cells - if (year < 0) { - // initialise matrix sub-community only - subComms[0]->initialise(pLandscape,pSpecies); - indIx = 0; // reset index for initial individuals - } - else { // add any initial individuals for the current year - initInd iind; iind.year = 0; - int ninds = paramsInit->numInitInds(); - while (indIx < ninds && iind.year <= year) { - iind = paramsInit->getInitInd(indIx); - while (iind.year == year) { + case 2: // initial individuals in specified patches/cells + if (year < 0) { + // initialise matrix sub-community only + subComms[0]->initialise(pLandscape, pSpecies); + indIx = 0; // reset index for initial individuals + } + else { // add any initial individuals for the current year + initInd iind; iind.year = 0; + int ninds = paramsInit->numInitInds(); + while (indIx < ninds && iind.year <= year) { + iind = paramsInit->getInitInd(indIx); + while (iind.year == year) { #if RSDEBUG -//DEBUGLOG << "Community::initialise(): year=" << year -// << " indIx=" << indIx << " iind.year=" << iind.year -// << " iind.patchID=" << iind.patchID << " iind.x=" << iind.x << " iind.y=" << iind.y -// << " iind.sex=" << iind.sex << " iind.age=" << iind.age << " iind.stage=" << iind.stage -// << endl; + //DEBUGLOG << "Community::initialise(): year=" << year + // << " indIx=" << indIx << " iind.year=" << iind.year + // << " iind.patchID=" << iind.patchID << " iind.x=" << iind.x << " iind.y=" << iind.y + // << " iind.sex=" << iind.sex << " iind.age=" << iind.age << " iind.stage=" << iind.stage + // << endl; #endif - if (ppLand.patchModel) { - if (pLandscape->existsPatch(iind.patchID)) { - pPatch = pLandscape->findPatch(iind.patchID); - if (pPatch->getK() > 0.0) - { // patch is suitable - subcomm = pPatch->getSubComm(); - if (subcomm == 0) { - // create a sub-community in the patch - pSubComm = addSubComm(pPatch,iind.patchID); - } - else { - pSubComm = (SubCommunity*)subcomm; - } - pSubComm->initialInd(pLandscape,pSpecies,pPatch,pPatch->getRandomCell(),indIx); - } - } - } - else { // cell-based model - pCell = pLandscape->findCell(iind.x,iind.y); - if (pCell != 0) { - intptr ppatch = pCell->getPatch(); - if (ppatch != 0) { - pPatch = (Patch*)ppatch; - if (pPatch->getK() > 0.0) + if (ppLand.patchModel) { + if (pLandscape->existsPatch(iind.patchID)) { + pPatch = pLandscape->findPatch(iind.patchID); + if (pPatch->getK() > 0.0) { // patch is suitable subcomm = pPatch->getSubComm(); if (subcomm == 0) { // create a sub-community in the patch - pSubComm = addSubComm(pPatch,iind.patchID); + pSubComm = addSubComm(pPatch, iind.patchID); } else { pSubComm = (SubCommunity*)subcomm; } - pSubComm->initialInd(pLandscape,pSpecies,pPatch,pCell,indIx); + pSubComm->initialInd(pLandscape, pSpecies, pPatch, pPatch->getRandomCell(), indIx); } } } - } - indIx++; - if (indIx < ninds) { - iind = paramsInit->getInitInd(indIx); - } - else { - iind.year = 99999999; + else { // cell-based model + pCell = pLandscape->findCell(iind.x, iind.y); + if (pCell != 0) { + intptr ppatch = pCell->getPatch(); + if (ppatch != 0) { + pPatch = (Patch*)ppatch; + if (pPatch->getK() > 0.0) + { // patch is suitable + subcomm = pPatch->getSubComm(); + if (subcomm == 0) { + // create a sub-community in the patch + pSubComm = addSubComm(pPatch, iind.patchID); + } + else { + pSubComm = (SubCommunity*)subcomm; + } + pSubComm->initialInd(pLandscape, pSpecies, pPatch, pCell, indIx); + } + } + } + } + indIx++; + if (indIx < ninds) { + iind = paramsInit->getInitInd(indIx); + } + else { + iind.year = 99999999; + } } } } - } - break; + break; -case 3: // from file - // this condition cannot occur here, as init.seedType will have been changed to 0 or 1 - // when the initialisation file was read - break; + case 3: // from file + // this condition cannot occur here, as init.seedType will have been changed to 0 or 1 + // when the initialisation file was read + break; -} // end of switch (init.seedType) + } // end of switch (init.seedType) #if RSDEBUG -DEBUGLOG << "Community::initialise(): this=" << this - << " nsubcomms=" << nsubcomms - << endl; + DEBUGLOG << "Community::initialise(): this=" << this + << " nsubcomms=" << nsubcomms + << endl; #endif } // Add manually selected patches/cells to the selected set for initialisation void Community::addManuallySelected(void) { -int npatches; -intptr subcomm,patch; -locn initloc; -Cell *pCell; -Patch *pPatch; -SubCommunity *pSubComm; + int npatches; + intptr subcomm, patch; + locn initloc; + Cell* pCell; + Patch* pPatch; + SubCommunity* pSubComm; -landParams ppLand = pLandscape->getLandParams(); + landParams ppLand = pLandscape->getLandParams(); -npatches = pLandscape->initCellCount(); // no. of patches/cells specified + npatches = pLandscape->initCellCount(); // no. of patches/cells specified #if RSDEBUG -DEBUGLOG << "Community::addManuallySelected(): this = " << this - << " npatches = " << npatches << endl; + DEBUGLOG << "Community::addManuallySelected(): this = " << this + << " npatches = " << npatches << endl; #endif -// identify sub-communities to be initialised -if (ppLand.patchModel) { - for (int i = 0; i < npatches; i++) { - initloc = pLandscape->getInitCell(i); // patch number held in x-coord of list - pPatch = pLandscape->findPatch(initloc.x); - if (pPatch != 0) { - subcomm = pPatch->getSubComm(); - if (subcomm != 0) { - pSubComm = (SubCommunity*)subcomm; - pSubComm->setInitial(true); + // identify sub-communities to be initialised + if (ppLand.patchModel) { + for (int i = 0; i < npatches; i++) { + initloc = pLandscape->getInitCell(i); // patch number held in x-coord of list + pPatch = pLandscape->findPatch(initloc.x); + if (pPatch != 0) { + subcomm = pPatch->getSubComm(); + if (subcomm != 0) { + pSubComm = (SubCommunity*)subcomm; + pSubComm->setInitial(true); + } } } } -} -else { // cell-based model - for (int i = 0; i < npatches; i++) { - initloc = pLandscape->getInitCell(i); - if (initloc.x >= 0 && initloc.x < ppLand.dimX - && initloc.y >= 0 && initloc.y < ppLand.dimY) { - pCell = pLandscape->findCell(initloc.x,initloc.y); - if (pCell != 0) { // not no-data cell - patch = pCell->getPatch(); + else { // cell-based model + for (int i = 0; i < npatches; i++) { + initloc = pLandscape->getInitCell(i); + if (initloc.x >= 0 && initloc.x < ppLand.dimX + && initloc.y >= 0 && initloc.y < ppLand.dimY) { + pCell = pLandscape->findCell(initloc.x, initloc.y); + if (pCell != 0) { // not no-data cell + patch = pCell->getPatch(); #if RSDEBUG -DEBUGLOG << "Community::initialise(): i = " << i - << " x = " << initloc.x << " y = " << initloc.y - << " pCell = " << pCell << " patch = " << patch - << endl; + DEBUGLOG << "Community::initialise(): i = " << i + << " x = " << initloc.x << " y = " << initloc.y + << " pCell = " << pCell << " patch = " << patch + << endl; #endif - if (patch != 0) { - pPatch = (Patch*)patch; - subcomm = pPatch->getSubComm(); + if (patch != 0) { + pPatch = (Patch*)patch; + subcomm = pPatch->getSubComm(); #if RSDEBUG -DEBUGLOG << "Community::initialise(): i = " << i - << " pPatch = " << pPatch << " subcomm = " << subcomm - << endl; + DEBUGLOG << "Community::initialise(): i = " << i + << " pPatch = " << pPatch << " subcomm = " << subcomm + << endl; #endif - if (subcomm != 0) { - pSubComm = (SubCommunity*)subcomm; - pSubComm->setInitial(true); + if (subcomm != 0) { + pSubComm = (SubCommunity*)subcomm; + pSubComm->setInitial(true); #if RSDEBUG -DEBUGLOG << "Community::initialise(): i = " << i - << " pSubComm = " << pSubComm - << endl; + DEBUGLOG << "Community::initialise(): i = " << i + << " pSubComm = " << pSubComm + << endl; #endif + } } } } } } } -} void Community::resetPopns(void) { -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->resetPopns(); -} -// reset the individual ids to start from zero -Individual::indCounter = 0; + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->resetPopns(); + } + // reset the individual ids to start from zero + Individual::indCounter = 0; } void Community::localExtinction(int option) { -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - if (subComms[i]->getNum() > 0) { // except in matrix - subComms[i]->localExtinction(option); + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + if (subComms[i]->getNum() > 0) { // except in matrix + subComms[i]->localExtinction(option); + } } } -} void Community::patchChanges(void) { -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - if (subComms[i]->getNum() > 0) { // except in matrix - subComms[i]->patchChange(); + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + if (subComms[i]->getNum() > 0) { // except in matrix + subComms[i]->patchChange(); + } } } -} void Community::reproduction(int yr) { -float eps = 0.0; // epsilon for environmental stochasticity -landParams land = pLandscape->getLandParams(); -envStochParams env = paramsStoch->getStoch(); -int nsubcomms = (int)subComms.size(); + float eps = 0.0; // epsilon for environmental stochasticity + landParams land = pLandscape->getLandParams(); + envStochParams env = paramsStoch->getStoch(); + int nsubcomms = (int)subComms.size(); #if RSDEBUG -DEBUGLOG << "Community::reproduction(): this=" << this - << " nsubcomms=" << nsubcomms << endl; + DEBUGLOG << "Community::reproduction(): this=" << this + << " nsubcomms=" << nsubcomms << endl; #endif -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - if (env.stoch) { - if (!env.local) { // global stochasticty - eps = pLandscape->getGlobalStoch(yr); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + if (env.stoch) { + if (!env.local) { // global stochasticty + eps = pLandscape->getGlobalStoch(yr); + } } + subComms[i]->reproduction(land.resol, eps, land.rasterType, land.patchModel); } - subComms[i]->reproduction(land.resol,eps,land.rasterType,land.patchModel); -} #if RSDEBUG -DEBUGLOG << "Community::reproduction(): finished" << endl; + DEBUGLOG << "Community::reproduction(): finished" << endl; #endif } -void Community::emigration(void) +void Community::emigration(void) { -int nsubcomms = (int)subComms.size(); + int nsubcomms = (int)subComms.size(); #if RSDEBUG -DEBUGLOG << "Community::emigration(): this=" << this - << " nsubcomms=" << nsubcomms << endl; + DEBUGLOG << "Community::emigration(): this=" << this + << " nsubcomms=" << nsubcomms << endl; #endif -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->emigration(); -} + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->emigration(); + } #if RSDEBUG -DEBUGLOG << "Community::emigration(): finished" << endl; + DEBUGLOG << "Community::emigration(): finished" << endl; #endif } #if RS_RCPP // included also SEASONAL -void Community::dispersal(short landIx,short nextseason) +void Community::dispersal(short landIx, short nextseason) #else void Community::dispersal(short landIx) #endif // SEASONAL || RS_RCPP { #if RSDEBUG -int t0,t1,t2; -t0 = time(0); + int t0, t1, t2; + t0 = time(0); #endif -simParams sim = paramsSim->getSim(); + simParams sim = paramsSim->getSim(); -int nsubcomms = (int)subComms.size(); -// initiate dispersal - all emigrants leave their natal community and join matrix community -SubCommunity *matrix = subComms[0]; // matrix community is always the first -for (int i = 0; i < nsubcomms; i++) { // all populations - subComms[i]->initiateDispersal(matrix); -} + int nsubcomms = (int)subComms.size(); + // initiate dispersal - all emigrants leave their natal community and join matrix community + SubCommunity* matrix = subComms[0]; // matrix community is always the first + for (int i = 0; i < nsubcomms; i++) { // all populations + subComms[i]->initiateDispersal(matrix); + } #if RSDEBUG -t1 = time(0); -DEBUGLOG << "Community::dispersal(): this=" << this - << " nsubcomms=" << nsubcomms << " initiation time=" << t1-t0 << endl; + t1 = time(0); + DEBUGLOG << "Community::dispersal(): this=" << this + << " nsubcomms=" << nsubcomms << " initiation time=" << t1 - t0 << endl; #endif -// dispersal is undertaken by all individuals now in the matrix patch -// (even if not physically in the matrix) -int ndispersers = 0; -do { - for (int i = 0; i < nsubcomms; i++) { // all populations - subComms[i]->resetPossSettlers(); - } + // dispersal is undertaken by all individuals now in the matrix patch + // (even if not physically in the matrix) + int ndispersers = 0; + do { + for (int i = 0; i < nsubcomms; i++) { // all populations + subComms[i]->resetPossSettlers(); + } #if RSDEBUG -//DEBUGLOG << "Community::dispersal() 1111: ndispersers=" << ndispersers << endl; + //DEBUGLOG << "Community::dispersal() 1111: ndispersers=" << ndispersers << endl; #endif #if RS_RCPP // included also SEASONAL - ndispersers = matrix->transfer(pLandscape,landIx,nextseason); + ndispersers = matrix->transfer(pLandscape, landIx, nextseason); #else - ndispersers = matrix->transfer(pLandscape,landIx); + ndispersers = matrix->transfer(pLandscape, landIx); #endif // SEASONAL || RS_RCPP #if RSDEBUG -//DEBUGLOG << "Community::dispersal() 2222: ndispersers=" << ndispersers << endl; + //DEBUGLOG << "Community::dispersal() 2222: ndispersers=" << ndispersers << endl; #endif - matrix->completeDispersal(pLandscape,sim.outConnect); + matrix->completeDispersal(pLandscape, sim.outConnect); #if RSDEBUG -//DEBUGLOG << "Community::dispersal() 3333: ndispersers=" << ndispersers << endl; + //DEBUGLOG << "Community::dispersal() 3333: ndispersers=" << ndispersers << endl; #endif -} while (ndispersers > 0); + } while (ndispersers > 0); #if RSDEBUG -DEBUGLOG << "Community::dispersal(): matrix=" << matrix << endl; -t2 = time(0); -DEBUGLOG << "Community::dispersal(): transfer time=" << t2-t1 << endl; + DEBUGLOG << "Community::dispersal(): matrix=" << matrix << endl; + t2 = time(0); + DEBUGLOG << "Community::dispersal(): transfer time=" << t2 - t1 << endl; #endif #if RSDEBUG -//int t3 = time(0); -//DEBUGLOG << "Community::dispersal(): completion time = " << t3-t2 << endl; + //int t3 = time(0); + //DEBUGLOG << "Community::dispersal(): completion time = " << t3-t2 << endl; #endif } -void Community::survival(short part,short option0,short option1) +void Community::survival(short part, short option0, short option1) { -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all communities (including in matrix) - subComms[i]->survival(part,option0,option1); -} + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all communities (including in matrix) + subComms[i]->survival(part, option0, option1); + } } void Community::ageIncrement(void) { -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all communities (including in matrix) - subComms[i]->ageIncrement(); -} + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all communities (including in matrix) + subComms[i]->ageIncrement(); + } } // Calculate total no. of individuals of all species int Community::totalInds(void) { -popStats p; -int total = 0; -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all communities (including in matrix) - p = subComms[i]->getPopStats(); - total += p.nInds; -} -return total; + popStats p; + int total = 0; + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all communities (including in matrix) + p = subComms[i]->getPopStats(); + total += p.nInds; + } + return total; } // Find the population of a given species in a given patch -Population* Community::findPop(Species *pSp,Patch *pPch) { -Population *pPop = 0; -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all communities (including in matrix) - pPop = subComms[i]->findPop(pSp,pPch); - if (pPop != 0) break; -} -return pPop; +Population* Community::findPop(Species* pSp, Patch* pPch) { + Population* pPop = 0; + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all communities (including in matrix) + pPop = subComms[i]->findPop(pSp, pPch); + if (pPop != 0) break; + } + return pPop; } //--------------------------------------------------------------------------- -void Community::createOccupancy(int nrows,int reps) { -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { - subComms[i]->createOccupancy(nrows); -} -// Initialise array for occupancy of suitable cells/patches -occSuit = new float *[nrows]; -for (int i = 0; i < nrows; i++) -{ - occSuit[i] = new float[reps]; - for (int ii = 0; ii < reps; ii++) occSuit[i][ii] = 0.0; -} +void Community::createOccupancy(int nrows, int reps) { + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { + subComms[i]->createOccupancy(nrows); + } + // Initialise array for occupancy of suitable cells/patches + occSuit = new float* [nrows]; + for (int i = 0; i < nrows; i++) + { + occSuit[i] = new float[reps]; + for (int ii = 0; ii < reps; ii++) occSuit[i][ii] = 0.0; + } } -void Community::updateOccupancy(int row,int rep) +void Community::updateOccupancy(int row, int rep) { #if RSDEBUG -DEBUGLOG << "Community::updateOccupancy(): row=" << row << endl; + DEBUGLOG << "Community::updateOccupancy(): row=" << row << endl; #endif -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { - subComms[i]->updateOccupancy(row); -} + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { + subComms[i]->updateOccupancy(row); + } -commStats s = getStats(); -occSuit[row][rep] = (float)s.occupied / (float)s.suitable; + commStats s = getStats(); + occSuit[row][rep] = (float)s.occupied / (float)s.suitable; } void Community::deleteOccupancy(int nrows) { -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { - subComms[i]->deleteOccupancy(); -} + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { + subComms[i]->deleteOccupancy(); + } -for(int i = 0; i < nrows; i++) - delete[] occSuit[i]; -delete[] occSuit; + for (int i = 0; i < nrows; i++) + delete[] occSuit[i]; + delete[] occSuit; } @@ -604,49 +604,49 @@ delete[] occSuit; // Determine range margins commStats Community::getStats(void) { -commStats s; -landParams ppLand = pLandscape->getLandParams(); -s.ninds = s.nnonjuvs = s.suitable = s.occupied = 0; -s.minX = ppLand.maxX; s.minY = ppLand.maxY; s.maxX = s.maxY = 0; -float localK; -popStats patchPop; -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - patchPop = subComms[i]->getPopStats(); - s.ninds += patchPop.nInds; - s.nnonjuvs += patchPop.nNonJuvs; + commStats s; + landParams ppLand = pLandscape->getLandParams(); + s.ninds = s.nnonjuvs = s.suitable = s.occupied = 0; + s.minX = ppLand.maxX; s.minY = ppLand.maxY; s.maxX = s.maxY = 0; + float localK; + popStats patchPop; + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + patchPop = subComms[i]->getPopStats(); + s.ninds += patchPop.nInds; + s.nnonjuvs += patchPop.nNonJuvs; #if RSDEBUG -//DEBUGLOG << "Community::getStats(): i = " << i -// << " pSpecies = " << patchPop.pSpecies << " pPatch = " << patchPop.pPatch -// << " nInds = " << patchPop.nInds << endl; + //DEBUGLOG << "Community::getStats(): i = " << i + // << " pSpecies = " << patchPop.pSpecies << " pPatch = " << patchPop.pPatch + // << " nInds = " << patchPop.nInds << endl; #endif - if (patchPop.pPatch != 0) { // not the matrix patch + if (patchPop.pPatch != 0) { // not the matrix patch #if RSDEBUG -//DEBUGLOG << "Community::getStats(): i = " << i -// << " patchNum = " << patchPop.pPatch->getPatchNum() << endl; + //DEBUGLOG << "Community::getStats(): i = " << i + // << " patchNum = " << patchPop.pPatch->getPatchNum() << endl; #endif - if (patchPop.pPatch->getPatchNum() != 0) { // not matrix patch - localK = patchPop.pPatch->getK(); + if (patchPop.pPatch->getPatchNum() != 0) { // not matrix patch + localK = patchPop.pPatch->getK(); #if RSDEBUG -//DEBUGLOG << "Community::getStats(): i= " << i -// << " pSpecies= " << patchPop.pSpecies << " pPatch= " << patchPop.pPatch -// << " patchNum= " << patchPop.pPatch->getPatchNum() << " localK= " << localK -// << " nInds= " << patchPop.nInds << " breeding= " << (int)patchPop.breeding -// << endl; + //DEBUGLOG << "Community::getStats(): i= " << i + // << " pSpecies= " << patchPop.pSpecies << " pPatch= " << patchPop.pPatch + // << " patchNum= " << patchPop.pPatch->getPatchNum() << " localK= " << localK + // << " nInds= " << patchPop.nInds << " breeding= " << (int)patchPop.breeding + // << endl; #endif - if (localK > 0.0) s.suitable++; - if (patchPop.nInds > 0 && patchPop.breeding) { - s.occupied++; - patchLimits pchlim = patchPop.pPatch->getLimits(); - if (pchlim.xMin < s.minX) s.minX = pchlim.xMin; - if (pchlim.xMax > s.maxX) s.maxX = pchlim.xMax; - if (pchlim.yMin < s.minY) s.minY = pchlim.yMin; - if (pchlim.yMax > s.maxY) s.maxY = pchlim.yMax; + if (localK > 0.0) s.suitable++; + if (patchPop.nInds > 0 && patchPop.breeding) { + s.occupied++; + patchLimits pchlim = patchPop.pPatch->getLimits(); + if (pchlim.xMin < s.minX) s.minX = pchlim.xMin; + if (pchlim.xMax > s.maxX) s.maxX = pchlim.xMax; + if (pchlim.yMin < s.minY) s.minY = pchlim.yMin; + if (pchlim.yMax > s.maxY) s.maxY = pchlim.yMax; + } } } } -} -return s; + return s; } //--------------------------------------------------------------------------- @@ -654,650 +654,650 @@ return s; // Functions to control production of output files // Open population file and write header record -bool Community::outPopHeaders(Species *pSpecies,int option) { -return subComms[0]->outPopHeaders(pLandscape,pSpecies,option); +bool Community::outPopHeaders(Species* pSpecies, int option) { + return subComms[0]->outPopHeaders(pLandscape, pSpecies, option); } // Write records to population file -void Community::outPop(int rep,int yr,int gen) +void Community::outPop(int rep, int yr, int gen) { -// generate output for each sub-community (patch) in the community -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->outPop(pLandscape,rep,yr,gen); -} + // generate output for each sub-community (patch) in the community + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->outPop(pLandscape, rep, yr, gen); + } } // Write records to individuals file -void Community::outInds(int rep, int yr, int gen,int landNr) { +void Community::outInds(int rep, int yr, int gen, int landNr) { -if (landNr >= 0) { // open the file - subComms[0]->outInds(pLandscape,rep,yr,gen,landNr); - return; -} -if (landNr == -999) { // close the file - subComms[0]->outInds(pLandscape,rep,yr,gen,-999); - return; -} -// generate output for each sub-community (patch) in the community -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->outInds(pLandscape,rep,yr,gen,landNr); -} + if (landNr >= 0) { // open the file + subComms[0]->outInds(pLandscape, rep, yr, gen, landNr); + return; + } + if (landNr == -999) { // close the file + subComms[0]->outInds(pLandscape, rep, yr, gen, -999); + return; + } + // generate output for each sub-community (patch) in the community + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->outInds(pLandscape, rep, yr, gen, landNr); + } } // Write records to genetics file -void Community::outGenetics(int rep, int yr, int gen,int landNr) { -//landParams ppLand = pLandscape->getLandParams(); -if (landNr >= 0) { // open the file - subComms[0]->outGenetics(rep,yr,gen,landNr); - return; -} -if (landNr == -999) { // close the file - subComms[0]->outGenetics(rep,yr,gen,landNr); - return; -} -// generate output for each sub-community (patch) in the community -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->outGenetics(rep,yr,gen,landNr); -} +void Community::outGenetics(int rep, int yr, int gen, int landNr) { + //landParams ppLand = pLandscape->getLandParams(); + if (landNr >= 0) { // open the file + subComms[0]->outGenetics(rep, yr, gen, landNr); + return; + } + if (landNr == -999) { // close the file + subComms[0]->outGenetics(rep, yr, gen, landNr); + return; + } + // generate output for each sub-community (patch) in the community + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->outGenetics(rep, yr, gen, landNr); + } } // Open range file and write header record -bool Community::outRangeHeaders(Species *pSpecies,int landNr) +bool Community::outRangeHeaders(Species* pSpecies, int landNr) { -if (landNr == -999) { // close the file - if (outrange.is_open()) outrange.close(); - outrange.clear(); - return true; -} + if (landNr == -999) { // close the file + if (outrange.is_open()) outrange.close(); + outrange.clear(); + return true; + } -string name; -landParams ppLand = pLandscape->getLandParams(); -envStochParams env = paramsStoch->getStoch(); -simParams sim = paramsSim->getSim(); + string name; + landParams ppLand = pLandscape->getLandParams(); + envStochParams env = paramsStoch->getStoch(); + simParams sim = paramsSim->getSim(); -// NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER -// ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); + // NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER + // ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); #if RSDEBUG -DEBUGLOG << "Community::outRangeHeaders(): simulation=" << sim.simulation - << " sim.batchMode=" << sim.batchMode - << " landNr=" << landNr << endl; + DEBUGLOG << "Community::outRangeHeaders(): simulation=" << sim.simulation + << " sim.batchMode=" << sim.batchMode + << " landNr=" << landNr << endl; #endif -if (sim.batchMode) { - name = paramsSim->getDir(2) + if (sim.batchMode) { + name = paramsSim->getDir(2) #if RS_RCPP - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" - + Int2Str(landNr) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + "_Land" + + Int2Str(landNr) #else - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" - + Int2Str(landNr) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + "_Land" + + Int2Str(landNr) #endif - + "_Range.txt"; -} -else { - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Range.txt"; -} -outrange.open(name.c_str()); -outrange << "Rep\tYear\tRepSeason"; -if (env.stoch && !env.local) outrange << "\tEpsilon"; - -outrange << "\tNInds"; -if (dem.stageStruct) { - for (int i = 1; i < sstruct.nStages; i++) outrange << "\tNInd_stage" << i; - outrange << "\tNJuvs"; -} -if (ppLand.patchModel) outrange << "\tNOccupPatches"; -else outrange << "\tNOccupCells"; -outrange << "\tOccup/Suit\tmin_X\tmax_X\tmin_Y\tmax_Y"; - -if (emig.indVar) { - if (emig.sexDep) { - if (emig.densDep) { - outrange << "\tF_meanD0\tF_stdD0\tM_meanD0\tM_stdD0"; - outrange << "\tF_meanAlpha\tF_stdAlpha\tM_meanAlpha\tM_stdAlpha"; - outrange << "\tF_meanBeta\tF_stdBeta\tM_meanBeta\tM_stdBeta"; - } - else { - outrange << "\tF_meanEP\tF_stdEP\tM_meanEP\tM_stdEP"; - } + + "_Range.txt"; } else { - if (emig.densDep) { - outrange << "\tmeanD0\tstdD0\tmeanAlpha\tstdAlpha"; - outrange << "\tmeanBeta\tstdBeta"; + name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Range.txt"; + } + outrange.open(name.c_str()); + outrange << "Rep\tYear\tRepSeason"; + if (env.stoch && !env.local) outrange << "\tEpsilon"; + + outrange << "\tNInds"; + if (dem.stageStruct) { + for (int i = 1; i < sstruct.nStages; i++) outrange << "\tNInd_stage" << i; + outrange << "\tNJuvs"; + } + if (ppLand.patchModel) outrange << "\tNOccupPatches"; + else outrange << "\tNOccupCells"; + outrange << "\tOccup/Suit\tmin_X\tmax_X\tmin_Y\tmax_Y"; + + if (emig.indVar) { + if (emig.sexDep) { + if (emig.densDep) { + outrange << "\tF_meanD0\tF_stdD0\tM_meanD0\tM_stdD0"; + outrange << "\tF_meanAlpha\tF_stdAlpha\tM_meanAlpha\tM_stdAlpha"; + outrange << "\tF_meanBeta\tF_stdBeta\tM_meanBeta\tM_stdBeta"; + } + else { + outrange << "\tF_meanEP\tF_stdEP\tM_meanEP\tM_stdEP"; + } } else { - outrange << "\tmeanEP\tstdEP"; + if (emig.densDep) { + outrange << "\tmeanD0\tstdD0\tmeanAlpha\tstdAlpha"; + outrange << "\tmeanBeta\tstdBeta"; + } + else { + outrange << "\tmeanEP\tstdEP"; + } } } -} -if (trfr.indVar) { - if (trfr.moveModel) { - if (trfr.moveType == 1) { - outrange << "\tmeanDP\tstdDP\tmeanGB\tstdGB"; + if (trfr.indVar) { + if (trfr.moveModel) { + if (trfr.moveType == 1) { + outrange << "\tmeanDP\tstdDP\tmeanGB\tstdGB"; outrange << "\tmeanAlphaDB\tstdAlphaDB\tmeanBetaDB\tstdBetaDB"; + } + if (trfr.moveType == 2) { + outrange << "\tmeanStepLength\tstdStepLength\tmeanRho\tstdRho"; + } } - if (trfr.moveType == 2) { - outrange << "\tmeanStepLength\tstdStepLength\tmeanRho\tstdRho"; - } - } - else { - if (trfr.sexDep) { - outrange << "\tF_mean_distI\tF_std_distI\tM_mean_distI\tM_std_distI"; - if (trfr.twinKern) - outrange << "\tF_mean_distII\tF_std_distII\tM_mean_distII\tM_std_distII" + else { + if (trfr.sexDep) { + outrange << "\tF_mean_distI\tF_std_distI\tM_mean_distI\tM_std_distI"; + if (trfr.twinKern) + outrange << "\tF_mean_distII\tF_std_distII\tM_mean_distII\tM_std_distII" << "\tF_meanPfirstKernel\tF_stdPfirstKernel" << "\tM_meanPfirstKernel\tM_stdPfirstKernel"; - } - else { - outrange << "\tmean_distI\tstd_distI"; - if (trfr.twinKern) - outrange << "\tmean_distII\tstd_distII\tmeanPfirstKernel\tstdPfirstKernel"; + } + else { + outrange << "\tmean_distI\tstd_distI"; + if (trfr.twinKern) + outrange << "\tmean_distII\tstd_distII\tmeanPfirstKernel\tstdPfirstKernel"; + } } } -} -if (sett.indVar) { - if (sett.sexDep) { - outrange << "\tF_meanS0\tF_stdS0\tM_meanS0\tM_stdS0"; - outrange << "\tF_meanAlphaS\tF_stdAlphaS\tM_meanAlphaS\tM_stdAlphaS"; - outrange << "\tF_meanBetaS\tF_stdBetaS\tM_meanBetaS\tM_stdBetaS"; + if (sett.indVar) { + if (sett.sexDep) { + outrange << "\tF_meanS0\tF_stdS0\tM_meanS0\tM_stdS0"; + outrange << "\tF_meanAlphaS\tF_stdAlphaS\tM_meanAlphaS\tM_stdAlphaS"; + outrange << "\tF_meanBetaS\tF_stdBetaS\tM_meanBetaS\tM_stdBetaS"; + } + else { + outrange << "\tmeanS0\tstdS0"; + outrange << "\tmeanAlphaS\tstdAlphaS"; + outrange << "\tmeanBetaS\tstdBetaS"; + } } - else { - outrange << "\tmeanS0\tstdS0"; - outrange << "\tmeanAlphaS\tstdAlphaS"; - outrange << "\tmeanBetaS\tstdBetaS"; - } -} -outrange << endl; + outrange << endl; #if RSDEBUG -DEBUGLOG << "Community::outRangeHeaders(): finished" << endl; + DEBUGLOG << "Community::outRangeHeaders(): finished" << endl; #endif -return outrange.is_open(); + return outrange.is_open(); } // Write record to range file -void Community::outRange(Species *pSpecies,int rep,int yr,int gen) +void Community::outRange(Species* pSpecies, int rep, int yr, int gen) { #if RSDEBUG -DEBUGLOG << "Community::outRange(): rep=" << rep - << " yr=" << yr << " gen=" << gen << endl; + DEBUGLOG << "Community::outRange(): rep=" << rep + << " yr=" << yr << " gen=" << gen << endl; #endif -landParams ppLand = pLandscape->getLandParams(); -envStochParams env = paramsStoch->getStoch(); - -// NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER -// ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); - -outrange << rep << "\t" << yr << "\t" << gen; -if (env.stoch && !env.local) // write global environmental stochasticity - outrange << "\t" << pLandscape->getGlobalStoch(yr); - -commStats s = getStats(); - -if (dem.stageStruct) { - outrange << "\t" << s.nnonjuvs; - int stagepop; - int nsubcomms = (int)subComms.size(); - // all non-juvenile stages - for (int stg = 1; stg < sstruct.nStages; stg++) { + landParams ppLand = pLandscape->getLandParams(); + envStochParams env = paramsStoch->getStoch(); + + // NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER + // ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + + outrange << rep << "\t" << yr << "\t" << gen; + if (env.stoch && !env.local) // write global environmental stochasticity + outrange << "\t" << pLandscape->getGlobalStoch(yr); + + commStats s = getStats(); + + if (dem.stageStruct) { + outrange << "\t" << s.nnonjuvs; + int stagepop; + int nsubcomms = (int)subComms.size(); + // all non-juvenile stages + for (int stg = 1; stg < sstruct.nStages; stg++) { + stagepop = 0; + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + stagepop += subComms[i]->stagePop(stg); + } + outrange << "\t" << stagepop; + } + // juveniles born in current reproductive season stagepop = 0; for (int i = 0; i < nsubcomms; i++) { // all sub-communities - stagepop += subComms[i]->stagePop(stg); + stagepop += subComms[i]->stagePop(0); } - outrange <<"\t" << stagepop; + outrange << "\t" << stagepop; } - // juveniles born in current reproductive season - stagepop = 0; - for (int i = 0; i < nsubcomms; i++) { // all sub-communities - stagepop += subComms[i]->stagePop(0); + else { // non-structured species + outrange << "\t" << s.ninds; } - outrange <<"\t" << stagepop; -} -else { // non-structured species - outrange << "\t" << s.ninds; -} -float occsuit = 0.0; -if (s.suitable > 0) occsuit = (float)s.occupied / (float)s.suitable; -outrange << "\t" << s.occupied << "\t" << occsuit; -// RANGE MINIMA AND MAXIMA NEED TO BECOME A PROPERTY OF THE SPECIES -if (s.ninds > 0) { - landOrigin origin = pLandscape->getOrigin(); - outrange << "\t" << (float)s.minX * (float)ppLand.resol + origin.minEast - << "\t" << (float)(s.maxX+1) * (float)ppLand.resol + origin.minEast - << "\t" << (float)s.minY * (float)ppLand.resol + origin.minNorth - << "\t" << (float)(s.maxY+1) * (float)ppLand.resol + origin.minNorth; -} -else - outrange <<"\t0\t0\t0\t0"; - -if (emig.indVar || trfr.indVar || sett.indVar) { // output trait means - traitsums ts; - traitsums scts; // sub-community traits - traitCanvas tcanv; - int ngenes,popsize; - - tcanv.pcanvas[0] = NULL; - - for (int i = 0; i < NSEXES; i++) { - ts.ninds[i] = 0; - ts.sumD0[i] = ts.ssqD0[i] = 0.0; - ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; - ts.sumDist1[i] = ts.ssqDist1[i] = 0.0; ts.sumDist2[i] = ts.ssqDist2[i] = 0.0; - ts.sumProp1[i] = ts.ssqProp1[i] = 0.0; - ts.sumDP[i] = ts.ssqDP[i] = 0.0; - ts.sumGB[i] = ts.ssqGB[i] = 0.0; - ts.sumAlphaDB[i] = ts.ssqAlphaDB[i] = 0.0; - ts.sumBetaDB[i] = ts.ssqBetaDB[i] = 0.0; - ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; - ts.sumS0[i] = ts.ssqS0[i] = 0.0; - ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; + float occsuit = 0.0; + if (s.suitable > 0) occsuit = (float)s.occupied / (float)s.suitable; + outrange << "\t" << s.occupied << "\t" << occsuit; + // RANGE MINIMA AND MAXIMA NEED TO BECOME A PROPERTY OF THE SPECIES + if (s.ninds > 0) { + landOrigin origin = pLandscape->getOrigin(); + outrange << "\t" << (float)s.minX * (float)ppLand.resol + origin.minEast + << "\t" << (float)(s.maxX + 1) * (float)ppLand.resol + origin.minEast + << "\t" << (float)s.minY * (float)ppLand.resol + origin.minNorth + << "\t" << (float)(s.maxY + 1) * (float)ppLand.resol + origin.minNorth; } + else + outrange << "\t0\t0\t0\t0"; - int nsubcomms = (int)subComms.size(); - for (int i = 0; i < nsubcomms; i++) { // all sub-communities (incl. matrix) - scts = subComms[i]->outTraits(tcanv,pLandscape,rep,yr,gen,true); - for (int j = 0; j < NSEXES; j++) { - ts.ninds[j] += scts.ninds[j]; - ts.sumD0[j] += scts.sumD0[j]; ts.ssqD0[j] += scts.ssqD0[j]; - ts.sumAlpha[j] += scts.sumAlpha[j]; ts.ssqAlpha[j] += scts.ssqAlpha[j]; - ts.sumBeta[j] += scts.sumBeta[j]; ts.ssqBeta[j] += scts.ssqBeta[j]; - ts.sumDist1[j] += scts.sumDist1[j]; ts.ssqDist1[j] += scts.ssqDist1[j]; - ts.sumDist2[j] += scts.sumDist2[j]; ts.ssqDist2[j] += scts.ssqDist2[j]; - ts.sumProp1[j] += scts.sumProp1[j]; ts.ssqProp1[j] += scts.ssqProp1[j]; - ts.sumDP[j] += scts.sumDP[j]; ts.ssqDP[j] += scts.ssqDP[j]; - ts.sumGB[j] += scts.sumGB[j]; ts.ssqGB[j] += scts.ssqGB[j]; - ts.sumAlphaDB[j] += scts.sumAlphaDB[j]; ts.ssqAlphaDB[j] += scts.ssqAlphaDB[j]; - ts.sumBetaDB[j] += scts.sumBetaDB[j]; ts.ssqBetaDB[j] += scts.ssqBetaDB[j]; - ts.sumStepL[j] += scts.sumStepL[j]; ts.ssqStepL[j] += scts.ssqStepL[j]; - ts.sumRho[j] += scts.sumRho[j]; ts.ssqRho[j] += scts.ssqRho[j]; - ts.sumS0[j] += scts.sumS0[j]; ts.ssqS0[j] += scts.ssqS0[j]; - ts.sumAlphaS[j] += scts.sumAlphaS[j]; ts.ssqAlphaS[j] += scts.ssqAlphaS[j]; - ts.sumBetaS[j] += scts.sumBetaS[j]; ts.ssqBetaS[j] += scts.ssqBetaS[j]; + if (emig.indVar || trfr.indVar || sett.indVar) { // output trait means + traitsums ts; + traitsums scts; // sub-community traits + traitCanvas tcanv; + int ngenes, popsize; + + tcanv.pcanvas[0] = NULL; + + for (int i = 0; i < NSEXES; i++) { + ts.ninds[i] = 0; + ts.sumD0[i] = ts.ssqD0[i] = 0.0; + ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; + ts.sumDist1[i] = ts.ssqDist1[i] = 0.0; ts.sumDist2[i] = ts.ssqDist2[i] = 0.0; + ts.sumProp1[i] = ts.ssqProp1[i] = 0.0; + ts.sumDP[i] = ts.ssqDP[i] = 0.0; + ts.sumGB[i] = ts.ssqGB[i] = 0.0; + ts.sumAlphaDB[i] = ts.ssqAlphaDB[i] = 0.0; + ts.sumBetaDB[i] = ts.ssqBetaDB[i] = 0.0; + ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; + ts.sumS0[i] = ts.ssqS0[i] = 0.0; + ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; + } + + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities (incl. matrix) + scts = subComms[i]->outTraits(tcanv, pLandscape, rep, yr, gen, true); + for (int j = 0; j < NSEXES; j++) { + ts.ninds[j] += scts.ninds[j]; + ts.sumD0[j] += scts.sumD0[j]; ts.ssqD0[j] += scts.ssqD0[j]; + ts.sumAlpha[j] += scts.sumAlpha[j]; ts.ssqAlpha[j] += scts.ssqAlpha[j]; + ts.sumBeta[j] += scts.sumBeta[j]; ts.ssqBeta[j] += scts.ssqBeta[j]; + ts.sumDist1[j] += scts.sumDist1[j]; ts.ssqDist1[j] += scts.ssqDist1[j]; + ts.sumDist2[j] += scts.sumDist2[j]; ts.ssqDist2[j] += scts.ssqDist2[j]; + ts.sumProp1[j] += scts.sumProp1[j]; ts.ssqProp1[j] += scts.ssqProp1[j]; + ts.sumDP[j] += scts.sumDP[j]; ts.ssqDP[j] += scts.ssqDP[j]; + ts.sumGB[j] += scts.sumGB[j]; ts.ssqGB[j] += scts.ssqGB[j]; + ts.sumAlphaDB[j] += scts.sumAlphaDB[j]; ts.ssqAlphaDB[j] += scts.ssqAlphaDB[j]; + ts.sumBetaDB[j] += scts.sumBetaDB[j]; ts.ssqBetaDB[j] += scts.ssqBetaDB[j]; + ts.sumStepL[j] += scts.sumStepL[j]; ts.ssqStepL[j] += scts.ssqStepL[j]; + ts.sumRho[j] += scts.sumRho[j]; ts.ssqRho[j] += scts.ssqRho[j]; + ts.sumS0[j] += scts.sumS0[j]; ts.ssqS0[j] += scts.ssqS0[j]; + ts.sumAlphaS[j] += scts.sumAlphaS[j]; ts.ssqAlphaS[j] += scts.ssqAlphaS[j]; + ts.sumBetaS[j] += scts.sumBetaS[j]; ts.ssqBetaS[j] += scts.ssqBetaS[j]; #if RSDEBUG -//DEBUGLOG << "Community::outRange(): i=" << i << " j=" << j -// << " scts.ninds[j]=" << scts.ninds[j] -// << " scts.sumD0[j]=" << scts.sumD0[j] -// << " scts.ssqD0[j]=" << scts.ssqD0[j] -// << endl; -//DEBUGLOG << "Community::outRange(): i=" << i << " j=" << j -// << " ts.ninds[j]=" << ts.ninds[j] -// << " ts.sumD0[j]=" << ts.sumD0[j] << " ts.ssqD0[j]=" << ts.ssqD0[j] -// << endl; + //DEBUGLOG << "Community::outRange(): i=" << i << " j=" << j + // << " scts.ninds[j]=" << scts.ninds[j] + // << " scts.sumD0[j]=" << scts.sumD0[j] + // << " scts.ssqD0[j]=" << scts.ssqD0[j] + // << endl; + //DEBUGLOG << "Community::outRange(): i=" << i << " j=" << j + // << " ts.ninds[j]=" << ts.ninds[j] + // << " ts.sumD0[j]=" << ts.sumD0[j] << " ts.ssqD0[j]=" << ts.ssqD0[j] + // << endl; #endif + } } - } - if (emig.indVar) { - if (emig.sexDep) { // must be a sexual species - ngenes = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction - ngenes = 1; - } - else { // sexual reproduction - ngenes = 1; + if (emig.indVar) { + if (emig.sexDep) { // must be a sexual species + ngenes = 2; } - } - double mnD0[2],mnAlpha[2],mnBeta[2],sdD0[2],sdAlpha[2],sdBeta[2]; - for (int g = 0; g < ngenes; g++) { - mnD0[g] = mnAlpha[g] = mnBeta[g] = sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - if (ngenes == 2) popsize = ts.ninds[g]; - else popsize = ts.ninds[0] + ts.ninds[1]; - if (popsize > 0) { - mnD0[g] = ts.sumD0[g] / (double)popsize; - mnAlpha[g] = ts.sumAlpha[g] / (double)popsize; - mnBeta[g] = ts.sumBeta[g] / (double)popsize; - if (popsize > 1) { - sdD0[g] = ts.ssqD0[g]/(double)popsize - mnD0[g]*mnD0[g]; - if (sdD0[g] > 0.0) sdD0[g] = sqrt(sdD0[g]); else sdD0[g] = 0.0; - sdAlpha[g] = ts.ssqAlpha[g]/(double)popsize - mnAlpha[g]*mnAlpha[g]; - if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; - sdBeta[g] = ts.ssqBeta[g]/(double)popsize - mnBeta[g]*mnBeta[g]; - if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + else { + if (dem.repType == 0) { // asexual reproduction + ngenes = 1; } - else { - sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + else { // sexual reproduction + ngenes = 1; } } + double mnD0[2], mnAlpha[2], mnBeta[2], sdD0[2], sdAlpha[2], sdBeta[2]; + for (int g = 0; g < ngenes; g++) { + mnD0[g] = mnAlpha[g] = mnBeta[g] = sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + // individuals may have been counted by sex if there was + // sex dependency in another dispersal phase + if (ngenes == 2) popsize = ts.ninds[g]; + else popsize = ts.ninds[0] + ts.ninds[1]; + if (popsize > 0) { + mnD0[g] = ts.sumD0[g] / (double)popsize; + mnAlpha[g] = ts.sumAlpha[g] / (double)popsize; + mnBeta[g] = ts.sumBeta[g] / (double)popsize; + if (popsize > 1) { + sdD0[g] = ts.ssqD0[g] / (double)popsize - mnD0[g] * mnD0[g]; + if (sdD0[g] > 0.0) sdD0[g] = sqrt(sdD0[g]); else sdD0[g] = 0.0; + sdAlpha[g] = ts.ssqAlpha[g] / (double)popsize - mnAlpha[g] * mnAlpha[g]; + if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; + sdBeta[g] = ts.ssqBeta[g] / (double)popsize - mnBeta[g] * mnBeta[g]; + if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + } + else { + sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + } + } #if RSDEBUG -//DEBUGLOG << "Community::outRange(): ngenes=" << ngenes << " g=" << g -// << " ts.ninds[g]=" << ts.ninds[g] -// << " ts.sumD0[g]=" << ts.sumD0[g] -// << " ts.ssqD0[g]=" << ts.ssqD0[g] -// << endl; -//DEBUGLOG << "Community::outRange(): popsize=" << popsize -// << " mnD0[g]" << mnD0[g] << " sdD0[g]" << sdD0[g] -// << endl; + //DEBUGLOG << "Community::outRange(): ngenes=" << ngenes << " g=" << g + // << " ts.ninds[g]=" << ts.ninds[g] + // << " ts.sumD0[g]=" << ts.sumD0[g] + // << " ts.ssqD0[g]=" << ts.ssqD0[g] + // << endl; + //DEBUGLOG << "Community::outRange(): popsize=" << popsize + // << " mnD0[g]" << mnD0[g] << " sdD0[g]" << sdD0[g] + // << endl; #endif - } - if (emig.sexDep) { - outrange << "\t" << mnD0[0] << "\t" << sdD0[0]; - outrange << "\t" << mnD0[1] << "\t" << sdD0[1]; - if (emig.densDep) { - outrange << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outrange << "\t" << mnAlpha[1] << "\t" << sdAlpha[1]; - outrange << "\t" << mnBeta[0] << "\t" << sdBeta[0]; - outrange << "\t" << mnBeta[1] << "\t" << sdBeta[1]; } - } - else { // sex-independent - outrange << "\t" << mnD0[0] << "\t" << sdD0[0]; - if (emig.densDep) { - outrange << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outrange << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + if (emig.sexDep) { + outrange << "\t" << mnD0[0] << "\t" << sdD0[0]; + outrange << "\t" << mnD0[1] << "\t" << sdD0[1]; + if (emig.densDep) { + outrange << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; + outrange << "\t" << mnAlpha[1] << "\t" << sdAlpha[1]; + outrange << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + outrange << "\t" << mnBeta[1] << "\t" << sdBeta[1]; + } + } + else { // sex-independent + outrange << "\t" << mnD0[0] << "\t" << sdD0[0]; + if (emig.densDep) { + outrange << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; + outrange << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + } } } - } - if (trfr.indVar) { - if (trfr.moveModel) { - // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ngenes = 1; - } - else { - if (trfr.sexDep) { // must be a sexual species - ngenes = 2; - } - else { + if (trfr.indVar) { + if (trfr.moveModel) { + // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT ngenes = 1; } - } - double mnDist1[2],mnDist2[2],mnProp1[2],mnStepL[2],mnRho[2]; - double sdDist1[2],sdDist2[2],sdProp1[2],sdStepL[2],sdRho[2]; - double mnDP[2],mnGB[2],mnAlphaDB[2],mnBetaDB[2]; - double sdDP[2],sdGB[2],sdAlphaDB[2],sdBetaDB[2]; - for (int g = 0; g < ngenes; g++) { - mnDist1[g] = mnDist2[g] = mnProp1[g] = mnStepL[g] = mnRho[g] = 0.0; - sdDist1[g] = sdDist2[g] = sdProp1[g] = sdStepL[g] = sdRho[g] = 0.0; - mnDP[g] = mnGB[g] = mnAlphaDB[g] = mnBetaDB[g] = 0.0; - sdDP[g] = sdGB[g] = sdAlphaDB[g] = sdBetaDB[g] = 0.0; - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - if (ngenes == 2) popsize = ts.ninds[g]; - else popsize = ts.ninds[0] + ts.ninds[1]; - if (popsize > 0) { - mnDist1[g] = ts.sumDist1[g] / (double)popsize; - mnDist2[g] = ts.sumDist2[g] / (double)popsize; - mnProp1[g] = ts.sumProp1[g] / (double)popsize; - mnStepL[g] = ts.sumStepL[g] / (double)popsize; - mnRho[g] = ts.sumRho[g] / (double)popsize; - mnDP[g] = ts.sumDP[g] / (double)popsize; - mnGB[g] = ts.sumGB[g] / (double)popsize; - mnAlphaDB[g] = ts.sumAlphaDB[g] / (double)popsize; - mnBetaDB[g] = ts.sumBetaDB[g] / (double)popsize; - if (popsize > 1) { - sdDist1[g] = ts.ssqDist1[g]/(double)popsize - mnDist1[g]*mnDist1[g]; - if (sdDist1[g] > 0.0) sdDist1[g] = sqrt(sdDist1[g]); else sdDist1[g] = 0.0; - sdDist2[g] = ts.ssqDist2[g]/(double)popsize - mnDist2[g]*mnDist2[g]; - if (sdDist2[g] > 0.0) sdDist2[g] = sqrt(sdDist2[g]); else sdDist2[g] = 0.0; - sdProp1[g] = ts.ssqProp1[g]/(double)popsize - mnProp1[g]*mnProp1[g]; - if (sdProp1[g] > 0.0) sdProp1[g] = sqrt(sdProp1[g]); else sdProp1[g] = 0.0; - sdStepL[g] = ts.ssqStepL[g]/(double)popsize - mnStepL[g]*mnStepL[g]; - if (sdStepL[g] > 0.0) sdStepL[g] = sqrt(sdStepL[g]); else sdStepL[g] = 0.0; - sdRho[g] = ts.ssqRho[g]/(double)popsize - mnRho[g]*mnRho[g]; - if (sdRho[g] > 0.0) sdRho[g] = sqrt(sdRho[g]); else sdRho[g] = 0.0; - sdDP[g] = ts.ssqDP[g]/(double)popsize - mnDP[g]*mnDP[g]; - if (sdDP[g] > 0.0) sdDP[g] = sqrt(sdDP[g]); else sdDP[g] = 0.0; - sdGB[g] = ts.ssqGB[g]/(double)popsize - mnGB[g]*mnGB[g]; - if (sdGB[g] > 0.0) sdGB[g] = sqrt(sdGB[g]); else sdGB[g] = 0.0; - sdAlphaDB[g] = ts.ssqAlphaDB[g]/(double)popsize - mnAlphaDB[g]*mnAlphaDB[g]; - if (sdAlphaDB[g] > 0.0) sdAlphaDB[g] = sqrt(sdAlphaDB[g]); else sdAlphaDB[g] = 0.0; - sdBetaDB[g] = ts.ssqBetaDB[g]/(double)popsize - mnBetaDB[g]*mnBetaDB[g]; - if (sdBetaDB[g] > 0.0) sdBetaDB[g] = sqrt(sdBetaDB[g]); else sdBetaDB[g] = 0.0; + else { + if (trfr.sexDep) { // must be a sexual species + ngenes = 2; + } + else { + ngenes = 1; } } + double mnDist1[2], mnDist2[2], mnProp1[2], mnStepL[2], mnRho[2]; + double sdDist1[2], sdDist2[2], sdProp1[2], sdStepL[2], sdRho[2]; + double mnDP[2], mnGB[2], mnAlphaDB[2], mnBetaDB[2]; + double sdDP[2], sdGB[2], sdAlphaDB[2], sdBetaDB[2]; + for (int g = 0; g < ngenes; g++) { + mnDist1[g] = mnDist2[g] = mnProp1[g] = mnStepL[g] = mnRho[g] = 0.0; + sdDist1[g] = sdDist2[g] = sdProp1[g] = sdStepL[g] = sdRho[g] = 0.0; + mnDP[g] = mnGB[g] = mnAlphaDB[g] = mnBetaDB[g] = 0.0; + sdDP[g] = sdGB[g] = sdAlphaDB[g] = sdBetaDB[g] = 0.0; + // individuals may have been counted by sex if there was + // sex dependency in another dispersal phase + if (ngenes == 2) popsize = ts.ninds[g]; + else popsize = ts.ninds[0] + ts.ninds[1]; + if (popsize > 0) { + mnDist1[g] = ts.sumDist1[g] / (double)popsize; + mnDist2[g] = ts.sumDist2[g] / (double)popsize; + mnProp1[g] = ts.sumProp1[g] / (double)popsize; + mnStepL[g] = ts.sumStepL[g] / (double)popsize; + mnRho[g] = ts.sumRho[g] / (double)popsize; + mnDP[g] = ts.sumDP[g] / (double)popsize; + mnGB[g] = ts.sumGB[g] / (double)popsize; + mnAlphaDB[g] = ts.sumAlphaDB[g] / (double)popsize; + mnBetaDB[g] = ts.sumBetaDB[g] / (double)popsize; + if (popsize > 1) { + sdDist1[g] = ts.ssqDist1[g] / (double)popsize - mnDist1[g] * mnDist1[g]; + if (sdDist1[g] > 0.0) sdDist1[g] = sqrt(sdDist1[g]); else sdDist1[g] = 0.0; + sdDist2[g] = ts.ssqDist2[g] / (double)popsize - mnDist2[g] * mnDist2[g]; + if (sdDist2[g] > 0.0) sdDist2[g] = sqrt(sdDist2[g]); else sdDist2[g] = 0.0; + sdProp1[g] = ts.ssqProp1[g] / (double)popsize - mnProp1[g] * mnProp1[g]; + if (sdProp1[g] > 0.0) sdProp1[g] = sqrt(sdProp1[g]); else sdProp1[g] = 0.0; + sdStepL[g] = ts.ssqStepL[g] / (double)popsize - mnStepL[g] * mnStepL[g]; + if (sdStepL[g] > 0.0) sdStepL[g] = sqrt(sdStepL[g]); else sdStepL[g] = 0.0; + sdRho[g] = ts.ssqRho[g] / (double)popsize - mnRho[g] * mnRho[g]; + if (sdRho[g] > 0.0) sdRho[g] = sqrt(sdRho[g]); else sdRho[g] = 0.0; + sdDP[g] = ts.ssqDP[g] / (double)popsize - mnDP[g] * mnDP[g]; + if (sdDP[g] > 0.0) sdDP[g] = sqrt(sdDP[g]); else sdDP[g] = 0.0; + sdGB[g] = ts.ssqGB[g] / (double)popsize - mnGB[g] * mnGB[g]; + if (sdGB[g] > 0.0) sdGB[g] = sqrt(sdGB[g]); else sdGB[g] = 0.0; + sdAlphaDB[g] = ts.ssqAlphaDB[g] / (double)popsize - mnAlphaDB[g] * mnAlphaDB[g]; + if (sdAlphaDB[g] > 0.0) sdAlphaDB[g] = sqrt(sdAlphaDB[g]); else sdAlphaDB[g] = 0.0; + sdBetaDB[g] = ts.ssqBetaDB[g] / (double)popsize - mnBetaDB[g] * mnBetaDB[g]; + if (sdBetaDB[g] > 0.0) sdBetaDB[g] = sqrt(sdBetaDB[g]); else sdBetaDB[g] = 0.0; + } + } #if RSDEBUG -//DEBUGLOG << "Community::outRange(): ngenes=" << ngenes << " g=" << g -// << " ts.ninds[g]=" << ts.ninds[g] -// << " ts.sumDP[g]=" << ts.sumDP[g] << " ts.ssqDP[g]=" << ts.ssqDP[g] -// << " ts.sumGB[g]=" << ts.sumGB[g] << " ts.ssqGB[g]=" << ts.ssqGB[g] -// << endl; -//DEBUGLOG << "Community::outRange(): popsize=" << popsize -// << " mnDP[g]" << mnDP[g] << " sdDP[g]" << sdDP[g] -// << " mnGB[g]" << mnGB[g] << " sdGB[g]" << sdGB[g] -// << endl; + //DEBUGLOG << "Community::outRange(): ngenes=" << ngenes << " g=" << g + // << " ts.ninds[g]=" << ts.ninds[g] + // << " ts.sumDP[g]=" << ts.sumDP[g] << " ts.ssqDP[g]=" << ts.ssqDP[g] + // << " ts.sumGB[g]=" << ts.sumGB[g] << " ts.ssqGB[g]=" << ts.ssqGB[g] + // << endl; + //DEBUGLOG << "Community::outRange(): popsize=" << popsize + // << " mnDP[g]" << mnDP[g] << " sdDP[g]" << sdDP[g] + // << " mnGB[g]" << mnGB[g] << " sdGB[g]" << sdGB[g] + // << endl; #endif - } - if (trfr.moveModel) { - if (trfr.moveType == 1) { - outrange << "\t" << mnDP[0] << "\t" << sdDP[0]; - outrange << "\t" << mnGB[0] << "\t" << sdGB[0]; - outrange << "\t" << mnAlphaDB[0] << "\t" << sdAlphaDB[0]; - outrange << "\t" << mnBetaDB[0] << "\t" << sdBetaDB[0]; - } - if (trfr.moveType == 2) { - outrange << "\t" << mnStepL[0] << "\t" << sdStepL[0]; - outrange << "\t" << mnRho[0] << "\t" << sdRho[0]; } - } - else { - if (trfr.sexDep) { - outrange << "\t" << mnDist1[0] << "\t" << sdDist1[0]; - outrange << "\t" << mnDist1[1] << "\t" << sdDist1[1]; - if (trfr.twinKern) - { - outrange << "\t" << mnDist2[0] << "\t" << sdDist2[0]; - outrange << "\t" << mnDist2[1] << "\t" << sdDist2[1]; - outrange << "\t" << mnProp1[0] << "\t" << sdProp1[0]; - outrange << "\t" << mnProp1[1] << "\t" << sdProp1[1]; + if (trfr.moveModel) { + if (trfr.moveType == 1) { + outrange << "\t" << mnDP[0] << "\t" << sdDP[0]; + outrange << "\t" << mnGB[0] << "\t" << sdGB[0]; + outrange << "\t" << mnAlphaDB[0] << "\t" << sdAlphaDB[0]; + outrange << "\t" << mnBetaDB[0] << "\t" << sdBetaDB[0]; + } + if (trfr.moveType == 2) { + outrange << "\t" << mnStepL[0] << "\t" << sdStepL[0]; + outrange << "\t" << mnRho[0] << "\t" << sdRho[0]; } } - else { // sex-independent - outrange << "\t" << mnDist1[0] << "\t" << sdDist1[0]; - if (trfr.twinKern) - { - outrange << "\t" << mnDist2[0] << "\t" << sdDist2[0]; - outrange << "\t" << mnProp1[0] << "\t" << sdProp1[0]; + else { + if (trfr.sexDep) { + outrange << "\t" << mnDist1[0] << "\t" << sdDist1[0]; + outrange << "\t" << mnDist1[1] << "\t" << sdDist1[1]; + if (trfr.twinKern) + { + outrange << "\t" << mnDist2[0] << "\t" << sdDist2[0]; + outrange << "\t" << mnDist2[1] << "\t" << sdDist2[1]; + outrange << "\t" << mnProp1[0] << "\t" << sdProp1[0]; + outrange << "\t" << mnProp1[1] << "\t" << sdProp1[1]; + } + } + else { // sex-independent + outrange << "\t" << mnDist1[0] << "\t" << sdDist1[0]; + if (trfr.twinKern) + { + outrange << "\t" << mnDist2[0] << "\t" << sdDist2[0]; + outrange << "\t" << mnProp1[0] << "\t" << sdProp1[0]; + } } } } - } - if (sett.indVar) { - if (sett.sexDep) { // must be a sexual species - ngenes = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction - ngenes = 1; - } - else { // sexual reproduction - ngenes = 1; + if (sett.indVar) { + if (sett.sexDep) { // must be a sexual species + ngenes = 2; } - } - // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - double mnS0[2],mnAlpha[2],mnBeta[2],sdS0[2],sdAlpha[2],sdBeta[2]; - for (int g = 0; g < ngenes; g++) { - mnS0[g] = mnAlpha[g] = mnBeta[g] = sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - if (ngenes == 2) popsize = ts.ninds[g]; - else popsize = ts.ninds[0] + ts.ninds[1]; - if (popsize > 0) { - mnS0[g] = ts.sumS0[g] / (double)popsize; - mnAlpha[g] = ts.sumAlphaS[g] / (double)popsize; - mnBeta[g] = ts.sumBetaS[g] / (double)popsize; - if (popsize > 1) { - sdS0[g] = ts.ssqS0[g]/(double)popsize - mnS0[g]*mnS0[g]; - if (sdS0[g] > 0.0) sdS0[g] = sqrt(sdS0[g]); else sdS0[g] = 0.0; - sdAlpha[g] = ts.ssqAlphaS[g]/(double)popsize - mnAlpha[g]*mnAlpha[g]; - if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; - sdBeta[g] = ts.ssqBetaS[g]/(double)popsize - mnBeta[g]*mnBeta[g]; - if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + else { + if (dem.repType == 0) { // asexual reproduction + ngenes = 1; } - else { - sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + else { // sexual reproduction + ngenes = 1; } } + // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT + double mnS0[2], mnAlpha[2], mnBeta[2], sdS0[2], sdAlpha[2], sdBeta[2]; + for (int g = 0; g < ngenes; g++) { + mnS0[g] = mnAlpha[g] = mnBeta[g] = sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + // individuals may have been counted by sex if there was + // sex dependency in another dispersal phase + if (ngenes == 2) popsize = ts.ninds[g]; + else popsize = ts.ninds[0] + ts.ninds[1]; + if (popsize > 0) { + mnS0[g] = ts.sumS0[g] / (double)popsize; + mnAlpha[g] = ts.sumAlphaS[g] / (double)popsize; + mnBeta[g] = ts.sumBetaS[g] / (double)popsize; + if (popsize > 1) { + sdS0[g] = ts.ssqS0[g] / (double)popsize - mnS0[g] * mnS0[g]; + if (sdS0[g] > 0.0) sdS0[g] = sqrt(sdS0[g]); else sdS0[g] = 0.0; + sdAlpha[g] = ts.ssqAlphaS[g] / (double)popsize - mnAlpha[g] * mnAlpha[g]; + if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; + sdBeta[g] = ts.ssqBetaS[g] / (double)popsize - mnBeta[g] * mnBeta[g]; + if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + } + else { + sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + } + } + } + if (sett.sexDep) { + outrange << "\t" << mnS0[0] << "\t" << sdS0[0]; + outrange << "\t" << mnS0[1] << "\t" << sdS0[1]; + outrange << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; + outrange << "\t" << mnAlpha[1] << "\t" << sdAlpha[1]; + outrange << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + outrange << "\t" << mnBeta[1] << "\t" << sdBeta[1]; + } + else { + outrange << "\t" << mnS0[0] << "\t" << sdS0[0]; + outrange << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; + outrange << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + } } - if (sett.sexDep) { - outrange << "\t" << mnS0[0] << "\t" << sdS0[0]; - outrange << "\t" << mnS0[1] << "\t" << sdS0[1]; - outrange << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outrange << "\t" << mnAlpha[1] << "\t" << sdAlpha[1]; - outrange << "\t" << mnBeta[0] << "\t" << sdBeta[0]; - outrange << "\t" << mnBeta[1] << "\t" << sdBeta[1]; - } - else { - outrange << "\t" << mnS0[0] << "\t" << sdS0[0]; - outrange << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outrange << "\t" << mnBeta[0] << "\t" << sdBeta[0]; - } - } -} + } -outrange << endl; + outrange << endl; } // Open occupancy file, write header record and set up occupancy array bool Community::outOccupancyHeaders(int option) { -if (option == -999) { // close the files - if (outsuit.is_open()) outsuit.close(); - if (outoccup.is_open()) outoccup.close(); - outsuit.clear(); outoccup.clear(); - return true; -} + if (option == -999) { // close the files + if (outsuit.is_open()) outsuit.close(); + if (outoccup.is_open()) outoccup.close(); + outsuit.clear(); outoccup.clear(); + return true; + } -string name, nameI; -simParams sim = paramsSim->getSim(); -//demogrParams dem = pSpecies->getDemogr(); -landParams ppLand = pLandscape->getLandParams(); -int outrows = (sim.years/sim.outIntOcc) + 1; + string name, nameI; + simParams sim = paramsSim->getSim(); + //demogrParams dem = pSpecies->getDemogr(); + landParams ppLand = pLandscape->getLandParams(); + int outrows = (sim.years / sim.outIntOcc) + 1; -name = paramsSim->getDir(2); -if (sim.batchMode) { - name += "Batch" + Int2Str(sim.batchNum) + "_"; - name += "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(ppLand.landNum); -} -else - name += "Sim" + Int2Str(sim.simulation); -name += "_Occupancy_Stats.txt"; -outsuit.open(name.c_str()); -outsuit << "Year\tMean_OccupSuit\tStd_error" << endl; - -name = paramsSim->getDir(2); -if (sim.batchMode) { - name += "Batch" + Int2Str(sim.batchNum) + "_"; - name += "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(ppLand.landNum); -} -else - name += "Sim" + Int2Str(sim.simulation); -name += "_Occupancy.txt"; -outoccup.open(name.c_str()); -if (ppLand.patchModel) { - outoccup << "PatchID"; -} -else { - outoccup << "X\tY"; -} -for (int i = 0; i < outrows; i++) - outoccup << "\t" << "Year_" << i*sim.outIntOcc; -outoccup << endl; + name = paramsSim->getDir(2); + if (sim.batchMode) { + name += "Batch" + Int2Str(sim.batchNum) + "_"; + name += "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(ppLand.landNum); + } + else + name += "Sim" + Int2Str(sim.simulation); + name += "_Occupancy_Stats.txt"; + outsuit.open(name.c_str()); + outsuit << "Year\tMean_OccupSuit\tStd_error" << endl; + + name = paramsSim->getDir(2); + if (sim.batchMode) { + name += "Batch" + Int2Str(sim.batchNum) + "_"; + name += "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(ppLand.landNum); + } + else + name += "Sim" + Int2Str(sim.simulation); + name += "_Occupancy.txt"; + outoccup.open(name.c_str()); + if (ppLand.patchModel) { + outoccup << "PatchID"; + } + else { + outoccup << "X\tY"; + } + for (int i = 0; i < outrows; i++) + outoccup << "\t" << "Year_" << i * sim.outIntOcc; + outoccup << endl; -// Initialise cells/patches occupancy array -createOccupancy(outrows,sim.reps); + // Initialise cells/patches occupancy array + createOccupancy(outrows, sim.reps); -return outsuit.is_open() && outoccup.is_open(); + return outsuit.is_open() && outoccup.is_open(); } void Community::outOccupancy(void) { -landParams ppLand = pLandscape->getLandParams(); -simParams sim = paramsSim->getSim(); -//streamsize prec = outoccup.precision(); -locn loc; + landParams ppLand = pLandscape->getLandParams(); + simParams sim = paramsSim->getSim(); + //streamsize prec = outoccup.precision(); + locn loc; -int nsubcomms = (int)subComms.size(); -for (int i = 1; i < nsubcomms; i++) { // all except matrix sub-community - if (ppLand.patchModel) { - outoccup << subComms[i]->getPatch()->getPatchNum(); - } - else { - loc = subComms[i]->getLocn(); - outoccup << loc.x << "\t" << loc.y; - } - for (int row = 0; row <= (sim.years/sim.outIntOcc); row++) - { - outoccup << "\t" << (double)subComms[i]->getOccupancy(row)/(double)sim.reps; + int nsubcomms = (int)subComms.size(); + for (int i = 1; i < nsubcomms; i++) { // all except matrix sub-community + if (ppLand.patchModel) { + outoccup << subComms[i]->getPatch()->getPatchNum(); + } + else { + loc = subComms[i]->getLocn(); + outoccup << loc.x << "\t" << loc.y; + } + for (int row = 0; row <= (sim.years / sim.outIntOcc); row++) + { + outoccup << "\t" << (double)subComms[i]->getOccupancy(row) / (double)sim.reps; + } + outoccup << endl; } - outoccup << endl; -} } void Community::outOccSuit(bool view) { -double sum,ss,mean,sd,se; -simParams sim = paramsSim->getSim(); -//streamsize prec = outsuit.precision(); + double sum, ss, mean, sd, se; + simParams sim = paramsSim->getSim(); + //streamsize prec = outsuit.precision(); #if RSDEBUG //DEBUGLOG << "Community::outOccSuit(): sim.reps=" << sim.reps // << " sim.years=" << sim.years << " sim.outInt=" << sim.outInt << endl; #endif -for (int i = 0; i < (sim.years/sim.outIntOcc)+1; i++) { - sum = ss = 0.0; - for (int rep = 0; rep < sim.reps; rep++) { - sum += occSuit[i][rep]; - ss += occSuit[i][rep] * occSuit[i][rep]; + for (int i = 0; i < (sim.years / sim.outIntOcc) + 1; i++) { + sum = ss = 0.0; + for (int rep = 0; rep < sim.reps; rep++) { + sum += occSuit[i][rep]; + ss += occSuit[i][rep] * occSuit[i][rep]; #if RSDEBUG -//DEBUGLOG << "Community::outOccSuit(): i=" << i << " rep=" << rep -// << " occSuit[i][rep]=" << occSuit[i][rep] -// << " sum=" << sum << " ss=" << ss -// << endl; + //DEBUGLOG << "Community::outOccSuit(): i=" << i << " rep=" << rep + // << " occSuit[i][rep]=" << occSuit[i][rep] + // << " sum=" << sum << " ss=" << ss + // << endl; #endif - } - mean = sum/(double)sim.reps; - sd = (ss - (sum*sum/(double)sim.reps)) / (double)(sim.reps-1); + } + mean = sum / (double)sim.reps; + sd = (ss - (sum * sum / (double)sim.reps)) / (double)(sim.reps - 1); #if RSDEBUG -//DEBUGLOG << "Community::outOccSuit(): i=" << i -// << " mean=" << mean << " sd=" << sd << endl; + //DEBUGLOG << "Community::outOccSuit(): i=" << i + // << " mean=" << mean << " sd=" << sd << endl; #endif - if (sd > 0.0) sd = sqrt(sd); - else sd = 0.0; - se = sd / sqrt((double)(sim.reps)); + if (sd > 0.0) sd = sqrt(sd); + else sd = 0.0; + se = sd / sqrt((double)(sim.reps)); #if RSDEBUG -//DEBUGLOG << "Community::outOccSuit(): i=" << i -// << " sd=" << sd << " se=" << se << endl; + //DEBUGLOG << "Community::outOccSuit(): i=" << i + // << " sd=" << sd << " se=" << se << endl; #endif // outsuit << i*sim.outInt << "\t" << mean << "\t" << se << endl; // if (view) viewOccSuit(i*sim.outInt,mean,se); - outsuit << i*sim.outIntOcc << "\t" << mean << "\t" << se << endl; - if (view) viewOccSuit(i*sim.outIntOcc,mean,se); -} + outsuit << i * sim.outIntOcc << "\t" << mean << "\t" << se << endl; + if (view) viewOccSuit(i * sim.outIntOcc, mean, se); + } } // Open traits file and write header record -bool Community::outTraitsHeaders(Species *pSpecies,int landNr) { -return subComms[0]->outTraitsHeaders(pLandscape,pSpecies,landNr); +bool Community::outTraitsHeaders(Species* pSpecies, int landNr) { + return subComms[0]->outTraitsHeaders(pLandscape, pSpecies, landNr); } // Write records to traits file @@ -1308,364 +1308,364 @@ order of y */ //void Community::outTraits(emigCanvas ecanv,trfrCanvas tcanv,Species *pSpecies, // int rep,int yr,int gen) -void Community::outTraits(traitCanvas tcanv,Species *pSpecies, - int rep,int yr,int gen) +void Community::outTraits(traitCanvas tcanv, Species* pSpecies, + int rep, int yr, int gen) { -simParams sim = paramsSim->getSim(); -simView v = paramsSim->getViews(); -landParams land = pLandscape->getLandParams(); -//demogrParams dem = pSpecies->getDemogr(); -//emigRules emig = pSpecies->getEmig(); -//trfrRules trfr = pSpecies->getTrfr(); -//locn loc; -traitsums *ts = 0; -traitsums sctraits; -if (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr%sim.outIntTraitRow == 0) { - // create array of traits means, etc., one for each row - ts = new traitsums[land.dimY]; - for (int y = 0; y < land.dimY; y++) { - for (int i = 0; i < NSEXES; i++) { - ts[y].ninds[i] = 0; - ts[y].sumD0[i] = ts[y].ssqD0[i] = 0.0; - ts[y].sumAlpha[i] = ts[y].ssqAlpha[i] = 0.0; - ts[y].sumBeta[i] = ts[y].ssqBeta[i] = 0.0; - ts[y].sumDist1[i] = ts[y].ssqDist1[i] = 0.0; - ts[y].sumDist2[i] = ts[y].ssqDist2[i] = 0.0; - ts[y].sumProp1[i] = ts[y].ssqProp1[i] = 0.0; - ts[y].sumStepL[i] = ts[y].ssqStepL[i] = 0.0; - ts[y].sumRho[i] = ts[y].ssqRho[i] = 0.0; - ts[y].sumS0[i] = ts[y].ssqS0[i] = 0.0; - ts[y].sumAlphaS[i] = ts[y].ssqAlphaS[i] = 0.0; - ts[y].sumBetaS[i] = ts[y].ssqBetaS[i] = 0.0; + simParams sim = paramsSim->getSim(); + simView v = paramsSim->getViews(); + landParams land = pLandscape->getLandParams(); + //demogrParams dem = pSpecies->getDemogr(); + //emigRules emig = pSpecies->getEmig(); + //trfrRules trfr = pSpecies->getTrfr(); + //locn loc; + traitsums* ts = 0; + traitsums sctraits; + if (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0) { + // create array of traits means, etc., one for each row + ts = new traitsums[land.dimY]; + for (int y = 0; y < land.dimY; y++) { + for (int i = 0; i < NSEXES; i++) { + ts[y].ninds[i] = 0; + ts[y].sumD0[i] = ts[y].ssqD0[i] = 0.0; + ts[y].sumAlpha[i] = ts[y].ssqAlpha[i] = 0.0; + ts[y].sumBeta[i] = ts[y].ssqBeta[i] = 0.0; + ts[y].sumDist1[i] = ts[y].ssqDist1[i] = 0.0; + ts[y].sumDist2[i] = ts[y].ssqDist2[i] = 0.0; + ts[y].sumProp1[i] = ts[y].ssqProp1[i] = 0.0; + ts[y].sumStepL[i] = ts[y].ssqStepL[i] = 0.0; + ts[y].sumRho[i] = ts[y].ssqRho[i] = 0.0; + ts[y].sumS0[i] = ts[y].ssqS0[i] = 0.0; + ts[y].sumAlphaS[i] = ts[y].ssqAlphaS[i] = 0.0; + ts[y].sumBetaS[i] = ts[y].ssqBetaS[i] = 0.0; + } } } -} -if (v.viewTraits -|| ((sim.outTraitsCells && yr >= sim.outStartTraitCell && yr%sim.outIntTraitCell == 0) || - (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr%sim.outIntTraitRow == 0))) -{ - // generate output for each sub-community (patch) in the community - int nsubcomms = (int)subComms.size(); - for (int i = 1; i < nsubcomms; i++) { // // all except matrix sub-community -// sctraits = subComms[i]->outTraits(ecanv,tcanv,pLandscape,rep,yr,gen); -// sctraits = subComms[i]->outTraits(tcanv,pLandscape,rep,yr,gen,v.viewGrad); - sctraits = subComms[i]->outTraits(tcanv,pLandscape,rep,yr,gen,false); - locn loc = subComms[i]->getLocn(); - int y = loc.y; - if (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr%sim.outIntTraitRow == 0) - { - for (int s = 0; s < NSEXES; s++) { - ts[y].ninds[s] += sctraits.ninds[s]; - ts[y].sumD0[s] += sctraits.sumD0[s]; ts[y].ssqD0[s] += sctraits.ssqD0[s]; - ts[y].sumAlpha[s] += sctraits.sumAlpha[s]; ts[y].ssqAlpha[s] += sctraits.ssqAlpha[s]; - ts[y].sumBeta[s] += sctraits.sumBeta[s]; ts[y].ssqBeta[s] += sctraits.ssqBeta[s]; - ts[y].sumDist1[s] += sctraits.sumDist1[s]; ts[y].ssqDist1[s] += sctraits.ssqDist1[s]; - ts[y].sumDist2[s] += sctraits.sumDist2[s]; ts[y].ssqDist2[s] += sctraits.ssqDist2[s]; - ts[y].sumProp1[s] += sctraits.sumProp1[s]; ts[y].ssqProp1[s] += sctraits.ssqProp1[s]; - ts[y].sumStepL[s] += sctraits.sumStepL[s]; ts[y].ssqStepL[s] += sctraits.ssqStepL[s]; - ts[y].sumRho[s] += sctraits.sumRho[s]; ts[y].ssqRho[s] += sctraits.ssqRho[s]; - ts[y].sumS0[s] += sctraits.sumS0[s]; ts[y].ssqS0[s] += sctraits.ssqS0[s]; - ts[y].sumAlphaS[s] += sctraits.sumAlphaS[s]; ts[y].ssqAlphaS[s] += sctraits.ssqAlphaS[s]; - ts[y].sumBetaS[s] += sctraits.sumBetaS[s]; ts[y].ssqBetaS[s] += sctraits.ssqBetaS[s]; + if (v.viewTraits + || ((sim.outTraitsCells && yr >= sim.outStartTraitCell && yr % sim.outIntTraitCell == 0) || + (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0))) + { + // generate output for each sub-community (patch) in the community + int nsubcomms = (int)subComms.size(); + for (int i = 1; i < nsubcomms; i++) { // // all except matrix sub-community + // sctraits = subComms[i]->outTraits(ecanv,tcanv,pLandscape,rep,yr,gen); + // sctraits = subComms[i]->outTraits(tcanv,pLandscape,rep,yr,gen,v.viewGrad); + sctraits = subComms[i]->outTraits(tcanv, pLandscape, rep, yr, gen, false); + locn loc = subComms[i]->getLocn(); + int y = loc.y; + if (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0) + { + for (int s = 0; s < NSEXES; s++) { + ts[y].ninds[s] += sctraits.ninds[s]; + ts[y].sumD0[s] += sctraits.sumD0[s]; ts[y].ssqD0[s] += sctraits.ssqD0[s]; + ts[y].sumAlpha[s] += sctraits.sumAlpha[s]; ts[y].ssqAlpha[s] += sctraits.ssqAlpha[s]; + ts[y].sumBeta[s] += sctraits.sumBeta[s]; ts[y].ssqBeta[s] += sctraits.ssqBeta[s]; + ts[y].sumDist1[s] += sctraits.sumDist1[s]; ts[y].ssqDist1[s] += sctraits.ssqDist1[s]; + ts[y].sumDist2[s] += sctraits.sumDist2[s]; ts[y].ssqDist2[s] += sctraits.ssqDist2[s]; + ts[y].sumProp1[s] += sctraits.sumProp1[s]; ts[y].ssqProp1[s] += sctraits.ssqProp1[s]; + ts[y].sumStepL[s] += sctraits.sumStepL[s]; ts[y].ssqStepL[s] += sctraits.ssqStepL[s]; + ts[y].sumRho[s] += sctraits.sumRho[s]; ts[y].ssqRho[s] += sctraits.ssqRho[s]; + ts[y].sumS0[s] += sctraits.sumS0[s]; ts[y].ssqS0[s] += sctraits.ssqS0[s]; + ts[y].sumAlphaS[s] += sctraits.sumAlphaS[s]; ts[y].ssqAlphaS[s] += sctraits.ssqAlphaS[s]; + ts[y].sumBetaS[s] += sctraits.sumBetaS[s]; ts[y].ssqBetaS[s] += sctraits.ssqBetaS[s]; + } } } - } - if (nsubcomms > 0 && sim.outTraitsRows - && yr >= sim.outStartTraitRow && yr%sim.outIntTraitRow == 0) { - for (int y = 0; y < land.dimY; y++) { - if ((ts[y].ninds[0]+ts[y].ninds[1]) > 0) { - writeTraitsRows(pSpecies,rep,yr,gen,y,ts[y]); + if (nsubcomms > 0 && sim.outTraitsRows + && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0) { + for (int y = 0; y < land.dimY; y++) { + if ((ts[y].ninds[0] + ts[y].ninds[1]) > 0) { + writeTraitsRows(pSpecies, rep, yr, gen, y, ts[y]); + } } } } -} -//if (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr%sim.outIntTraitRow == 0) -//{ -// if (ts != 0) delete[] ts; -//} -if (ts != 0) { delete[] ts; ts = 0; } + //if (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr%sim.outIntTraitRow == 0) + //{ + // if (ts != 0) delete[] ts; + //} + if (ts != 0) { delete[] ts; ts = 0; } } // Write records to trait rows file -void Community::writeTraitsRows(Species *pSpecies,int rep,int yr,int gen,int y, +void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int y, traitsums ts) { -//simParams sim = paramsSim->getSim(); -//simView v = paramsSim->getViews(); -//landData land = pLandscape->getLandData(); -//landOrigin origin = pLandscape->getOrigin(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -double mn,sd; - -// calculate population size in case one phase is sex-dependent and the other is not -// (in which case numbers of individuals are recorded by sex) -int popsize = ts.ninds[0] + ts.ninds[1]; -outtraitsrows << rep << "\t" << yr << "\t" << gen - << "\t" << y; -// << "\t" << y*land.resol + origin.minNorth; -if ((emig.indVar && emig.sexDep) || (trfr.indVar && trfr.sexDep)) - outtraitsrows << "\t" << ts.ninds[0] << "\t" << ts.ninds[1]; -else - outtraitsrows << "\t" << popsize; - -if (emig.indVar) { - if (emig.sexDep) { - if (ts.ninds[0] > 0) mn = ts.sumD0[0]/(double)ts.ninds[0]; else mn = 0.0; - if (ts.ninds[0] > 1) sd = ts.ssqD0[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[1] > 0) mn = ts.sumD0[1]/(double)ts.ninds[1]; else mn = 0.0; - if (ts.ninds[1] > 1) sd = ts.ssqD0[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (emig.densDep) { - if (ts.ninds[0] > 0) mn = ts.sumAlpha[0]/(double)ts.ninds[0]; else mn = 0.0; - if (ts.ninds[0] > 1) sd = ts.ssqAlpha[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[1] > 0) mn = ts.sumAlpha[1]/(double)ts.ninds[1]; else mn = 0.0; - if (ts.ninds[1] > 1) sd = ts.ssqAlpha[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[0] > 0) mn = ts.sumBeta[0]/(double)ts.ninds[0]; else mn = 0.0; - if (ts.ninds[0] > 1) sd = ts.ssqBeta[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[1] > 0) mn = ts.sumBeta[1]/(double)ts.ninds[1]; else mn = 0.0; - if (ts.ninds[1] > 1) sd = ts.ssqBeta[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - } - } - else { // no sex dependence in emigration - if (popsize > 0) mn = ts.sumD0[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqD0[0]/(double)popsize - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (emig.densDep) { - if (popsize > 0) mn = ts.sumAlpha[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqAlpha[0]/(double)popsize - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (popsize > 0) mn = ts.sumBeta[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqBeta[0]/(double)popsize - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - } - } -} + //simParams sim = paramsSim->getSim(); + //simView v = paramsSim->getViews(); + //landData land = pLandscape->getLandData(); + //landOrigin origin = pLandscape->getOrigin(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + double mn, sd; + + // calculate population size in case one phase is sex-dependent and the other is not + // (in which case numbers of individuals are recorded by sex) + int popsize = ts.ninds[0] + ts.ninds[1]; + outtraitsrows << rep << "\t" << yr << "\t" << gen + << "\t" << y; + // << "\t" << y*land.resol + origin.minNorth; + if ((emig.indVar && emig.sexDep) || (trfr.indVar && trfr.sexDep)) + outtraitsrows << "\t" << ts.ninds[0] << "\t" << ts.ninds[1]; + else + outtraitsrows << "\t" << popsize; -if (trfr.indVar) { - if (trfr.moveModel) { - if (trfr.moveType == 2) { // CRW - // NB - CURRENTLY CANNOT BE SEX-DEPENDENT... - if (popsize > 0) mn = ts.sumStepL[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqStepL[0]/(double)popsize - mn*mn; else sd = 0.0; + if (emig.indVar) { + if (emig.sexDep) { + if (ts.ninds[0] > 0) mn = ts.sumD0[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqD0[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (popsize > 0) mn = ts.sumRho[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqRho[0]/(double)popsize - mn*mn; else sd = 0.0; + if (ts.ninds[1] > 0) mn = ts.sumD0[1] / (double)ts.ninds[1]; else mn = 0.0; + if (ts.ninds[1] > 1) sd = ts.ssqD0[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; -// if (ts.ninds[0] > 0) mn = ts.sumStepL[0]/(double)ts.ninds[0]; else mn = 0.0; -// if (ts.ninds[0] > 1) sd = ts.ssqStepL[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; -// if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; -// outtraitsrows << "\t" << mn << "\t" << sd; -// if (ts.ninds[0] > 0) mn = ts.sumRho[0]/(double)ts.ninds[0]; else mn = 0.0; -// if (ts.ninds[0] > 1) sd = ts.ssqRho[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; -// if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; -// outtraitsrows << "\t" << mn << "\t" << sd; + if (emig.densDep) { + if (ts.ninds[0] > 0) mn = ts.sumAlpha[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqAlpha[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (ts.ninds[1] > 0) mn = ts.sumAlpha[1] / (double)ts.ninds[1]; else mn = 0.0; + if (ts.ninds[1] > 1) sd = ts.ssqAlpha[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (ts.ninds[0] > 0) mn = ts.sumBeta[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqBeta[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (ts.ninds[1] > 0) mn = ts.sumBeta[1] / (double)ts.ninds[1]; else mn = 0.0; + if (ts.ninds[1] > 1) sd = ts.ssqBeta[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + } } - } - else { // dispersal kernel - if (trfr.sexDep) { - if (ts.ninds[0] > 0) mn = ts.sumDist1[0]/(double)ts.ninds[0]; else mn = 0.0; - if (ts.ninds[0] > 1) sd = ts.ssqDist1[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; + else { // no sex dependence in emigration + if (popsize > 0) mn = ts.sumD0[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqD0[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[1] > 0) mn = ts.sumDist1[1]/(double)ts.ninds[1]; else mn = 0.0; - if (ts.ninds[1] > 1) sd = ts.ssqDist1[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (trfr.twinKern) - { - if (ts.ninds[0] > 0) mn = ts.sumDist2[0]/(double)ts.ninds[0]; else mn = 0.0; - if (ts.ninds[0] > 1) sd = ts.ssqDist2[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; + if (emig.densDep) { + if (popsize > 0) mn = ts.sumAlpha[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqAlpha[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[1] > 0) mn = ts.sumDist2[1]/(double)ts.ninds[1]; else mn = 0.0; - if (ts.ninds[1] > 1) sd = ts.ssqDist2[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; + if (popsize > 0) mn = ts.sumBeta[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqBeta[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[0] > 0) mn = ts.sumProp1[0]/(double)ts.ninds[0]; else mn = 0.0; - if (ts.ninds[0] > 1) sd = ts.ssqProp1[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; + } + } + } + + if (trfr.indVar) { + if (trfr.moveModel) { + if (trfr.moveType == 2) { // CRW + // NB - CURRENTLY CANNOT BE SEX-DEPENDENT... + if (popsize > 0) mn = ts.sumStepL[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqStepL[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[1] > 0) mn = ts.sumProp1[1]/(double)ts.ninds[1]; else mn = 0.0; - if (ts.ninds[1] > 1) sd = ts.ssqProp1[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; + if (popsize > 0) mn = ts.sumRho[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqRho[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; + // if (ts.ninds[0] > 0) mn = ts.sumStepL[0]/(double)ts.ninds[0]; else mn = 0.0; + // if (ts.ninds[0] > 1) sd = ts.ssqStepL[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; + // if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + // outtraitsrows << "\t" << mn << "\t" << sd; + // if (ts.ninds[0] > 0) mn = ts.sumRho[0]/(double)ts.ninds[0]; else mn = 0.0; + // if (ts.ninds[0] > 1) sd = ts.ssqRho[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; + // if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + // outtraitsrows << "\t" << mn << "\t" << sd; } } - else { // sex-independent - if (popsize > 0) mn = ts.sumDist1[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqDist1[0]/(double)popsize - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (trfr.twinKern) - { - if (popsize > 0) mn = ts.sumDist2[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqDist2[0]/(double)popsize - mn*mn; else sd = 0.0; + else { // dispersal kernel + if (trfr.sexDep) { + if (ts.ninds[0] > 0) mn = ts.sumDist1[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqDist1[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (popsize > 0) mn = ts.sumProp1[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqProp1[0]/(double)popsize - mn*mn; else sd = 0.0; + if (ts.ninds[1] > 0) mn = ts.sumDist1[1] / (double)ts.ninds[1]; else mn = 0.0; + if (ts.ninds[1] > 1) sd = ts.ssqDist1[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; + if (trfr.twinKern) + { + if (ts.ninds[0] > 0) mn = ts.sumDist2[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqDist2[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (ts.ninds[1] > 0) mn = ts.sumDist2[1] / (double)ts.ninds[1]; else mn = 0.0; + if (ts.ninds[1] > 1) sd = ts.ssqDist2[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (ts.ninds[0] > 0) mn = ts.sumProp1[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqProp1[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (ts.ninds[1] > 0) mn = ts.sumProp1[1] / (double)ts.ninds[1]; else mn = 0.0; + if (ts.ninds[1] > 1) sd = ts.ssqProp1[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + } + } + else { // sex-independent + if (popsize > 0) mn = ts.sumDist1[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqDist1[0] / (double)popsize - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (trfr.twinKern) + { + if (popsize > 0) mn = ts.sumDist2[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqDist2[0] / (double)popsize - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (popsize > 0) mn = ts.sumProp1[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqProp1[0] / (double)popsize - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + } } } } -} -if (sett.indVar) { - // NB - CURRENTLY CANNOT BE SEX-DEPENDENT... -// if (sett.sexDep) { -// if (ts.ninds[0] > 0) mn = ts.sumS0[0]/(double)ts.ninds[0]; else mn = 0.0; -// if (ts.ninds[0] > 1) sd = ts.ssqS0[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; -// if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; -// outtraitsrows << "\t" << mn << "\t" << sd; -// if (ts.ninds[1] > 0) mn = ts.sumS0[1]/(double)ts.ninds[1]; else mn = 0.0; -// if (ts.ninds[1] > 1) sd = ts.ssqS0[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; -// if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; -// outtraitsrows << "\t" << mn << "\t" << sd; -// if (ts.ninds[0] > 0) mn = ts.sumAlphaS[0]/(double)ts.ninds[0]; else mn = 0.0; -// if (ts.ninds[0] > 1) sd = ts.ssqAlphaS[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; -// if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; -// outtraitsrows << "\t" << mn << "\t" << sd; -// if (ts.ninds[1] > 0) mn = ts.sumAlphaS[1]/(double)ts.ninds[1]; else mn = 0.0; -// if (ts.ninds[1] > 1) sd = ts.ssqAlphaS[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; -// if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; -// outtraitsrows << "\t" << mn << "\t" << sd; -// if (ts.ninds[0] > 0) mn = ts.sumBetaS[0]/(double)ts.ninds[0]; else mn = 0.0; -// if (ts.ninds[0] > 1) sd = ts.ssqBetaS[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; -// if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; -// outtraitsrows << "\t" << mn << "\t" << sd; -// if (ts.ninds[1] > 0) mn = ts.sumBetaS[1]/(double)ts.ninds[1]; else mn = 0.0; -// if (ts.ninds[1] > 1) sd = ts.ssqBetaS[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; -// if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; -// outtraitsrows << "\t" << mn << "\t" << sd; -// } -// else { // no sex dependence in settlement - if (popsize > 0) mn = ts.sumS0[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqS0[0]/(double)popsize - mn*mn; else sd = 0.0; + if (sett.indVar) { + // NB - CURRENTLY CANNOT BE SEX-DEPENDENT... + // if (sett.sexDep) { + // if (ts.ninds[0] > 0) mn = ts.sumS0[0]/(double)ts.ninds[0]; else mn = 0.0; + // if (ts.ninds[0] > 1) sd = ts.ssqS0[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; + // if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + // outtraitsrows << "\t" << mn << "\t" << sd; + // if (ts.ninds[1] > 0) mn = ts.sumS0[1]/(double)ts.ninds[1]; else mn = 0.0; + // if (ts.ninds[1] > 1) sd = ts.ssqS0[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; + // if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + // outtraitsrows << "\t" << mn << "\t" << sd; + // if (ts.ninds[0] > 0) mn = ts.sumAlphaS[0]/(double)ts.ninds[0]; else mn = 0.0; + // if (ts.ninds[0] > 1) sd = ts.ssqAlphaS[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; + // if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + // outtraitsrows << "\t" << mn << "\t" << sd; + // if (ts.ninds[1] > 0) mn = ts.sumAlphaS[1]/(double)ts.ninds[1]; else mn = 0.0; + // if (ts.ninds[1] > 1) sd = ts.ssqAlphaS[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; + // if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + // outtraitsrows << "\t" << mn << "\t" << sd; + // if (ts.ninds[0] > 0) mn = ts.sumBetaS[0]/(double)ts.ninds[0]; else mn = 0.0; + // if (ts.ninds[0] > 1) sd = ts.ssqBetaS[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; + // if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + // outtraitsrows << "\t" << mn << "\t" << sd; + // if (ts.ninds[1] > 0) mn = ts.sumBetaS[1]/(double)ts.ninds[1]; else mn = 0.0; + // if (ts.ninds[1] > 1) sd = ts.ssqBetaS[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; + // if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + // outtraitsrows << "\t" << mn << "\t" << sd; + // } + // else { // no sex dependence in settlement + if (popsize > 0) mn = ts.sumS0[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqS0[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (popsize > 0) mn = ts.sumAlphaS[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqAlphaS[0]/(double)popsize - mn*mn; else sd = 0.0; + if (popsize > 0) mn = ts.sumAlphaS[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqAlphaS[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (popsize > 0) mn = ts.sumBetaS[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqBetaS[0]/(double)popsize - mn*mn; else sd = 0.0; + if (popsize > 0) mn = ts.sumBetaS[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqBetaS[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; -// } -} + // } + } -outtraitsrows << endl; + outtraitsrows << endl; } // Open trait rows file and write header record -bool Community::outTraitsRowsHeaders(Species *pSpecies,int landNr) { +bool Community::outTraitsRowsHeaders(Species* pSpecies, int landNr) { -if (landNr == -999) { // close file - if (outtraitsrows.is_open()) outtraitsrows.close(); - outtraitsrows.clear(); - return true; -} + if (landNr == -999) { // close file + if (outtraitsrows.is_open()) outtraitsrows.close(); + outtraitsrows.clear(); + return true; + } -string name; -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -simParams sim = paramsSim->getSim(); - -string DirOut = paramsSim->getDir(2); -if (sim.batchMode) { - name = DirOut - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) + "_TraitsXrow.txt"; -} -else { - name = DirOut + "Sim" + Int2Str(sim.simulation) + "_TraitsXrow.txt"; -} -outtraitsrows.open(name.c_str()); - -outtraitsrows << "Rep\tYear\tRepSeason\ty"; -if ((emig.indVar && emig.sexDep) || (trfr.indVar && trfr.sexDep)) - outtraitsrows << "\tN_females\tN_males"; -else - outtraitsrows << "\tN"; - -if (emig.indVar) { - if (emig.sexDep) { - if (emig.densDep) { - outtraitsrows << "\tF_meanD0\tF_stdD0\tM_meanD0\tM_stdD0"; - outtraitsrows << "\tF_meanAlpha\tF_stdAlpha\tM_meanAlpha\tM_stdAlpha"; - outtraitsrows << "\tF_meanBeta\tF_stdBeta\tM_meanBeta\tM_stdBeta"; - } - else { - outtraitsrows << "\tF_meanEP\tF_stdEP\tM_meanEP\tM_stdEP"; - } + string name; + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + simParams sim = paramsSim->getSim(); + + string DirOut = paramsSim->getDir(2); + if (sim.batchMode) { + name = DirOut + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) + "_TraitsXrow.txt"; } else { - if (emig.densDep) { - outtraitsrows << "\tmeanD0\tstdD0\tmeanAlpha\tstdAlpha"; - outtraitsrows << "\tmeanBeta\tstdBeta"; + name = DirOut + "Sim" + Int2Str(sim.simulation) + "_TraitsXrow.txt"; + } + outtraitsrows.open(name.c_str()); + + outtraitsrows << "Rep\tYear\tRepSeason\ty"; + if ((emig.indVar && emig.sexDep) || (trfr.indVar && trfr.sexDep)) + outtraitsrows << "\tN_females\tN_males"; + else + outtraitsrows << "\tN"; + + if (emig.indVar) { + if (emig.sexDep) { + if (emig.densDep) { + outtraitsrows << "\tF_meanD0\tF_stdD0\tM_meanD0\tM_stdD0"; + outtraitsrows << "\tF_meanAlpha\tF_stdAlpha\tM_meanAlpha\tM_stdAlpha"; + outtraitsrows << "\tF_meanBeta\tF_stdBeta\tM_meanBeta\tM_stdBeta"; + } + else { + outtraitsrows << "\tF_meanEP\tF_stdEP\tM_meanEP\tM_stdEP"; + } } else { - outtraitsrows << "\tmeanEP\tstdEP"; + if (emig.densDep) { + outtraitsrows << "\tmeanD0\tstdD0\tmeanAlpha\tstdAlpha"; + outtraitsrows << "\tmeanBeta\tstdBeta"; + } + else { + outtraitsrows << "\tmeanEP\tstdEP"; + } } } -} -if (trfr.indVar) { - if (trfr.moveModel) { - if (trfr.moveType == 2) { - outtraitsrows << "\tmeanStepLength\tstdStepLength\tmeanRho\tstdRho"; + if (trfr.indVar) { + if (trfr.moveModel) { + if (trfr.moveType == 2) { + outtraitsrows << "\tmeanStepLength\tstdStepLength\tmeanRho\tstdRho"; + } } - } - else { // dispersal kernel - if (trfr.sexDep) { - outtraitsrows << "\tF_mean_distI\tF_std_distI\tM_mean_distI\tM_std_distI"; - if (trfr.twinKern) - outtraitsrows << "\tF_mean_distII\tF_std_distII\tM_mean_distII\tM_std_distII" + else { // dispersal kernel + if (trfr.sexDep) { + outtraitsrows << "\tF_mean_distI\tF_std_distI\tM_mean_distI\tM_std_distI"; + if (trfr.twinKern) + outtraitsrows << "\tF_mean_distII\tF_std_distII\tM_mean_distII\tM_std_distII" << "\tF_meanPfirstKernel\tF_stdPfirstKernel" << "\tM_meanPfirstKernel\tM_stdPfirstKernel"; - } - else { - outtraitsrows << "\tmean_distI\tstd_distI"; - if (trfr.twinKern) - outtraitsrows << "\tmean_distII\tstd_distII\tmeanPfirstKernel\tstdPfirstKernel"; + } + else { + outtraitsrows << "\tmean_distI\tstd_distI"; + if (trfr.twinKern) + outtraitsrows << "\tmean_distII\tstd_distII\tmeanPfirstKernel\tstdPfirstKernel"; + } } } -} -if (sett.indVar) { -// if (sett.sexDep) { -// outtraitsrows << "\tF_meanS0\tF_stdS0\tM_meanS0\tM_stdS0"; -// outtraitsrows << "\tF_meanAlphaS\tF_stdAlphaS\tM_meanAlphaS\tM_stdAlphaS"; -// outtraitsrows << "\tF_meanBetaS\tF_stdBetaS\tM_meanBetaS\tM_stdBetaS"; -// } -// else { + if (sett.indVar) { + // if (sett.sexDep) { + // outtraitsrows << "\tF_meanS0\tF_stdS0\tM_meanS0\tM_stdS0"; + // outtraitsrows << "\tF_meanAlphaS\tF_stdAlphaS\tM_meanAlphaS\tM_stdAlphaS"; + // outtraitsrows << "\tF_meanBetaS\tF_stdBetaS\tM_meanBetaS\tM_stdBetaS"; + // } + // else { outtraitsrows << "\tmeanS0\tstdS0"; outtraitsrows << "\tmeanAlphaS\tstdAlphaS"; outtraitsrows << "\tmeanBetaS\tstdBetaS"; -// } -} -outtraitsrows << endl; + // } + } + outtraitsrows << endl; -return outtraitsrows.is_open(); + return outtraitsrows.is_open(); } @@ -1673,34 +1673,36 @@ return outtraitsrows.is_open(); Rcpp::IntegerMatrix Community::addYearToPopList(int rep, int yr) { // TODO: define new simparams to control start and interval of output landParams ppLand = pLandscape->getLandParams(); - Rcpp::IntegerMatrix pop_map_year(ppLand.dimY,ppLand.dimX); + Rcpp::IntegerMatrix pop_map_year(ppLand.dimY, ppLand.dimX); intptr patch = 0; Patch* pPatch = 0; intptr subcomm = 0; - SubCommunity *pSubComm = 0; + SubCommunity* pSubComm = 0; popStats pop; //pop.breeding = false; pop.nInds = pop.nAdults = pop.nNonJuvs = 0; for (int y = 0; y < ppLand.dimY; y++) { for (int x = 0; x < ppLand.dimX; x++) { - Cell *pCell = pLandscape->findCell(x,y); //if (pLandscape->cells[y][x] == 0) { + Cell* pCell = pLandscape->findCell(x, y); //if (pLandscape->cells[y][x] == 0) { if (pCell == 0) { // no-data cell - pop_map_year(ppLand.dimY-1-y,x) = NA_INTEGER; - } else { + pop_map_year(ppLand.dimY - 1 - y, x) = NA_INTEGER; + } + else { patch = pCell->getPatch(); if (patch == 0) { // matrix cell - pop_map_year(ppLand.dimY-1-y,x) = 0; + pop_map_year(ppLand.dimY - 1 - y, x) = 0; } - else{ + else { pPatch = (Patch*)patch; subcomm = pPatch->getSubComm(); if (subcomm == 0) { // check if sub-community exists - pop_map_year(ppLand.dimY-1-y,x) = 0; - } else { + pop_map_year(ppLand.dimY - 1 - y, x) = 0; + } + else { pSubComm = (SubCommunity*)subcomm; pop = pSubComm->getPopStats(); - pop_map_year(ppLand.dimY-1-y,x) = pop.nInds; // use indices like this because matrix gets transposed upon casting it into a raster on R-level + pop_map_year(ppLand.dimY - 1 - y, x) = pop.nInds; // use indices like this because matrix gets transposed upon casting it into a raster on R-level //pop_map_year(ppLand.dimY-1-y,x) = pop.nAdults; } } @@ -1708,7 +1710,7 @@ Rcpp::IntegerMatrix Community::addYearToPopList(int rep, int yr) { // TODO: def } } //list_outPop.push_back(pop_map_year, "rep" + std::to_string(rep) + "_year" + std::to_string(yr)); - return pop_map_year; + return pop_map_year; } #endif diff --git a/FractalGenerator.cpp b/FractalGenerator.cpp index 7a5ccc3..e423059 100644 --- a/FractalGenerator.cpp +++ b/FractalGenerator.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "FractalGenerator.h" //--------------------------------------------------------------------------- @@ -29,211 +29,211 @@ vector patches; //----- Landscape creation -------------------------------------------------- -land::land(): x_coord(0), y_coord(0), value(0.0), avail(0) {} +land::land() : x_coord(0), y_coord(0), value(0.0), avail(0) {} bool compare(const land& z, const land& zz) //compares only the values of the cells { -return z.value < zz.value; + return z.value < zz.value; } -vector& fractal_landscape(int X,int Y,double Hurst,double prop, - double maxValue,double minValue) +vector& fractal_landscape(int X, int Y, double Hurst, double prop, + double maxValue, double minValue) { #if RSDEBUG -DEBUGLOG << "fractal_landscape(): X=" << X << " Y=" << Y - << " Hurst=" << Hurst << " prop=" << prop - << " maxValue=" << maxValue << " minValue=" << minValue - << endl; + DEBUGLOG << "fractal_landscape(): X=" << X << " Y=" << Y + << " Hurst=" << Hurst << " prop=" << prop + << " maxValue=" << maxValue << " minValue=" << minValue + << endl; #endif -int ii, jj, x, y; -int ix, iy; -//int x0, y0, size, kx, kx2, ky, ky2; -int kx,kx2,ky,ky2; + int ii, jj, x, y; + int ix, iy; + //int x0, y0, size, kx, kx2, ky, ky2; + int kx, kx2, ky, ky2; -double range; //range to draw random numbers at each iteration -double nx, ny; -double i, j; -int Nx = X; -int Ny = Y; + double range; //range to draw random numbers at each iteration + double nx, ny; + double i, j; + int Nx = X; + int Ny = Y; -double ran[5]; // to store each time the 5 random numbers for the random displacement + double ran[5]; // to store each time the 5 random numbers for the random displacement -int Nno; // number of cells NON suitable as habitat + int Nno; // number of cells NON suitable as habitat -// exponents used to obtain the landscape dimensions -double pow2x = log(((double)X-1.0))/log(2.0); -double pow2y = log(((double)Y-1.0))/log(2.0); - -double **arena = new double *[X]; -for(ii = 0; ii < X; ii++) { - arena[ii] = new double[Y]; -} + // exponents used to obtain the landscape dimensions + double pow2x = log(((double)X - 1.0)) / log(2.0); + double pow2y = log(((double)Y - 1.0)) / log(2.0); -patches.clear(); -// initialise all the landscape with zeroes -for (jj = 0; jj < X; jj++) { - for (ii = 0; ii < Y; ii++) { - arena[jj][ii]=0; + double** arena = new double* [X]; + for (ii = 0; ii < X; ii++) { + arena[ii] = new double[Y]; } -} - -// initialisation of the four corners -arena[0][0] = 1.0 + pRandom->Random() * (maxValue-1.0); -arena[0][Y-1] = 1.0 + pRandom->Random() * (maxValue-1.0); -arena[X-1][0] = 1.0 + pRandom->Random() * (maxValue-1.0); -arena[X-1][Y-1] = 1.0 + pRandom->Random() * (maxValue-1.0); - -/////////////MIDPOINT DISPLACEMENT ALGORITHM////////////////////////////////// -kx = (Nx-1) / 2; -kx2 = 2 * kx; -ky = (Ny-1) / 2; -ky2 = 2 * ky; - -for (ii = 0; ii < 5; ii++) //random displacement -{ - ran[ii] = 1.0 + pRandom->Random() * (maxValue-1.0); -} - -//The diamond step: -arena[kx][ky] = ((arena[0][0] + arena[0][ky2] + arena[kx2][0] + arena[kx2][ky2])/4) + ran[0]; -//The square step: -//left -arena[0][ky] = ((arena[0][0] +arena[0][ky2] + arena[kx][ky]) / 3) + ran[1]; -//top -arena[kx][0] = ((arena[0][0] + arena[kx][ky] + arena[kx2][0]) / 3) + ran[2]; -//right -arena[kx2][ky] = ((arena[kx2][0] + arena[kx][ky] + arena[kx2][ky2]) / 3) + ran[3]; -//bottom -arena[kx][ky2] = ((arena[0][ky2] + arena[kx][ky] +arena[kx2][ky2]) / 3) + ran[4]; - -range = maxValue*pow(2,-Hurst); + patches.clear(); + // initialise all the landscape with zeroes + for (jj = 0; jj < X; jj++) { + for (ii = 0; ii < Y; ii++) { + arena[jj][ii] = 0; + } + } -i = pow2x-1; -j = pow2y-1; + // initialisation of the four corners + arena[0][0] = 1.0 + pRandom->Random() * (maxValue - 1.0); + arena[0][Y - 1] = 1.0 + pRandom->Random() * (maxValue - 1.0); + arena[X - 1][0] = 1.0 + pRandom->Random() * (maxValue - 1.0); + arena[X - 1][Y - 1] = 1.0 + pRandom->Random() * (maxValue - 1.0); -while (i > 0) { - nx = pow(2,i)+1; - kx = (int)((nx-1) / 2); + /////////////MIDPOINT DISPLACEMENT ALGORITHM////////////////////////////////// + kx = (Nx - 1) / 2; kx2 = 2 * kx; - - ny = pow(2,j)+1; - ky = (int)((ny-1) / 2); + ky = (Ny - 1) / 2; ky2 = 2 * ky; - ix = 0; - while (ix <= (Nx-nx)) { - iy = 0; - while (iy <= (Ny-ny)) { - for (ii = 0; ii < 5; ii++) //random displacement - { - ran[ii] = (int)(pRandom->Random() * 2.0 * range - range); + for (ii = 0; ii < 5; ii++) //random displacement + { + ran[ii] = 1.0 + pRandom->Random() * (maxValue - 1.0); + } + + //The diamond step: + arena[kx][ky] = ((arena[0][0] + arena[0][ky2] + arena[kx2][0] + arena[kx2][ky2]) / 4) + ran[0]; + + //The square step: + //left + arena[0][ky] = ((arena[0][0] + arena[0][ky2] + arena[kx][ky]) / 3) + ran[1]; + //top + arena[kx][0] = ((arena[0][0] + arena[kx][ky] + arena[kx2][0]) / 3) + ran[2]; + //right + arena[kx2][ky] = ((arena[kx2][0] + arena[kx][ky] + arena[kx2][ky2]) / 3) + ran[3]; + //bottom + arena[kx][ky2] = ((arena[0][ky2] + arena[kx][ky] + arena[kx2][ky2]) / 3) + ran[4]; + + range = maxValue * pow(2, -Hurst); + + i = pow2x - 1; + j = pow2y - 1; + + while (i > 0) { + nx = pow(2, i) + 1; + kx = (int)((nx - 1) / 2); + kx2 = 2 * kx; + + ny = pow(2, j) + 1; + ky = (int)((ny - 1) / 2); + ky2 = 2 * ky; + + ix = 0; + while (ix <= (Nx - nx)) { + iy = 0; + while (iy <= (Ny - ny)) { + for (ii = 0; ii < 5; ii++) //random displacement + { + ran[ii] = (int)(pRandom->Random() * 2.0 * range - range); + } + //The diamond step: + + arena[ix + kx][iy + ky] = ((arena[ix][iy] + arena[ix][iy + ky2] + arena[ix + ky2][iy] + + arena[ix + kx2][iy + ky2]) / 4) + ran[0]; + if (arena[ix + kx][iy + ky] < 1) arena[ix + kx][iy + ky] = 1; + + //The square step: + //left + arena[ix][iy + ky] = ((arena[ix][iy] + arena[ix][iy + ky2] + arena[ix + kx][iy + ky]) / 3) + + ran[1]; + if (arena[ix][iy + ky] < 1) arena[ix][iy + ky] = 1; + //top + arena[ix + kx][iy] = ((arena[ix][iy] + arena[ix + kx][iy + ky] + arena[ix + kx2][iy]) / 3) + + ran[2]; + if (arena[ix + kx][iy] < 1) arena[ix + kx][iy] = 1; + //right + arena[ix + kx2][iy + ky] = ((arena[ix + kx2][iy] + arena[ix + kx][iy + ky] + + arena[ix + kx2][iy + ky2]) / 3) + ran[3]; + if (arena[ix + kx2][iy + ky] < 1) arena[ix + kx2][iy + ky] = 1; + //bottom + arena[ix + kx][iy + ky2] = ((arena[ix][iy + ky2] + arena[ix + kx][iy + ky] + + arena[ix + kx2][iy + ky2]) / 3) + ran[4]; + if (arena[ix + kx][iy + ky2] < 1) arena[ix + kx][iy + ky2] = 1; + + iy += ((int)ny - 1); } - //The diamond step: - - arena[ix+kx][iy+ky] = ((arena[ix][iy] + arena[ix][iy+ky2] + arena[ix+ky2][iy] - + arena[ix+kx2][iy+ky2])/ 4) + ran[0]; - if (arena[ix+kx][iy+ky] < 1) arena[ix+kx][iy+ky] = 1; - - //The square step: - //left - arena[ix][iy+ky] =((arena[ix][iy] +arena[ix][iy+ky2] + arena[ix+kx][iy+ky])/3) - + ran[1]; - if (arena[ix][iy+ky] < 1) arena[ix][iy+ky] = 1; - //top - arena[ix+kx][iy] =((arena[ix][iy] + arena[ix+kx][iy+ky] + arena[ix+kx2][iy])/3) - + ran[2]; - if (arena[ix+kx][iy] < 1) arena[ix+kx][iy] = 1; - //right - arena[ix+kx2][iy+ky] = ((arena[ix+kx2][iy] + arena[ix+kx][iy+ky] + - arena[ix+kx2][iy+ky2]) / 3) + ran[3]; - if (arena[ix+kx2][iy+ky] < 1) arena[ix+kx2][iy+ky] = 1; - //bottom - arena[ix+kx][iy+ky2] = ((arena[ix][iy+ky2] + arena[ix+kx][iy+ky] + - arena[ix+kx2][iy+ky2]) / 3) + ran[4]; - if (arena[ix+kx][iy+ky2] < 1) arena[ix+kx][iy+ky2] = 1; - - iy += ((int)ny-1); + ix += ((int)nx - 1); } - ix += ((int)nx-1); - } - if (i==j) j--; - i--; + if (i == j) j--; + i--; - range = range*pow(2,-Hurst); //reduce the random number range -} + range = range * pow(2, -Hurst); //reduce the random number range + } -// Now all the cells will be sorted and the Nno cells with the lower carrying -// capacity will be set as matrix, i.e. with K = 0 + // Now all the cells will be sorted and the Nno cells with the lower carrying + // capacity will be set as matrix, i.e. with K = 0 -land *patch; + land* patch; -for (x = 0; x < X; x++) // put all the cells with their values in a vector -{ - for (y = 0; y < Y; y++) + for (x = 0; x < X; x++) // put all the cells with their values in a vector { - patch = new land; - patch->x_coord = x; - patch->y_coord = y; - patch->value = (float)arena[x][y]; - patch->avail = 1; + for (y = 0; y < Y; y++) + { + patch = new land; + patch->x_coord = x; + patch->y_coord = y; + patch->value = (float)arena[x][y]; + patch->avail = 1; - patches.push_back(*patch); + patches.push_back(*patch); - delete patch; + delete patch; + } } -} -sort(patches.begin(),patches.end(),compare); // sorts the vector + sort(patches.begin(), patches.end(), compare); // sorts the vector -Nno = (int)(prop*X*Y); -for (ii = 0; ii < Nno; ii++) -{ - patches[ii].value = 0.0; - patches[ii].avail = 0; -} + Nno = (int)(prop * X * Y); + for (ii = 0; ii < Nno; ii++) + { + patches[ii].value = 0.0; + patches[ii].avail = 0; + } -double min = (double)patches[Nno].value; // variables for the rescaling -double max = (double)patches[X*Y-1].value; + double min = (double)patches[Nno].value; // variables for the rescaling + double max = (double)patches[X * Y - 1].value; -double diff = max - min; -double diffK = maxValue-minValue; -double new_value; + double diff = max - min; + double diffK = maxValue - minValue; + double new_value; -vector::iterator iter = patches.begin(); -while (iter != patches.end()) -{ - if (iter->value > 0) // rescale to a range of K between Kmin and Kmax + vector::iterator iter = patches.begin(); + while (iter != patches.end()) { - new_value = maxValue - diffK * (max - (double)iter->value) / diff; + if (iter->value > 0) // rescale to a range of K between Kmin and Kmax + { + new_value = maxValue - diffK * (max - (double)iter->value) / diff; - iter->value = (float)new_value; - } - else iter->value = 0; + iter->value = (float)new_value; + } + else iter->value = 0; - iter++; -} + iter++; + } -if (arena != NULL) { + if (arena != NULL) { #if RSDEBUG -//DebugGUI(("fractal_landscape(): arena=" + Int2Str((int)arena) -// + " X=" + Int2Str(X) + " Y=" + Int2Str(Y) -// ).c_str()); + //DebugGUI(("fractal_landscape(): arena=" + Int2Str((int)arena) + // + " X=" + Int2Str(X) + " Y=" + Int2Str(Y) + // ).c_str()); #endif - for(ii = 0; ii < X; ii++) { + for (ii = 0; ii < X; ii++) { #if RSDEBUG -//DebugGUI(("fractal_landscape(): ii=" + Int2Str(ii) -// + " arena[ii]=" + Int2Str((int)arena[ii]) -// ).c_str()); + //DebugGUI(("fractal_landscape(): ii=" + Int2Str(ii) + // + " arena[ii]=" + Int2Str((int)arena[ii]) + // ).c_str()); #endif - delete[] arena[ii]; + delete[] arena[ii]; + } + delete[] arena; } - delete[] arena; -} -return patches; + return patches; } diff --git a/FractalGenerator.h b/FractalGenerator.h index 24acbc7..5e7e9f9 100644 --- a/FractalGenerator.h +++ b/FractalGenerator.h @@ -1,66 +1,66 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ -RangeShifter v2.0 FractalGenerator -Implements the midpoint displacement algorithm for generating a fractal Landscape, -following: + /*------------------------------------------------------------------------------ -Saupe, D. (1988). Algorithms for random fractals. In: The Science of Fractal Images -(eds. Pietgen, H.O. & Saupe, D.). Springer, New York, pp. 71–113. + RangeShifter v2.0 FractalGenerator + Implements the midpoint displacement algorithm for generating a fractal Landscape, + following: -For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. -and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. -Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 + Saupe, D. (1988). Algorithms for random fractals. In: The Science of Fractal Images + (eds. Pietgen, H.O. & Saupe, D.). Springer, New York, pp. 71–113. -Authors: Greta Bocedi & Steve Palmer, University of Aberdeen -Last updated: 15 July 2021 by Anne-Kathleen Malchow + For full details of RangeShifter, please see: + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. + and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial + eco-evolutionary dynamics and species’ responses to environmental changes. + Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 -------------------------------------------------------------------------------*/ + Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + + Last updated: 15 July 2021 by Anne-Kathleen Malchow + + ------------------------------------------------------------------------------*/ #ifndef FractalGeneratorH #define FractalGeneratorH #include #include -//using namespace std; + //using namespace std; #include "Parameters.h" class land { - public: +public: land(); int x_coord; int y_coord; float value; int avail; // if 0 the patch is not available as habitat, if 1 it is - private: +private: }; // IMPORTANT NOTE: X AND Y ARE TRANSPOSED, i.e. X IS THE VERTICAL CO-ORDINATE @@ -76,7 +76,7 @@ vector& fractal_landscape( ); bool compare(const land&, const land&); -extern RSrandom *pRandom; +extern RSrandom* pRandom; #if RSDEBUG extern void DebugGUI(string); #endif diff --git a/Genome.cpp b/Genome.cpp index 90d030b..f19933f 100644 --- a/Genome.cpp +++ b/Genome.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Genome.h" //--------------------------------------------------------------------------- @@ -39,93 +39,93 @@ ofstream outGenetic; Chromosome::Chromosome(int nloc) { #if RSDEBUG -//DEBUGLOG << "Chromosome::Chromosome(): this=" << this -// << " nloc=" << nloc -//// << " maternalLoci.size()=" << maternalLoci.size() -//// << " paternalLoci.size()=" << paternalLoci.size() -// << endl; -//DebugGUI("Chromosome::Chromosome(): this=" + Int2Str((int)this) -// + " nloc=" + Int2Str(nloc) -//// + " maternalLoci.size()=" + Int2Str((int)maternalLoci.size()) -//// + " paternalLoci.size()=" + Int2Str((int)paternalLoci.size()) -// ); + //DEBUGLOG << "Chromosome::Chromosome(): this=" << this + // << " nloc=" << nloc + //// << " maternalLoci.size()=" << maternalLoci.size() + //// << " paternalLoci.size()=" << paternalLoci.size() + // << endl; + //DebugGUI("Chromosome::Chromosome(): this=" + Int2Str((int)this) + // + " nloc=" + Int2Str(nloc) + //// + " maternalLoci.size()=" + Int2Str((int)maternalLoci.size()) + //// + " paternalLoci.size()=" + Int2Str((int)paternalLoci.size()) + // ); #endif -if (nloc > 0) nloci = nloc; else nloci = 1; -pLoci = new locus[nloci]; -for (int i = 0; i < nloci; i++) { - pLoci[i].allele[0] = pLoci[i].allele[1] = 0; -} + if (nloc > 0) nloci = nloc; else nloci = 1; + pLoci = new locus[nloci]; + for (int i = 0; i < nloci; i++) { + pLoci[i].allele[0] = pLoci[i].allele[1] = 0; + } } Chromosome::~Chromosome() { #if RSDEBUG -//DEBUGLOG << "Chromosome::~Chromosome(): this=" << this << endl; + //DEBUGLOG << "Chromosome::~Chromosome(): this=" << this << endl; #endif #if RSDEBUG //DEBUGLOG << "Chromosome::Chromosome(): deleting this=" << this << endl; //DebugGUI("Chromosome::Chromosome(): deleting this=" + Int2Str((int)this)); #endif -if (pLoci != 0) { -// for (int i = 0; i < nloci; i++) { -// delete pLoci[i]; pLoci[i] = NULL; -// } - delete[] pLoci; pLoci = NULL; -} + if (pLoci != 0) { + // for (int i = 0; i < nloci; i++) { + // delete pLoci[i]; pLoci[i] = NULL; + // } + delete[] pLoci; pLoci = NULL; + } } short Chromosome::nLoci(void) { return nloci; } locus Chromosome::alleles(const int loc) { // return allele values at a specified locus -locus l; l.allele[0] = l.allele[1] = 0; -if (loc >= 0 && loc < nloci) { - l.allele[0] = pLoci[loc].allele[0]; l.allele[1] = pLoci[loc].allele[1]; -} -return l; + locus l; l.allele[0] = l.allele[1] = 0; + if (loc >= 0 && loc < nloci) { + l.allele[0] = pLoci[loc].allele[0]; l.allele[1] = pLoci[loc].allele[1]; + } + return l; } double Chromosome::additive(const bool diploid) { -int sum = 0; -for (int i = 0; i < nloci; i++) { - sum += pLoci[i].allele[0]; - if (diploid) sum += pLoci[i].allele[1]; -} + int sum = 0; + for (int i = 0; i < nloci; i++) { + sum += pLoci[i].allele[0]; + if (diploid) sum += pLoci[i].allele[1]; + } #if RSDEBUG -//DEBUGLOG << "Chromosome::additive(): this=" << this -// << " sum=" << sum -// << endl; + //DEBUGLOG << "Chromosome::additive(): this=" << this + // << " sum=" << sum + // << endl; #endif -return (double)sum / INTBASE; + return (double)sum / INTBASE; } double Chromosome::meanvalue(const bool diploid) { -int sum = 0; -double mean; -for (int i = 0; i < nloci; i++) { - sum += pLoci[i].allele[0]; - if (diploid) sum += pLoci[i].allele[1]; -} -mean = (double)sum / (double)nloci; -if (diploid) mean /= 2.0; -mean /= INTBASE; + int sum = 0; + double mean; + for (int i = 0; i < nloci; i++) { + sum += pLoci[i].allele[0]; + if (diploid) sum += pLoci[i].allele[1]; + } + mean = (double)sum / (double)nloci; + if (diploid) mean /= 2.0; + mean /= INTBASE; #if RSDEBUG -//DEBUGLOG << "Chromosome::meanvalue(): this=" << this -// << " sum=" << sum -// << " mean=" << mean -// << endl; + //DEBUGLOG << "Chromosome::meanvalue(): this=" << this + // << " sum=" << sum + // << " mean=" << mean + // << endl; #endif -return mean; + return mean; } -double Chromosome::additive(const short loc,const bool diploid) { -int sum = 0; -sum += pLoci[loc].allele[0]; -if (diploid) sum += pLoci[loc].allele[1]; +double Chromosome::additive(const short loc, const bool diploid) { + int sum = 0; + sum += pLoci[loc].allele[0]; + if (diploid) sum += pLoci[loc].allele[1]; #if RSDEBUG -//DEBUGLOG << "Chromosome::additive(): this=" << this -// << " sum=" << sum -// << endl; + //DEBUGLOG << "Chromosome::additive(): this=" << this + // << " sum=" << sum + // << endl; #endif -return (double)sum / INTBASE; + return (double)sum / INTBASE; } /* @@ -152,119 +152,119 @@ return phenval; // Set up chromosome at simulation initialisation //void Chromosome::initialise(const float mean,const float sd, // const bool diploid) { -void Chromosome::initialise(const double mean, const double sd, - const bool diploid) { -double avalue; -double intbase = INTBASE; -//// adjust mean and s.d. allowing for number of alleles determining phenotype -//double adjmean,adjsd,factor; -//if (diploid) factor = (double)(nloci * 2); else factor = (double)(nloci); -//adjmean = mean / factor; -//adjsd = sqrt(sd * sd / factor); -for (int i = 0; i < nloci; i++) { -// avalue = pRandom->Normal(adjmean,adjsd); - avalue = pRandom->Normal(mean,sd); - if (avalue > 0.0) - pLoci[i].allele[0] = (int)(avalue * intbase + 0.5); - else - pLoci[i].allele[0] = (int)(avalue * intbase - 0.5); -#if RSDEBUG -//DEBUGLOG << "Chromosome::initialise(): this=" << this -// << " mean=" << mean << " sd=" << sd -// << " i=" << i << " avalue=" << avalue -// << " allele[0]=" << pLoci[i].allele[0]; -//DEBUGLOG << endl; -#endif - if (diploid) { -// avalue = pRandom->Normal(adjmean,adjsd); - avalue = pRandom->Normal(mean,sd); +void Chromosome::initialise(const double mean, const double sd, + const bool diploid) { + double avalue; + double intbase = INTBASE; + //// adjust mean and s.d. allowing for number of alleles determining phenotype + //double adjmean,adjsd,factor; + //if (diploid) factor = (double)(nloci * 2); else factor = (double)(nloci); + //adjmean = mean / factor; + //adjsd = sqrt(sd * sd / factor); + for (int i = 0; i < nloci; i++) { + // avalue = pRandom->Normal(adjmean,adjsd); + avalue = pRandom->Normal(mean, sd); if (avalue > 0.0) - pLoci[i].allele[1] = (int)(avalue * intbase + 0.5); + pLoci[i].allele[0] = (int)(avalue * intbase + 0.5); else - pLoci[i].allele[1] = (int)(avalue * intbase - 0.5); + pLoci[i].allele[0] = (int)(avalue * intbase - 0.5); +#if RSDEBUG + //DEBUGLOG << "Chromosome::initialise(): this=" << this + // << " mean=" << mean << " sd=" << sd + // << " i=" << i << " avalue=" << avalue + // << " allele[0]=" << pLoci[i].allele[0]; + //DEBUGLOG << endl; +#endif + if (diploid) { + // avalue = pRandom->Normal(adjmean,adjsd); + avalue = pRandom->Normal(mean, sd); + if (avalue > 0.0) + pLoci[i].allele[1] = (int)(avalue * intbase + 0.5); + else + pLoci[i].allele[1] = (int)(avalue * intbase - 0.5); #if RSDEBUG -//DEBUGLOG << "Chromosome::initialise(): this=" << this -// << " mean=" << mean << " sd=" << sd -// << " i=" << i << " avalue=" << avalue -// << " allele[1]=" << pLoci[i].allele[1]; -//DEBUGLOG << endl; + //DEBUGLOG << "Chromosome::initialise(): this=" << this + // << " mean=" << mean << " sd=" << sd + // << " i=" << i << " avalue=" << avalue + // << " allele[1]=" << pLoci[i].allele[1]; + //DEBUGLOG << endl; #endif + } } -} } // Set up specified locus at simulation initialisation -void Chromosome::initialise(const short locus,const short posn,const int aval) +void Chromosome::initialise(const short locus, const short posn, const int aval) { -// note that initialising value is ADDED to current value to allow for pleiotropy -pLoci[locus].allele[posn] += aval; + // note that initialising value is ADDED to current value to allow for pleiotropy + pLoci[locus].allele[posn] += aval; } // Inherit from specified parent -void Chromosome::inherit(const Chromosome *parentChr,const short posn,const short nloc, - const double probmutn,const double probcross,const double mutnSD,const bool diploid) +void Chromosome::inherit(const Chromosome* parentChr, const short posn, const short nloc, + const double probmutn, const double probcross, const double mutnSD, const bool diploid) { -// NOTE: At present for diploid genome, presence of crossover is determined at each -// locus (except first). However, Roslyn has shown that it is more efficient to sample -// crossover locations from geometric distribution if number of loci is large. -// HOW LARGE IS 'LARGE' IN THIS CASE?... - -//// adjust mutation variance for number of loci -//double mutnsd; -//if (diploid) -// mutnsd = sqrt(mutnSD * mutnSD / (double)(2*nloc)); -//else -// mutnsd = sqrt(mutnSD * mutnSD / (double)nloc); -int ix = 0; // indexes maternal and paternal strands -if (diploid) ix = pRandom->Bernoulli(0.5); // start index at random -for (int i = 0; i < nloc; i++) { - if (diploid) { - pLoci[i].allele[posn] = parentChr->pLoci[i].allele[ix]; - if (pRandom->Bernoulli(probcross)) { // crossover occurs - if (ix == 0) ix = 1; else ix = 0; + // NOTE: At present for diploid genome, presence of crossover is determined at each + // locus (except first). However, Roslyn has shown that it is more efficient to sample + // crossover locations from geometric distribution if number of loci is large. + // HOW LARGE IS 'LARGE' IN THIS CASE?... + + //// adjust mutation variance for number of loci + //double mutnsd; + //if (diploid) + // mutnsd = sqrt(mutnSD * mutnSD / (double)(2*nloc)); + //else + // mutnsd = sqrt(mutnSD * mutnSD / (double)nloc); + int ix = 0; // indexes maternal and paternal strands + if (diploid) ix = pRandom->Bernoulli(0.5); // start index at random + for (int i = 0; i < nloc; i++) { + if (diploid) { + pLoci[i].allele[posn] = parentChr->pLoci[i].allele[ix]; + if (pRandom->Bernoulli(probcross)) { // crossover occurs + if (ix == 0) ix = 1; else ix = 0; + } } - } - else - pLoci[i].allele[posn] = parentChr->pLoci[i].allele[0]; + else + pLoci[i].allele[posn] = parentChr->pLoci[i].allele[0]; #if RSDEBUG -//DEBUGLOG << "Chromosome::inherit(): this=" << this -// << " posn=" << posn << " nloc=" << nloc << " pmutn=" << pmutn -// << " i=" << i << " allele=" << pLoci[i].allele[posn] -// << endl; + //DEBUGLOG << "Chromosome::inherit(): this=" << this + // << " posn=" << posn << " nloc=" << nloc << " pmutn=" << pmutn + // << " i=" << i << " allele=" << pLoci[i].allele[posn] + // << endl; #endif - if (pRandom->Bernoulli(probmutn)) { // mutation occurs - double intbase = INTBASE; + if (pRandom->Bernoulli(probmutn)) { // mutation occurs + double intbase = INTBASE; #if RSDEBUG - int oldval = pLoci[i].allele[posn]; + int oldval = pLoci[i].allele[posn]; #endif -// double mutnvalue = pRandom->Normal(0,mutnsd); - double mutnvalue = pRandom->Normal(0,mutnSD); - if (mutnvalue > 0.0) - pLoci[i].allele[posn] += (int)(intbase * mutnvalue + 0.5); - else - pLoci[i].allele[posn] += (int)(intbase * mutnvalue - 0.5); + // double mutnvalue = pRandom->Normal(0,mutnsd); + double mutnvalue = pRandom->Normal(0, mutnSD); + if (mutnvalue > 0.0) + pLoci[i].allele[posn] += (int)(intbase * mutnvalue + 0.5); + else + pLoci[i].allele[posn] += (int)(intbase * mutnvalue - 0.5); #if RSDEBUG -//DEBUGLOG << "Chromosome::inherit(): this=" << this -// << " probmutn=" << probmutn << " nloc=" << nloc -//// << " mutnsd=" << mutnsd -// << " mutnSD=" << mutnSD -// << " posn=" << posn << " locus=" << i << " MUTATED " -// << " old=" << oldval << " new=" << pLoci[i].allele[posn] -// << endl; + //DEBUGLOG << "Chromosome::inherit(): this=" << this + // << " probmutn=" << probmutn << " nloc=" << nloc + //// << " mutnsd=" << mutnsd + // << " mutnSD=" << mutnSD + // << " posn=" << posn << " locus=" << i << " MUTATED " + // << " old=" << oldval << " new=" << pLoci[i].allele[posn] + // << endl; #endif #if RSDEBUG //MUTNLOG << 1 << endl; -MUTNLOG << mutnvalue << " " << oldval << " " << pLoci[i].allele[posn] << " " << endl; + MUTNLOG << mutnvalue << " " << oldval << " " << pLoci[i].allele[posn] << " " << endl; #endif - } + } #if RSDEBUG -// else { -//MUTNLOG << 0 << endl; -// } + // else { + //MUTNLOG << 0 << endl; + // } #endif -} + } } @@ -273,80 +273,80 @@ MUTNLOG << mutnvalue << " " << oldval << " " << pLoci[i].allele[posn] << " " << // NB THIS FUNCTION IS CURRENTLY NOT BEING CALLED TO CONSTRUCT AN INSTANCE OF Genome // Genome(int) IS USED INSTEAD -Genome::Genome(){ -pChromosome = NULL; -nChromosomes = 0; +Genome::Genome() { + pChromosome = NULL; + nChromosomes = 0; } // Set up new genome at initialisation for 1 chromosome per trait -Genome::Genome(int nchromosomes,int nloci,bool d) { +Genome::Genome(int nchromosomes, int nloci, bool d) { #if RSDEBUG -//DEBUGLOG << "Genome::Genome(): this=" << this -// << " nchromosomes=" << nchromosomes << " nLoci=" << nLoci -// << endl; + //DEBUGLOG << "Genome::Genome(): this=" << this + // << " nchromosomes=" << nchromosomes << " nLoci=" << nLoci + // << endl; #endif -diploid = d; -if (nchromosomes > 0) nChromosomes = nchromosomes; else nChromosomes = 1; -pChromosome = new Chromosome *[nChromosomes]; -for (int i = 0; i < nChromosomes; i++) { - pChromosome[i] = new Chromosome(nloci); -// pChromosome[i]->initialise(alleleMean,alleleSD); -} + diploid = d; + if (nchromosomes > 0) nChromosomes = nchromosomes; else nChromosomes = 1; + pChromosome = new Chromosome * [nChromosomes]; + for (int i = 0; i < nChromosomes; i++) { + pChromosome[i] = new Chromosome(nloci); + // pChromosome[i]->initialise(alleleMean,alleleSD); + } } // Set up new genome at initialisation for trait mapping -Genome::Genome(Species *pSpecies) { -int nloci; -nChromosomes = pSpecies->getNChromosomes(); -diploid = pSpecies->isDiploid(); +Genome::Genome(Species* pSpecies) { + int nloci; + nChromosomes = pSpecies->getNChromosomes(); + diploid = pSpecies->isDiploid(); #if RSDEBUG -//DEBUGLOG << "Genome::Genome(): this=" << this -// << " nChromosomes=" << nChromosomes -// << endl; + //DEBUGLOG << "Genome::Genome(): this=" << this + // << " nChromosomes=" << nChromosomes + // << endl; #endif -pChromosome = new Chromosome *[nChromosomes]; -for (int i = 0; i < nChromosomes; i++) { - nloci = pSpecies->getNLoci(i); + pChromosome = new Chromosome * [nChromosomes]; + for (int i = 0; i < nChromosomes; i++) { + nloci = pSpecies->getNLoci(i); #if RSDEBUG -//DEBUGLOG << "Genome::Genome(): this=" << this -// << " i=" << i << " nloci=" << nloci << endl; + //DEBUGLOG << "Genome::Genome(): this=" << this + // << " i=" << i << " nloci=" << nloci << endl; #endif - pChromosome[i] = new Chromosome(nloci); -} + pChromosome[i] = new Chromosome(nloci); + } } // Inherit genome from parent(s) -Genome::Genome(Species *pSpecies,Genome *mother,Genome *father) +Genome::Genome(Species* pSpecies, Genome* mother, Genome* father) { -genomeData gen = pSpecies->getGenomeData(); - -nChromosomes = mother->nChromosomes; -diploid = mother->diploid; -pChromosome = new Chromosome *[nChromosomes]; - -for (int i = 0; i < nChromosomes; i++) { - pChromosome[i] = new Chromosome(mother->pChromosome[i]->nLoci()); - inherit(mother,0,i,gen.probMutn,gen.probCrossover,gen.mutationSD); - if (diploid) { - if (father == 0) { // species is hermaphrodite - inherit again from mother - inherit(mother,1,i,gen.probMutn,gen.probCrossover,gen.mutationSD); + genomeData gen = pSpecies->getGenomeData(); + + nChromosomes = mother->nChromosomes; + diploid = mother->diploid; + pChromosome = new Chromosome * [nChromosomes]; + + for (int i = 0; i < nChromosomes; i++) { + pChromosome[i] = new Chromosome(mother->pChromosome[i]->nLoci()); + inherit(mother, 0, i, gen.probMutn, gen.probCrossover, gen.mutationSD); + if (diploid) { + if (father == 0) { // species is hermaphrodite - inherit again from mother + inherit(mother, 1, i, gen.probMutn, gen.probCrossover, gen.mutationSD); + } + else inherit(father, 1, i, gen.probMutn, gen.probCrossover, gen.mutationSD); } - else inherit(father,1,i,gen.probMutn,gen.probCrossover,gen.mutationSD); } -} } -Genome::~Genome(){ +Genome::~Genome() { -if (pChromosome == NULL) return; + if (pChromosome == NULL) return; -for (int i = 0; i < nChromosomes; i++) { - delete pChromosome[i]; -} -delete[] pChromosome; + for (int i = 0; i < nChromosomes; i++) { + delete pChromosome[i]; + } + delete[] pChromosome; } @@ -368,93 +368,93 @@ short Genome::getNChromosomes(void) { return nChromosomes; } //--------------------------------------------------------------------------- // Inherit from specified parent -void Genome::inherit(const Genome *parent,const short posn,const short chr, - const double probmutn,const double probcross,const double mutnSD) +void Genome::inherit(const Genome* parent, const short posn, const short chr, + const double probmutn, const double probcross, const double mutnSD) { -// adjust mutation variance for number of loci -//double mutnSD = sqrt(mutationSD * mutationSD / (double)nLoci); -//for (int i = 0; i < nChromosomes; i++) { -// pChromosome[i]->inherit(parent->pChromosome[i],pChromosome[i]->nLoci()); -//} -pChromosome[chr]->inherit(parent->pChromosome[chr],posn,parent->pChromosome[chr]->nLoci(), - probmutn,probcross,mutnSD,diploid); + // adjust mutation variance for number of loci + //double mutnSD = sqrt(mutationSD * mutationSD / (double)nLoci); + //for (int i = 0; i < nChromosomes; i++) { + // pChromosome[i]->inherit(parent->pChromosome[i],pChromosome[i]->nLoci()); + //} + pChromosome[chr]->inherit(parent->pChromosome[chr], posn, parent->pChromosome[chr]->nLoci(), + probmutn, probcross, mutnSD, diploid); } -void Genome::outGenHeaders(const int rep,const int landNr,const bool xtab) +void Genome::outGenHeaders(const int rep, const int landNr, const bool xtab) { -if (landNr == -999) { // close file - if (outGenetic.is_open()) { - outGenetic.close(); outGenetic.clear(); + if (landNr == -999) { // close file + if (outGenetic.is_open()) { + outGenetic.close(); outGenetic.clear(); + } + return; } - return; -} -string name; -simParams sim = paramsSim->getSim(); + string name; + simParams sim = paramsSim->getSim(); -if (sim.batchMode) { - name = paramsSim->getDir(2) - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) - + "_Land" + Int2Str(landNr) + "_Rep" + Int2Str(rep) + "_Genetics.txt"; -} -else { - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) - + "_Rep" + Int2Str(rep) +"_Genetics.txt"; -} -outGenetic.open(name.c_str()); - -outGenetic << "Rep\tYear\tSpecies\tIndID"; -if (xtab) { - for (int i = 0; i < nChromosomes; i++) { - int nloci = pChromosome[i]->nLoci(); - for (int j = 0; j < nloci; j++) { - outGenetic << "\tChr" << i << "Loc" << j << "Allele0"; - if (diploid) outGenetic << "\tChr" << i << "Loc" << j << "Allele1"; + if (sim.batchMode) { + name = paramsSim->getDir(2) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + + "_Land" + Int2Str(landNr) + "_Rep" + Int2Str(rep) + "_Genetics.txt"; + } + else { + name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + + "_Rep" + Int2Str(rep) + "_Genetics.txt"; + } + outGenetic.open(name.c_str()); + + outGenetic << "Rep\tYear\tSpecies\tIndID"; + if (xtab) { + for (int i = 0; i < nChromosomes; i++) { + int nloci = pChromosome[i]->nLoci(); + for (int j = 0; j < nloci; j++) { + outGenetic << "\tChr" << i << "Loc" << j << "Allele0"; + if (diploid) outGenetic << "\tChr" << i << "Loc" << j << "Allele1"; + } } + outGenetic << endl; + } + else { + outGenetic << "\tChromosome\tLocus\tAllele0"; + if (diploid) outGenetic << "\tAllele1"; + outGenetic << endl; } - outGenetic << endl; -} -else { - outGenetic << "\tChromosome\tLocus\tAllele0"; - if (diploid) outGenetic << "\tAllele1"; - outGenetic << endl; -} } -void Genome::outGenetics(const int rep,const int year,const int spnum, - const int indID,const bool xtab) - { -locus l; -if (xtab) { - outGenetic << rep << "\t" << year << "\t" << spnum << "\t" << indID; - for (int i = 0; i < nChromosomes; i++) { - int nloci = pChromosome[i]->nLoci(); - for (int j = 0; j < nloci; j++) { - l = pChromosome[i]->alleles(j); - outGenetic << "\t" << l.allele[0]; - if (diploid) outGenetic << "\t" << l.allele[1]; +void Genome::outGenetics(const int rep, const int year, const int spnum, + const int indID, const bool xtab) +{ + locus l; + if (xtab) { + outGenetic << rep << "\t" << year << "\t" << spnum << "\t" << indID; + for (int i = 0; i < nChromosomes; i++) { + int nloci = pChromosome[i]->nLoci(); + for (int j = 0; j < nloci; j++) { + l = pChromosome[i]->alleles(j); + outGenetic << "\t" << l.allele[0]; + if (diploid) outGenetic << "\t" << l.allele[1]; + } } + outGenetic << endl; } - outGenetic << endl; -} -else { - for (int i = 0; i < nChromosomes; i++) { - int nloci = pChromosome[i]->nLoci(); - for (int j = 0; j < nloci; j++) { - outGenetic << rep << "\t" << year << "\t" << spnum << "\t" - << indID << "\t" << i << "\t" << j; - l = pChromosome[i]->alleles(j); - outGenetic << "\t" << l.allele[0]; - if (diploid) outGenetic << "\t" << l.allele[1]; - outGenetic << endl; + else { + for (int i = 0; i < nChromosomes; i++) { + int nloci = pChromosome[i]->nLoci(); + for (int j = 0; j < nloci; j++) { + outGenetic << rep << "\t" << year << "\t" << spnum << "\t" + << indID << "\t" << i << "\t" << j; + l = pChromosome[i]->alleles(j); + outGenetic << "\t" << l.allele[0]; + if (diploid) outGenetic << "\t" << l.allele[1]; + outGenetic << endl; + } } } } -} //--------------------------------------------------------------------------- @@ -462,119 +462,119 @@ else { //void Genome::setGene(const short chr,const short exp, // const float traitval,const float alleleSD) void Genome::setGene(const short chr, const short exp, - const double traitval, const double alleleSD) -// NB PARAMETER exp FOR EXPRESSION TYPE IS NOT CURRENTLY USED... + const double traitval, const double alleleSD) + // NB PARAMETER exp FOR EXPRESSION TYPE IS NOT CURRENTLY USED... { #if RSDEBUG -//DEBUGLOG << "Genome::setGene(): this=" << this -// << " chr=" << chr -// << " exp=" << exp << " traitval=" << traitval -// << " alleleSD=" << alleleSD -// << endl; + //DEBUGLOG << "Genome::setGene(): this=" << this + // << " chr=" << chr + // << " exp=" << exp << " traitval=" << traitval + // << " alleleSD=" << alleleSD + // << endl; #endif -if (chr >= 0 && chr < nChromosomes) { - pChromosome[chr]->initialise(traitval,alleleSD,diploid); -} + if (chr >= 0 && chr < nChromosomes) { + pChromosome[chr]->initialise(traitval, alleleSD, diploid); + } } // Set up trait at initialisation for trait mapping //void Genome::setTrait(Species *pSpecies,const int trait, // const float traitval,const float alleleSD) void Genome::setTrait(Species* pSpecies, const int trait, - const double traitval, const double alleleSD) + const double traitval, const double alleleSD) { -traitAllele allele; -int nalleles = pSpecies->getNTraitAlleles(trait); -int ntraitmaps = pSpecies->getNTraitMaps(); + traitAllele allele; + int nalleles = pSpecies->getNTraitAlleles(trait); + int ntraitmaps = pSpecies->getNTraitMaps(); #if RSDEBUG -//DEBUGLOG << "Genome::setTrait(): this=" << this << " ntraitmaps=" << ntraitmaps -// << " trait=" << trait << " traitval=" << traitval << " alleleSD=" << alleleSD -// << " nalleles=" << nalleles -// << endl; + //DEBUGLOG << "Genome::setTrait(): this=" << this << " ntraitmaps=" << ntraitmaps + // << " trait=" << trait << " traitval=" << traitval << " alleleSD=" << alleleSD + // << " nalleles=" << nalleles + // << endl; #endif -int avalue; -double intbase = INTBASE; -if (trait < ntraitmaps) { -// // adjust mean and s.d. allowing for number of alleles determining phenotype -// double adjmean,adjsd,factor; -// if (diploid) factor = (double)(nalleles * 2); else factor = (double)(nalleles); -// adjmean = traitval / factor; -// adjsd = sqrt(alleleSD * alleleSD / factor); - - for (int i = 0; i < nalleles; i++) { - allele = pSpecies->getTraitAllele(trait,i); -// avalue = (int)(pRandom->Normal(adjmean,adjsd) * intbase); - avalue = (int)(pRandom->Normal(traitval,alleleSD) * intbase); + int avalue; + double intbase = INTBASE; + if (trait < ntraitmaps) { + // // adjust mean and s.d. allowing for number of alleles determining phenotype + // double adjmean,adjsd,factor; + // if (diploid) factor = (double)(nalleles * 2); else factor = (double)(nalleles); + // adjmean = traitval / factor; + // adjsd = sqrt(alleleSD * alleleSD / factor); + + for (int i = 0; i < nalleles; i++) { + allele = pSpecies->getTraitAllele(trait, i); + // avalue = (int)(pRandom->Normal(adjmean,adjsd) * intbase); + avalue = (int)(pRandom->Normal(traitval, alleleSD) * intbase); #if RSDEBUG -//DEBUGLOG << "Genome::setTrait(): this=" << this -// << " i=" << i << " chromo=" << allele.chromo << " locus=" << allele.locus -// << " posn=" << 0 << " avalue=" << avalue -// << endl; + //DEBUGLOG << "Genome::setTrait(): this=" << this + // << " i=" << i << " chromo=" << allele.chromo << " locus=" << allele.locus + // << " posn=" << 0 << " avalue=" << avalue + // << endl; #endif - pChromosome[allele.chromo]->initialise(allele.locus,0,avalue); - if (diploid) { -// avalue = (int)(pRandom->Normal(adjmean,adjsd) * intbase); - avalue = (int)(pRandom->Normal(traitval,alleleSD) * intbase); - pChromosome[allele.chromo]->initialise(allele.locus,1,avalue); + pChromosome[allele.chromo]->initialise(allele.locus, 0, avalue); + if (diploid) { + // avalue = (int)(pRandom->Normal(adjmean,adjsd) * intbase); + avalue = (int)(pRandom->Normal(traitval, alleleSD) * intbase); + pChromosome[allele.chromo]->initialise(allele.locus, 1, avalue); + } } } -} -else { // insufficient traits were defined - // alleles cannot be initialised - all individuals have mean phenotype + else { // insufficient traits were defined + // alleles cannot be initialised - all individuals have mean phenotype #if RSDEBUG //DEBUGLOG << "Genome::setTrait(): this=" << this // << " *** unable to initialise undefined trait ***" << endl; #endif -} + } } // Set up trait at initialisation for trait mapping -void Genome::setNeutralLoci(Species *pSpecies,const double alleleSD) +void Genome::setNeutralLoci(Species* pSpecies, const double alleleSD) { -traitAllele allele; -int nneutral = pSpecies->getNNeutralLoci(); + traitAllele allele; + int nneutral = pSpecies->getNNeutralLoci(); #if RSDEBUG -//DEBUGLOG << "Genome::setNeutralLoci(): this=" << this -// << " nneutral=" << nneutral << " alleleSD=" << alleleSD -// << endl; + //DEBUGLOG << "Genome::setNeutralLoci(): this=" << this + // << " nneutral=" << nneutral << " alleleSD=" << alleleSD + // << endl; #endif //int avalue; -double avalue; -double intbase = INTBASE; -//// adjust allele s.d. for diploid genotype -//double adjsd,factor; -//if (diploid) factor = 2.0; else factor = 1.0; -//adjsd = sqrt(alleleSD * alleleSD / factor); - -for (int i = 0; i < nneutral; i++) { - allele = pSpecies->getNeutralAllele(i); -// avalue = (int)(pRandom->Normal(0.0,adjsd) * intbase); -// pChromosome[allele.chromo]->initialise(allele.locus,0,avalue); - avalue = pRandom->Normal(0.0,alleleSD); - if (avalue > 0.0) - pChromosome[allele.chromo]->initialise(allele.locus,0,(int)(avalue * intbase + 0.5)); - else - pChromosome[allele.chromo]->initialise(allele.locus,0,(int)(avalue * intbase - 0.5)); -#if RSDEBUG -//DEBUGLOG << "Genome::setNeutralLoci(): this=" << this -// << " i=" << i << " chromo=" << allele.chromo << " locus=" << allele.locus -// << " avalue=" << avalue -// << endl; -#endif - if (diploid) { -// avalue = (int)(pRandom->Normal(0.0,adjsd) * intbase); -// pChromosome[allele.chromo]->initialise(allele.locus,1,avalue); - avalue = pRandom->Normal(0.0,alleleSD); + double avalue; + double intbase = INTBASE; + //// adjust allele s.d. for diploid genotype + //double adjsd,factor; + //if (diploid) factor = 2.0; else factor = 1.0; + //adjsd = sqrt(alleleSD * alleleSD / factor); + + for (int i = 0; i < nneutral; i++) { + allele = pSpecies->getNeutralAllele(i); + // avalue = (int)(pRandom->Normal(0.0,adjsd) * intbase); + // pChromosome[allele.chromo]->initialise(allele.locus,0,avalue); + avalue = pRandom->Normal(0.0, alleleSD); if (avalue > 0.0) - pChromosome[allele.chromo]->initialise(allele.locus,1,(int)(avalue * intbase + 0.5)); + pChromosome[allele.chromo]->initialise(allele.locus, 0, (int)(avalue * intbase + 0.5)); else - pChromosome[allele.chromo]->initialise(allele.locus,1,(int)(avalue * intbase - 0.5)); + pChromosome[allele.chromo]->initialise(allele.locus, 0, (int)(avalue * intbase - 0.5)); +#if RSDEBUG + //DEBUGLOG << "Genome::setNeutralLoci(): this=" << this + // << " i=" << i << " chromo=" << allele.chromo << " locus=" << allele.locus + // << " avalue=" << avalue + // << endl; +#endif + if (diploid) { + // avalue = (int)(pRandom->Normal(0.0,adjsd) * intbase); + // pChromosome[allele.chromo]->initialise(allele.locus,1,avalue); + avalue = pRandom->Normal(0.0, alleleSD); + if (avalue > 0.0) + pChromosome[allele.chromo]->initialise(allele.locus, 1, (int)(avalue * intbase + 0.5)); + else + pChromosome[allele.chromo]->initialise(allele.locus, 1, (int)(avalue * intbase - 0.5)); + } } } -} // Return a single allele, having applied mutation // Either allele is returned with equal probability, unless the gene is sex-linked, @@ -589,22 +589,22 @@ return genevalue; */ // Return the expressed value of a gene when species has one chromosome per trait -double Genome::express(short chr,short expr,short indsex) +double Genome::express(short chr, short expr, short indsex) { -double genevalue = 0.0; -//if (expr == 1) { -// genevalue = pChromosome[chr]->probval(diploid); -//} -//else -//genevalue = pChromosome[chr]->additive(diploid); -genevalue = pChromosome[chr]->meanvalue(diploid); + double genevalue = 0.0; + //if (expr == 1) { + // genevalue = pChromosome[chr]->probval(diploid); + //} + //else + //genevalue = pChromosome[chr]->additive(diploid); + genevalue = pChromosome[chr]->meanvalue(diploid); #if RSDEBUG -//DEBUGLOG << "Genome::express(): this=" << this -// << " chr=" << chr -// << " genevalue=" << genevalue -// << endl; + //DEBUGLOG << "Genome::express(): this=" << this + // << " chr=" << chr + // << " genevalue=" << genevalue + // << endl; #endif -return genevalue; + return genevalue; } /* // Return the expressed value of an allele @@ -627,47 +627,47 @@ return genevalue; */ // Return the expressed value of a trait when genetic architecture is defined -double Genome::express(Species *pSpecies,short traitnum) +double Genome::express(Species* pSpecies, short traitnum) { -double genevalue = 0.0; - -traitAllele allele; -int nalleles = pSpecies->getNTraitAlleles(traitnum); -if (nalleles > 0) { - for (int i = 0; i < nalleles; i++) { - allele = pSpecies->getTraitAllele(traitnum,i); - genevalue += pChromosome[allele.chromo]->additive(allele.locus,diploid); + double genevalue = 0.0; + + traitAllele allele; + int nalleles = pSpecies->getNTraitAlleles(traitnum); + if (nalleles > 0) { + for (int i = 0; i < nalleles; i++) { + allele = pSpecies->getTraitAllele(traitnum, i); + genevalue += pChromosome[allele.chromo]->additive(allele.locus, diploid); + } + genevalue /= (double)nalleles; + if (diploid) genevalue /= 2.0; } - genevalue /= (double)nalleles; - if (diploid) genevalue /= 2.0; -} -// genevalue = pChromosome[chr]->additive(diploid); + // genevalue = pChromosome[chr]->additive(diploid); #if RSDEBUG //DEBUGLOG << "Genome::express(): this=" << this // << " traitnum=" << traitnum << " nalleles=" << nalleles // << " genevalue=" << genevalue // << endl; #endif -return genevalue; + return genevalue; } -locusOK Genome::getAlleles(short chr,short loc) { -locusOK l; -l.allele[0] = l.allele[1] = 0; l.ok = false; -//double intbase = INTBASE; -if (chr >= 0 && chr < nChromosomes) { - if (pChromosome[chr] != 0) { - if (loc >= 0 && loc < pChromosome[chr]->nLoci()) { - locus a = pChromosome[chr]->alleles(loc); - l.allele[0] = a.allele[0]; l.allele[1] = a.allele[1]; l.ok = true; +locusOK Genome::getAlleles(short chr, short loc) { + locusOK l; + l.allele[0] = l.allele[1] = 0; l.ok = false; + //double intbase = INTBASE; + if (chr >= 0 && chr < nChromosomes) { + if (pChromosome[chr] != 0) { + if (loc >= 0 && loc < pChromosome[chr]->nLoci()) { + locus a = pChromosome[chr]->alleles(loc); + l.allele[0] = a.allele[0]; l.allele[1] = a.allele[1]; l.ok = true; + } } } -} -// l.allele[0] = (int)(intbase * pChromosome[0]->additive(diploid)); + // l.allele[0] = (int)(intbase * pChromosome[0]->additive(diploid)); -return l; + return l; } //--------------------------------------------------------------------------- @@ -833,7 +833,7 @@ switch (genome[i]->expression) { genevalue = (genome[i]->allele[0] + genome[i]->allele[1]) / 2.0; // if (sexx == 0 || sexx == 1) genevalue = genome[i]->allele[sexx]; // else genevalue = -999999.999; // indicates error in sex of parent animal - break; + break; default: genevalue = -777777.777; // error in expression type } diff --git a/Genome.h b/Genome.h index d42c161..b19fee0 100644 --- a/Genome.h +++ b/Genome.h @@ -1,43 +1,43 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ -RangeShifter v2.0 Genome -Implements the Genome class + /*------------------------------------------------------------------------------ -Author: Steve Palmer & Roslyn Henry, University of Aberdeen + RangeShifter v2.0 Genome -Last updated: 28 July 2021 by Greta Bocedi + Implements the Genome class -------------------------------------------------------------------------------*/ + Author: Steve Palmer & Roslyn Henry, University of Aberdeen + + Last updated: 28 July 2021 by Greta Bocedi + + ------------------------------------------------------------------------------*/ #ifndef GenomeH #define GenomeH #include #include -//#include "maths.h" + //#include "maths.h" #include "Parameters.h" #include "Species.h" @@ -65,7 +65,7 @@ class Chromosome { const short, // locus const bool // diploid ); -// double probval(const bool); + // double probval(const bool); locus alleles( // Return allele values at a specified locus const int // position of locus on chromosome ); @@ -93,25 +93,25 @@ class Chromosome { private: short nloci; - locus *pLoci; + locus* pLoci; }; //--------------------------------------------------------------------------- -class Genome{ +class Genome { public: -// -// static float delPMutation, delEffectSize, delDominance, delBackMutation ,genomeMeanRecombination; -// static int delMaxSize, delNMutations; -// static bool genomeCanRecombine, genomeCompletelyUnlinked; -// + // + // static float delPMutation, delEffectSize, delDominance, delBackMutation ,genomeMeanRecombination; + // static int delMaxSize, delNMutations; + // static bool genomeCanRecombine, genomeCompletelyUnlinked; + // Genome(); - Genome(int,int,bool); + Genome(int, int, bool); Genome(Species*); - Genome(Species*,Genome*,Genome*); + Genome(Species*, Genome*, Genome*); ~Genome(); void setGene( // Set up new gene at initialisation for 1 chromosome per trait const short, // chromosome number @@ -129,23 +129,23 @@ class Genome{ Species*, // pointer to Species const double // s.d. of allelic variance ); -// double copy(int,int); + // double copy(int,int); double express( - // Return the expressed value of a gene when species has one chromosome per trait + // Return the expressed value of a gene when species has one chromosome per trait short, // chromosome number short, // expression type (NOT CURRENTLY USED) short // individual's sex (NOT CURRENTLY USED) ); -// double express( -// short, // chromosome number -// short // locus on chromosome -// ); + // double express( + // short, // chromosome number + // short // locus on chromosome + // ); double express( - // Return the expressed value of a trait when genetic architecture is defined + // Return the expressed value of a trait when genetic architecture is defined Species*, // pointer to Species short // trait number // bool // true if trait is sex-dependent - ); +); locusOK getAlleles( // Get allele values at a specified locus short, // chromosome number short // locus position on chromosome @@ -161,8 +161,8 @@ class Genome{ const double, // crossover probability const double // s.d. of mutation magnitude (genetic scale) ); -// void setStaticData(genomeData); -// genomeData getStaticData(void); + // void setStaticData(genomeData); + // genomeData getStaticData(void); short getNChromosomes(void); void outGenHeaders( const int, // replicate @@ -181,7 +181,7 @@ class Genome{ private: short nChromosomes; // no. of chromosomes bool diploid; - Chromosome **pChromosome; + Chromosome** pChromosome; }; @@ -237,8 +237,8 @@ class Genome //--------------------------------------------------------------------------- -extern paramSim *paramsSim; -extern RSrandom *pRandom; +extern paramSim* paramsSim; +extern RSrandom* pRandom; #if RSDEBUG extern ofstream DEBUGLOG; diff --git a/Individual.cpp b/Individual.cpp index 357f175..c756f6f 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Individual.h" //--------------------------------------------------------------------------- @@ -30,82 +30,82 @@ int Individual::indCounter = 0; //--------------------------------------------------------------------------- // Individual constructor -Individual::Individual(Cell *pCell,Patch *pPatch,short stg,short a,short repInt, - float probmale,bool movt,short moveType) +Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short repInt, + float probmale, bool movt, short moveType) { -indId = indCounter; indCounter++; // unique identifier for each individual + indId = indCounter; indCounter++; // unique identifier for each individual #if RSDEBUG -//DEBUGLOG << "Individual::Individual(): indId=" << indId -// << " stg=" << stg << " a=" << a << " probmale=" << probmale -// << endl; + //DEBUGLOG << "Individual::Individual(): indId=" << indId + // << " stg=" << stg << " a=" << a << " probmale=" << probmale + // << endl; #endif -stage = stg; -if (probmale <= 0.0) sex = 0; -else sex = pRandom->Bernoulli(probmale); -age = a; -status = 0; + stage = stg; + if (probmale <= 0.0) sex = 0; + else sex = pRandom->Bernoulli(probmale); + age = a; + status = 0; -if (sex == 0 && repInt > 0) { // set no. of fallow seasons for female - fallow = pRandom->IRandom(0,repInt); -} -else fallow = 9999; -isDeveloping = false; -pPrevCell = pCurrCell = pCell; -pNatalPatch = pPatch; -if (movt) { - locn loc = pCell->getLocn(); - path = new pathData; - path->year = 0; path->total = 0; path->out = 0; - path->pSettPatch = 0; path->settleStatus = 0; -// path->leftNatalPatch = false; + if (sex == 0 && repInt > 0) { // set no. of fallow seasons for female + fallow = pRandom->IRandom(0, repInt); + } + else fallow = 9999; + isDeveloping = false; + pPrevCell = pCurrCell = pCell; + pNatalPatch = pPatch; + if (movt) { + locn loc = pCell->getLocn(); + path = new pathData; + path->year = 0; path->total = 0; path->out = 0; + path->pSettPatch = 0; path->settleStatus = 0; + // path->leftNatalPatch = false; #if RS_RCPP - path->pathoutput = 1; -#endif - if (moveType == 1) { // SMS - // set up location data for SMS - smsData = new smsdata; - smsData->dp = smsData->gb = smsData->alphaDB = 1.0; - smsData->betaDB = 1; - smsData->prev.x = loc.x; smsData->prev.y = loc.y; // previous location - smsData->goal.x = loc.x; smsData->goal.y = loc.y; // goal location - initialised for dispersal bias - } - else smsData = 0; - if (moveType == 2) { // CRW - // set up continuous co-ordinates etc. for CRW movement - crw = new crwParams; - crw->xc = ((float)pRandom->Random()*0.999f) + (float)loc.x; - crw->yc = (float)(pRandom->Random()*0.999f) + (float)loc.y; - crw->prevdrn = (float)(pRandom->Random()*2.0 * PI); - crw->stepL = crw->rho = 0.0; - } - else crw = 0; -} -else { - path = 0; crw = 0; smsData = 0; -} -emigtraits = 0; -kerntraits = 0; -setttraits = 0; -pGenome = 0; + path->pathoutput = 1; +#endif + if (moveType == 1) { // SMS + // set up location data for SMS + smsData = new smsdata; + smsData->dp = smsData->gb = smsData->alphaDB = 1.0; + smsData->betaDB = 1; + smsData->prev.x = loc.x; smsData->prev.y = loc.y; // previous location + smsData->goal.x = loc.x; smsData->goal.y = loc.y; // goal location - initialised for dispersal bias + } + else smsData = 0; + if (moveType == 2) { // CRW + // set up continuous co-ordinates etc. for CRW movement + crw = new crwParams; + crw->xc = ((float)pRandom->Random() * 0.999f) + (float)loc.x; + crw->yc = (float)(pRandom->Random() * 0.999f) + (float)loc.y; + crw->prevdrn = (float)(pRandom->Random() * 2.0 * PI); + crw->stepL = crw->rho = 0.0; + } + else crw = 0; + } + else { + path = 0; crw = 0; smsData = 0; + } + emigtraits = 0; + kerntraits = 0; + setttraits = 0; + pGenome = 0; #if RSDEBUG -//locn currloc = pCurrCell->getLocn(); -//DEBUGLOG << "Individual::Individual(): indId=" << indId -// << " x=" << currloc.x << " y=" << currloc.y -//// << " smsData=" << smsData << " dp=" << smsData->dp -// << endl; + //locn currloc = pCurrCell->getLocn(); + //DEBUGLOG << "Individual::Individual(): indId=" << indId + // << " x=" << currloc.x << " y=" << currloc.y + //// << " smsData=" << smsData << " dp=" << smsData->dp + // << endl; #endif } Individual::~Individual(void) { -if (path != 0) delete path; -if (crw != 0) delete crw; -if (smsData != 0) delete smsData; -if (emigtraits != 0) delete emigtraits; -if (kerntraits != 0) delete kerntraits; -if (setttraits != 0) delete setttraits; + if (path != 0) delete path; + if (crw != 0) delete crw; + if (smsData != 0) delete smsData; + if (emigtraits != 0) delete emigtraits; + if (kerntraits != 0) delete kerntraits; + if (setttraits != 0) delete setttraits; -if (pGenome != 0) delete pGenome; + if (pGenome != 0) delete pGenome; } @@ -114,375 +114,375 @@ if (pGenome != 0) delete pGenome; //--------------------------------------------------------------------------- // Set genes for individual variation from species initialisation parameters -void Individual::setGenes(Species *pSpecies,int resol) { -demogrParams dem = pSpecies->getDemogr(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -genomeData gen = pSpecies->getGenomeData(); -simParams sim = paramsSim->getSim(); -int ntraits; // first trait for all/female expression, second for male expression - -if (gen.trait1Chromosome) { - pGenome = new Genome(pSpecies->getNChromosomes(),pSpecies->getNLoci(0), - pSpecies->isDiploid()); -} -else { - pGenome = new Genome(pSpecies); -} +void Individual::setGenes(Species* pSpecies, int resol) { + demogrParams dem = pSpecies->getDemogr(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + genomeData gen = pSpecies->getGenomeData(); + simParams sim = paramsSim->getSim(); + int ntraits; // first trait for all/female expression, second for male expression + + if (gen.trait1Chromosome) { + pGenome = new Genome(pSpecies->getNChromosomes(), pSpecies->getNLoci(0), + pSpecies->isDiploid()); + } + else { + pGenome = new Genome(pSpecies); + } #if RSDEBUG -//DEBUGLOG << endl; -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " sex=" << sex -// << " trait1Chromosome=" << gen.trait1Chromosome << " pGenome=" << pGenome -// << endl; + //DEBUGLOG << endl; + //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " sex=" << sex + // << " trait1Chromosome=" << gen.trait1Chromosome << " pGenome=" << pGenome + // << endl; #endif -int gposn = 0; // current position on genome -int expr = 0; // gene expression type - NOT CURRENTLY USED + int gposn = 0; // current position on genome + int expr = 0; // gene expression type - NOT CURRENTLY USED -//int emigposn = 0; + //int emigposn = 0; #if RSDEBUG //DEBUGLOG << "Individual::setGenes(): emigration genes" << endl; #endif -if (emig.indVar) { // set emigration genes - int emigposn = gposn; - double d0,alpha,beta; - emigParams eparams; -// emigScales scale = pSpecies->getEmigScales(); - if (emig.sexDep) { // must be a sexual species - ntraits = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction (haploid) - ntraits = 1; + if (emig.indVar) { // set emigration genes + int emigposn = gposn; + double d0, alpha, beta; + emigParams eparams; + // emigScales scale = pSpecies->getEmigScales(); + if (emig.sexDep) { // must be a sexual species + ntraits = 2; } - else { // sexual reproduction - ntraits = 1; + else { + if (dem.repType == 0) { // asexual reproduction (haploid) + ntraits = 1; + } + else { // sexual reproduction + ntraits = 1; + } } - } - for (int g = 0; g < ntraits; g++) { // first trait for females/all, second for males - eparams = pSpecies->getEmigParams(0,g); - d0 = pRandom->Normal(0.0,eparams.d0SD) / eparams.d0Scale; - if (emig.densDep) { - alpha = pRandom->Normal(0.0,eparams.alphaSD) / eparams.alphaScale; - beta = pRandom->Normal(0.0,eparams.betaSD) / eparams.betaScale; - } -#if RSDEBUG -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g -// << " eparams.d0Mean=" << eparams.d0Mean << " eparams.d0SD=" << eparams.d0SD -// << " eparams.d0Scale=" << eparams.d0Scale << " d0=" << d0 -//// << " log(d0/(1.0-d0))=" << log(d0/(1.0-d0)) -// << endl; -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g -// << " eparams.alphaMean=" << eparams.alphaMean << " eparams.alphaSD=" << eparams.alphaSD -// << " eparams.alphaScale=" << eparams.alphaScale << " alpha=" << alpha -// << endl; -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g -// << " eparams.betaMean=" << eparams.betaMean << " eparams.betaSD=" << eparams.betaSD -// << " eparams.betaScale=" << eparams.betaScale << " beta=" << beta -// << endl; -#endif - if (gen.trait1Chromosome) { - pGenome->setGene(gposn++,expr,d0,gen.alleleSD); + for (int g = 0; g < ntraits; g++) { // first trait for females/all, second for males + eparams = pSpecies->getEmigParams(0, g); + d0 = pRandom->Normal(0.0, eparams.d0SD) / eparams.d0Scale; if (emig.densDep) { - pGenome->setGene(gposn++,expr,alpha,gen.alleleSD); - pGenome->setGene(gposn++,expr,beta,gen.alleleSD); + alpha = pRandom->Normal(0.0, eparams.alphaSD) / eparams.alphaScale; + beta = pRandom->Normal(0.0, eparams.betaSD) / eparams.betaScale; } +#if RSDEBUG + //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g + // << " eparams.d0Mean=" << eparams.d0Mean << " eparams.d0SD=" << eparams.d0SD + // << " eparams.d0Scale=" << eparams.d0Scale << " d0=" << d0 + //// << " log(d0/(1.0-d0))=" << log(d0/(1.0-d0)) + // << endl; + //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g + // << " eparams.alphaMean=" << eparams.alphaMean << " eparams.alphaSD=" << eparams.alphaSD + // << " eparams.alphaScale=" << eparams.alphaScale << " alpha=" << alpha + // << endl; + //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g + // << " eparams.betaMean=" << eparams.betaMean << " eparams.betaSD=" << eparams.betaSD + // << " eparams.betaScale=" << eparams.betaScale << " beta=" << beta + // << endl; +#endif + if (gen.trait1Chromosome) { + pGenome->setGene(gposn++, expr, d0, gen.alleleSD); + if (emig.densDep) { + pGenome->setGene(gposn++, expr, alpha, gen.alleleSD); + pGenome->setGene(gposn++, expr, beta, gen.alleleSD); + } + } + else { + pGenome->setTrait(pSpecies, gposn++, d0, gen.alleleSD); + if (emig.densDep) { + pGenome->setTrait(pSpecies, gposn++, alpha, gen.alleleSD); + pGenome->setTrait(pSpecies, gposn++, beta, gen.alleleSD); + } + } + } + // record phenotypic traits + if (emig.densDep) { + setEmigTraits(pSpecies, emigposn, 3, emig.sexDep); } else { - pGenome->setTrait(pSpecies,gposn++,d0,gen.alleleSD); - if (emig.densDep) { - pGenome->setTrait(pSpecies,gposn++,alpha,gen.alleleSD); - pGenome->setTrait(pSpecies,gposn++,beta,gen.alleleSD); - } + setEmigTraits(pSpecies, emigposn, 1, emig.sexDep); } } - // record phenotypic traits - if (emig.densDep) { - setEmigTraits(pSpecies,emigposn,3,emig.sexDep); - } - else { - setEmigTraits(pSpecies,emigposn,1,emig.sexDep); - } -} -//int trfrposn = 0; -if (trfr.indVar) { // set transfer genes - int trfrposn = gposn; - if (trfr.sexDep) { // must be a sexual species - ntraits = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction - ntraits = 1; - } - else { // sexual reproduction - ntraits = 1; + //int trfrposn = 0; + if (trfr.indVar) { // set transfer genes + int trfrposn = gposn; + if (trfr.sexDep) { // must be a sexual species + ntraits = 2; } - } -// trfrScales scale = pSpecies->getTrfrScales(); - if (trfr.moveModel) { - if (trfr.moveType == 1) { // set SMS genes - double dp,gb,alphaDB,betaDB; - trfrSMSParams smsparams = pSpecies->getSMSParams(0,0); // only traits for females/all - trfrSMSTraits smstraits = pSpecies->getSMSTraits(); - dp = pRandom->Normal(0.0,smsparams.dpSD) / smsparams.dpScale; - gb = pRandom->Normal(0.0,smsparams.gbSD) / smsparams.gbScale; - if (smstraits.goalType == 2) { - alphaDB = pRandom->Normal(0.0,smsparams.alphaDBSD) / smsparams.alphaDBScale; - betaDB = pRandom->Normal(0.0,smsparams.betaDBSD) / smsparams.betaDBScale; + else { + if (dem.repType == 0) { // asexual reproduction + ntraits = 1; } - if (gen.trait1Chromosome) { - pGenome->setGene(gposn++,expr,dp,gen.alleleSD); - pGenome->setGene(gposn++,expr,gb,gen.alleleSD); - if (smstraits.goalType == 2) { - pGenome->setGene(gposn++,expr,alphaDB,gen.alleleSD); - pGenome->setGene(gposn++,expr,betaDB,gen.alleleSD); - } + else { // sexual reproduction + ntraits = 1; } - else { - pGenome->setTrait(pSpecies,gposn++,dp,gen.alleleSD); - pGenome->setTrait(pSpecies,gposn++,gb,gen.alleleSD); + } + // trfrScales scale = pSpecies->getTrfrScales(); + if (trfr.moveModel) { + if (trfr.moveType == 1) { // set SMS genes + double dp, gb, alphaDB, betaDB; + trfrSMSParams smsparams = pSpecies->getSMSParams(0, 0); // only traits for females/all + trfrSMSTraits smstraits = pSpecies->getSMSTraits(); + dp = pRandom->Normal(0.0, smsparams.dpSD) / smsparams.dpScale; + gb = pRandom->Normal(0.0, smsparams.gbSD) / smsparams.gbScale; if (smstraits.goalType == 2) { - pGenome->setTrait(pSpecies,gposn++,alphaDB,gen.alleleSD); - pGenome->setTrait(pSpecies,gposn++,betaDB,gen.alleleSD); + alphaDB = pRandom->Normal(0.0, smsparams.alphaDBSD) / smsparams.alphaDBScale; + betaDB = pRandom->Normal(0.0, smsparams.betaDBSD) / smsparams.betaDBScale; } + if (gen.trait1Chromosome) { + pGenome->setGene(gposn++, expr, dp, gen.alleleSD); + pGenome->setGene(gposn++, expr, gb, gen.alleleSD); + if (smstraits.goalType == 2) { + pGenome->setGene(gposn++, expr, alphaDB, gen.alleleSD); + pGenome->setGene(gposn++, expr, betaDB, gen.alleleSD); + } + } + else { + pGenome->setTrait(pSpecies, gposn++, dp, gen.alleleSD); + pGenome->setTrait(pSpecies, gposn++, gb, gen.alleleSD); + if (smstraits.goalType == 2) { + pGenome->setTrait(pSpecies, gposn++, alphaDB, gen.alleleSD); + pGenome->setTrait(pSpecies, gposn++, betaDB, gen.alleleSD); + } + } + // record phenotypic traits + if (smstraits.goalType == 2) + setSMSTraits(pSpecies, trfrposn, 4, false); + else + setSMSTraits(pSpecies, trfrposn, 2, false); } - // record phenotypic traits - if (smstraits.goalType == 2) - setSMSTraits(pSpecies,trfrposn,4,false); - else - setSMSTraits(pSpecies,trfrposn,2,false); - } - if (trfr.moveType == 2) { // set CRW genes - double stepL,rho; - trfrCRWParams m = pSpecies->getCRWParams(0,0); // only traits for females/all - stepL = pRandom->Normal(0.0,m.stepLgthSD) / m.stepLScale; - rho = pRandom->Normal(0.0,m.rhoSD) / m.rhoScale; - if (gen.trait1Chromosome) { - pGenome->setGene(gposn++,expr,stepL,gen.alleleSD); - pGenome->setGene(gposn++,expr,rho,gen.alleleSD); - } - else { - pGenome->setTrait(pSpecies,gposn++,stepL,gen.alleleSD); - pGenome->setTrait(pSpecies,gposn++,rho,gen.alleleSD); + if (trfr.moveType == 2) { // set CRW genes + double stepL, rho; + trfrCRWParams m = pSpecies->getCRWParams(0, 0); // only traits for females/all + stepL = pRandom->Normal(0.0, m.stepLgthSD) / m.stepLScale; + rho = pRandom->Normal(0.0, m.rhoSD) / m.rhoScale; + if (gen.trait1Chromosome) { + pGenome->setGene(gposn++, expr, stepL, gen.alleleSD); + pGenome->setGene(gposn++, expr, rho, gen.alleleSD); + } + else { + pGenome->setTrait(pSpecies, gposn++, stepL, gen.alleleSD); + pGenome->setTrait(pSpecies, gposn++, rho, gen.alleleSD); + } + // record phenotypic traits + setCRWTraits(pSpecies, trfrposn, 2, false); } - // record phenotypic traits - setCRWTraits(pSpecies,trfrposn,2,false); } - } - else { // set kernel genes - double dist1,dist2,prob1; - trfrKernParams k; - for (int g = 0; g < ntraits; g++) { // first traits for females/all, second for males - k = pSpecies->getKernParams(0,g); - dist1 = pRandom->Normal(0.0,k.dist1SD) / k.dist1Scale; - if (trfr.twinKern) - { - dist2 = pRandom->Normal(0.0,k.dist2SD) / k.dist2Scale; - prob1 = pRandom->Normal(0.0,k.PKern1SD) / k.PKern1Scale; - } - if (gen.trait1Chromosome) { - pGenome->setGene(gposn++,expr,dist1,gen.alleleSD); - if (trfr.twinKern) + else { // set kernel genes + double dist1, dist2, prob1; + trfrKernParams k; + for (int g = 0; g < ntraits; g++) { // first traits for females/all, second for males + k = pSpecies->getKernParams(0, g); + dist1 = pRandom->Normal(0.0, k.dist1SD) / k.dist1Scale; + if (trfr.twinKern) { - pGenome->setGene(gposn++,expr,dist2,gen.alleleSD); - pGenome->setGene(gposn++,expr,prob1,gen.alleleSD); + dist2 = pRandom->Normal(0.0, k.dist2SD) / k.dist2Scale; + prob1 = pRandom->Normal(0.0, k.PKern1SD) / k.PKern1Scale; + } + if (gen.trait1Chromosome) { + pGenome->setGene(gposn++, expr, dist1, gen.alleleSD); + if (trfr.twinKern) + { + pGenome->setGene(gposn++, expr, dist2, gen.alleleSD); + pGenome->setGene(gposn++, expr, prob1, gen.alleleSD); + } + } + else { + pGenome->setTrait(pSpecies, gposn++, dist1, gen.alleleSD); + if (trfr.twinKern) + { + pGenome->setTrait(pSpecies, gposn++, dist2, gen.alleleSD); + pGenome->setTrait(pSpecies, gposn++, prob1, gen.alleleSD); + } } } + // record phenotypic traits + if (trfr.twinKern) + { + setKernTraits(pSpecies, trfrposn, 3, resol, trfr.sexDep); + } else { - pGenome->setTrait(pSpecies,gposn++,dist1,gen.alleleSD); - if (trfr.twinKern) - { - pGenome->setTrait(pSpecies,gposn++,dist2,gen.alleleSD); - pGenome->setTrait(pSpecies,gposn++,prob1,gen.alleleSD); - } - } - } - // record phenotypic traits - if (trfr.twinKern) - { - setKernTraits(pSpecies,trfrposn,3,resol,trfr.sexDep); - } - else { - setKernTraits(pSpecies,trfrposn,1,resol,trfr.sexDep); + setKernTraits(pSpecies, trfrposn, 1, resol, trfr.sexDep); + } } } -} -//int settposn = 0; + //int settposn = 0; #if RSDEBUG //DEBUGLOG << "Individual::setGenes(): settlement genes" << endl; #endif -if (sett.indVar) { - int settposn = gposn; - double s0,alpha,beta; - settParams sparams; -// settScales scale = pSpecies->getSettScales(); - if (sett.sexDep) { // must be a sexual species - ntraits = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction - ntraits = 1; - } - else { // sexual reproduction - ntraits = 1; - } - } - for (int g = 0; g < ntraits; g++) { // first trait for females/all, second for males - if (sim.batchMode) { - sparams = pSpecies->getSettParams(0,g); - } - else { // individual variability not (yet) implemented as sex-dependent in GUI - sparams = pSpecies->getSettParams(0,0); - } - s0 = pRandom->Normal(0.0,sparams.s0SD) / sparams.s0Scale; - alpha = pRandom->Normal(0.0,sparams.alphaSSD) / sparams.alphaSScale; - beta = pRandom->Normal(0.0,sparams.betaSSD) / sparams.betaSScale; -#if RSDEBUG -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g -// << " sparams.s0Mean=" << sparams.s0Mean -// << " sparams.s0SD=" << sparams.s0SD -// << " sparams.s0Scale=" << sparams.s0Scale -// << " s0=" << s0 -// << endl; -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g -// << " sparams.alphaSMean=" << sparams.alphaSMean -// << " sparams.alphaSSD=" << sparams.alphaSSD -// << " sparams.alphaSScale=" << sparams.alphaSScale -// << " alpha=" << alpha -// << endl; -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g -// << " sparams.betaSMean=" << sparams.betaSMean -// << " sparams.betaSSD=" << sparams.betaSSD -// << " sparams.betaSScale=" << sparams.betaSScale -// << " beta=" << beta -// << endl; -#endif - if (gen.trait1Chromosome) { - pGenome->setGene(gposn++,expr,s0,gen.alleleSD); - pGenome->setGene(gposn++,expr,alpha,gen.alleleSD); - pGenome->setGene(gposn++,expr,beta,gen.alleleSD); + if (sett.indVar) { + int settposn = gposn; + double s0, alpha, beta; + settParams sparams; + // settScales scale = pSpecies->getSettScales(); + if (sett.sexDep) { // must be a sexual species + ntraits = 2; } else { - pGenome->setTrait(pSpecies,gposn++,s0,gen.alleleSD); - pGenome->setTrait(pSpecies,gposn++,alpha,gen.alleleSD); - pGenome->setTrait(pSpecies,gposn++,beta,gen.alleleSD); + if (dem.repType == 0) { // asexual reproduction + ntraits = 1; + } + else { // sexual reproduction + ntraits = 1; + } } + for (int g = 0; g < ntraits; g++) { // first trait for females/all, second for males + if (sim.batchMode) { + sparams = pSpecies->getSettParams(0, g); + } + else { // individual variability not (yet) implemented as sex-dependent in GUI + sparams = pSpecies->getSettParams(0, 0); + } + s0 = pRandom->Normal(0.0, sparams.s0SD) / sparams.s0Scale; + alpha = pRandom->Normal(0.0, sparams.alphaSSD) / sparams.alphaSScale; + beta = pRandom->Normal(0.0, sparams.betaSSD) / sparams.betaSScale; +#if RSDEBUG + //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g + // << " sparams.s0Mean=" << sparams.s0Mean + // << " sparams.s0SD=" << sparams.s0SD + // << " sparams.s0Scale=" << sparams.s0Scale + // << " s0=" << s0 + // << endl; + //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g + // << " sparams.alphaSMean=" << sparams.alphaSMean + // << " sparams.alphaSSD=" << sparams.alphaSSD + // << " sparams.alphaSScale=" << sparams.alphaSScale + // << " alpha=" << alpha + // << endl; + //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g + // << " sparams.betaSMean=" << sparams.betaSMean + // << " sparams.betaSSD=" << sparams.betaSSD + // << " sparams.betaSScale=" << sparams.betaSScale + // << " beta=" << beta + // << endl; +#endif + if (gen.trait1Chromosome) { + pGenome->setGene(gposn++, expr, s0, gen.alleleSD); + pGenome->setGene(gposn++, expr, alpha, gen.alleleSD); + pGenome->setGene(gposn++, expr, beta, gen.alleleSD); + } + else { + pGenome->setTrait(pSpecies, gposn++, s0, gen.alleleSD); + pGenome->setTrait(pSpecies, gposn++, alpha, gen.alleleSD); + pGenome->setTrait(pSpecies, gposn++, beta, gen.alleleSD); + } + } + // record phenotypic traits + setSettTraits(pSpecies, settposn, 3, sett.sexDep); } - // record phenotypic traits - setSettTraits(pSpecies,settposn,3,sett.sexDep); -} -if (!gen.trait1Chromosome) { - if (gen.neutralMarkers || pSpecies->getNNeutralLoci() > 0) { - pGenome->setNeutralLoci(pSpecies,gen.alleleSD); + if (!gen.trait1Chromosome) { + if (gen.neutralMarkers || pSpecies->getNNeutralLoci() > 0) { + pGenome->setNeutralLoci(pSpecies, gen.alleleSD); + } } -} #if RSDEBUG -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " finished" -// << endl; + //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " finished" + // << endl; #endif } // Inherit genome from parent(s) -void Individual::setGenes(Species *pSpecies,Individual *mother,Individual *father, +void Individual::setGenes(Species* pSpecies, Individual* mother, Individual* father, int resol) { #if RSDEBUG -//locn currloc = pCurrCell->getLocn(); -//DEBUGLOG << "Individual::setGenes(): indId=" << indId -// << " x=" << currloc.x << " y=" << currloc.y -//// << " pSpecies=" << pSpecies -// << " mother=" << mother -// << " motherID=" << mother->getId() -// << " father=" << father; -//if (father != 0) DEBUGLOG << " fatherID=" << father->getId(); -//DEBUGLOG << endl; + //locn currloc = pCurrCell->getLocn(); + //DEBUGLOG << "Individual::setGenes(): indId=" << indId + // << " x=" << currloc.x << " y=" << currloc.y + //// << " pSpecies=" << pSpecies + // << " mother=" << mother + // << " motherID=" << mother->getId() + // << " father=" << father; + //if (father != 0) DEBUGLOG << " fatherID=" << father->getId(); + //DEBUGLOG << endl; #endif -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); -Genome *pFatherGenome; -if (father == 0) pFatherGenome = 0; else pFatherGenome = father->pGenome; + Genome* pFatherGenome; + if (father == 0) pFatherGenome = 0; else pFatherGenome = father->pGenome; -pGenome = new Genome(pSpecies,mother->pGenome,pFatherGenome); + pGenome = new Genome(pSpecies, mother->pGenome, pFatherGenome); -if (emig.indVar) { - // record emigration traits - if (father == 0) { // haploid - if (emig.densDep) { - setEmigTraits(pSpecies,0,3,0); - } - else { - setEmigTraits(pSpecies,0,1,0); - } - } - else { // diploid - if (emig.densDep) { - setEmigTraits(pSpecies,0,3,emig.sexDep); - } - else { - setEmigTraits(pSpecies,0,1,emig.sexDep); - } - } -} - -if (trfr.indVar) { - // record movement model traits - if (trfr.moveModel) { - if (trfr.moveType == 1) { // SMS - trfrSMSTraits s = pSpecies->getSMSTraits(); - if (s.goalType == 2) - setSMSTraits(pSpecies,trfr.movtTrait[0],4,0); - else - setSMSTraits(pSpecies,trfr.movtTrait[0],2,0); - } - if (trfr.moveType == 2) { // CRW - setCRWTraits(pSpecies,trfr.movtTrait[0],2,0); - } - } - else { // kernel + if (emig.indVar) { + // record emigration traits if (father == 0) { // haploid - if (trfr.twinKern) - { - setKernTraits(pSpecies,trfr.movtTrait[0],3,resol,0); + if (emig.densDep) { + setEmigTraits(pSpecies, 0, 3, 0); } else { - setKernTraits(pSpecies,trfr.movtTrait[0],1,resol,0); + setEmigTraits(pSpecies, 0, 1, 0); } } else { // diploid - if (trfr.twinKern) - { - setKernTraits(pSpecies,trfr.movtTrait[0],3,resol,trfr.sexDep); + if (emig.densDep) { + setEmigTraits(pSpecies, 0, 3, emig.sexDep); } else { - setKernTraits(pSpecies,trfr.movtTrait[0],1,resol,trfr.sexDep); + setEmigTraits(pSpecies, 0, 1, emig.sexDep); } } } -} -if (sett.indVar) { - // record settlement traits - if (father == 0) { // haploid - setSettTraits(pSpecies,sett.settTrait[0],3,0); + if (trfr.indVar) { + // record movement model traits + if (trfr.moveModel) { + if (trfr.moveType == 1) { // SMS + trfrSMSTraits s = pSpecies->getSMSTraits(); + if (s.goalType == 2) + setSMSTraits(pSpecies, trfr.movtTrait[0], 4, 0); + else + setSMSTraits(pSpecies, trfr.movtTrait[0], 2, 0); + } + if (trfr.moveType == 2) { // CRW + setCRWTraits(pSpecies, trfr.movtTrait[0], 2, 0); + } + } + else { // kernel + if (father == 0) { // haploid + if (trfr.twinKern) + { + setKernTraits(pSpecies, trfr.movtTrait[0], 3, resol, 0); + } + else { + setKernTraits(pSpecies, trfr.movtTrait[0], 1, resol, 0); + } + } + else { // diploid + if (trfr.twinKern) + { + setKernTraits(pSpecies, trfr.movtTrait[0], 3, resol, trfr.sexDep); + } + else { + setKernTraits(pSpecies, trfr.movtTrait[0], 1, resol, trfr.sexDep); + } + } + } } - else { // diploid - setSettTraits(pSpecies,sett.settTrait[0],3,sett.sexDep); -// setSettTraits(pSpecies,sett.settTrait[0],3,0); + + if (sett.indVar) { + // record settlement traits + if (father == 0) { // haploid + setSettTraits(pSpecies, sett.settTrait[0], 3, 0); + } + else { // diploid + setSettTraits(pSpecies, sett.settTrait[0], 3, sett.sexDep); + // setSettTraits(pSpecies,sett.settTrait[0],3,0); + } } -} #if RSDEBUG -//emigParams e = getEmigTraits(0,1,0); -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " finished " -// << " d0=" << e.d0 -//// << " alpha=" << e.alpha << " beta=" << e.beta -// << endl; + //emigParams e = getEmigTraits(0,1,0); + //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " finished " + // << " d0=" << e.d0 + //// << " alpha=" << e.alpha << " beta=" << e.beta + // << endl; #endif } @@ -491,12 +491,12 @@ if (sett.indVar) { // Identify whether an individual is a potentially breeding female - // if so, return her stage, otherwise return 0 int Individual::breedingFem(void) { -if (sex == 0) { - if (status == 0 || status == 4 || status == 5) return stage; + if (sex == 0) { + if (status == 0 || status == 4 || status == 5) return stage; + else return 0; + } else return 0; } -else return 0; -} int Individual::getId(void) { return indId; } @@ -505,583 +505,583 @@ int Individual::getSex(void) { return sex; } int Individual::getStatus(void) { return status; } indStats Individual::getStats(void) { -indStats s; -s.stage = stage; s.sex = sex; s.age = age; s.status = status; s.fallow = fallow; -s.isDeveloping = isDeveloping; -return s; + indStats s; + s.stage = stage; s.sex = sex; s.age = age; s.status = status; s.fallow = fallow; + s.isDeveloping = isDeveloping; + return s; } Cell* Individual::getLocn(const short option) { -if (option == 0) { // return previous location - return pPrevCell; -} -else { // return current location - return pCurrCell; -} + if (option == 0) { // return previous location + return pPrevCell; + } + else { // return current location + return pCurrCell; + } } Patch* Individual::getNatalPatch(void) { return pNatalPatch; } void Individual::setYearSteps(int t) { -if (path != 0 && t >= 0) { - if (t >= 0) path->year = t; - else path->year = 666; -} + if (path != 0 && t >= 0) { + if (t >= 0) path->year = t; + else path->year = 666; + } #if RSDEBUG -//DEBUGLOG << "Individual::setYearSteps(): indId=" << indId -// << " t=" << t << " path->year=" << path->year -// << endl; + //DEBUGLOG << "Individual::setYearSteps(): indId=" << indId + // << " t=" << t << " path->year=" << path->year + // << endl; #endif } pathSteps Individual::getSteps(void) { -pathSteps s; -if (path == 0) { - s.year = 0; s.total = 0; s.out = 0; -} -else { - s.year = path->year; s.total = path->total; s.out = path->out; -} -return s; + pathSteps s; + if (path == 0) { + s.year = 0; s.total = 0; s.out = 0; + } + else { + s.year = path->year; s.total = path->total; s.out = path->out; + } + return s; } settlePatch Individual::getSettPatch(void) { -settlePatch s; -if (path == 0) { - s.pSettPatch = 0; s.settleStatus = 0; -} -else { - s.pSettPatch = path->pSettPatch; s.settleStatus = path->settleStatus; -} -return s; + settlePatch s; + if (path == 0) { + s.pSettPatch = 0; s.settleStatus = 0; + } + else { + s.pSettPatch = path->pSettPatch; s.settleStatus = path->settleStatus; + } + return s; } void Individual::setSettPatch(const settlePatch s) { -if (path == 0) { - path = new pathData; - path->year = 0; path->total = 0; path->out = 0; path->settleStatus = 0; + if (path == 0) { + path = new pathData; + path->year = 0; path->total = 0; path->out = 0; path->settleStatus = 0; #if RS_RCPP - path->pathoutput = 1; + path->pathoutput = 1; #endif -} -if (s.settleStatus >= 0 && s.settleStatus <= 2) path->settleStatus = s.settleStatus; -path->pSettPatch = s.pSettPatch; + } + if (s.settleStatus >= 0 && s.settleStatus <= 2) path->settleStatus = s.settleStatus; + path->pSettPatch = s.pSettPatch; } // Set phenotypic emigration traits -void Individual::setEmigTraits(Species *pSpecies,short emiggenelocn,short nemigtraits, +void Individual::setEmigTraits(Species* pSpecies, short emiggenelocn, short nemigtraits, bool sexdep) { #if RSDEBUG -//DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId -// << " emiggenelocn=" << emiggenelocn << " nemigtraits=" << nemigtraits << " sexdep=" << sexdep -// << endl; + //DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId + // << " emiggenelocn=" << emiggenelocn << " nemigtraits=" << nemigtraits << " sexdep=" << sexdep + // << endl; #endif -emigTraits e; e.d0 = e.alpha = e.beta = 0.0; -if (pGenome != 0) { - if (pSpecies->has1ChromPerTrait()) { - if (sexdep) { - if (nemigtraits == 3) { // emigration is density-dependent - e.d0 = (float)pGenome->express(emiggenelocn+3*sex,0,0); - e.alpha = (float)pGenome->express(emiggenelocn+3*sex+1,0,0); - e.beta = (float)pGenome->express(emiggenelocn+3*sex+2,0,0); + emigTraits e; e.d0 = e.alpha = e.beta = 0.0; + if (pGenome != 0) { + if (pSpecies->has1ChromPerTrait()) { + if (sexdep) { + if (nemigtraits == 3) { // emigration is density-dependent + e.d0 = (float)pGenome->express(emiggenelocn + 3 * sex, 0, 0); + e.alpha = (float)pGenome->express(emiggenelocn + 3 * sex + 1, 0, 0); + e.beta = (float)pGenome->express(emiggenelocn + 3 * sex + 2, 0, 0); + } + else { + e.d0 = (float)pGenome->express(emiggenelocn + sex, 0, 0); + } } else { - e.d0 = (float)pGenome->express(emiggenelocn+sex,0,0); + e.d0 = (float)pGenome->express(emiggenelocn, 0, 0); + if (nemigtraits == 3) { // emigration is density-dependent + e.alpha = (float)pGenome->express(emiggenelocn + 1, 0, 0); + e.beta = (float)pGenome->express(emiggenelocn + 2, 0, 0); + } } } else { - e.d0 = (float)pGenome->express(emiggenelocn,0,0); - if (nemigtraits == 3) { // emigration is density-dependent - e.alpha = (float)pGenome->express(emiggenelocn+1,0,0); - e.beta = (float)pGenome->express(emiggenelocn+2,0,0); - } - } - } - else { - if (sexdep) { - if (nemigtraits == 3) { // emigration is density-dependent - e.d0 = (float)pGenome->express(pSpecies,emiggenelocn+3*sex); - e.alpha = (float)pGenome->express(pSpecies,emiggenelocn+3*sex+1); - e.beta = (float)pGenome->express(pSpecies,emiggenelocn+3*sex+2); + if (sexdep) { + if (nemigtraits == 3) { // emigration is density-dependent + e.d0 = (float)pGenome->express(pSpecies, emiggenelocn + 3 * sex); + e.alpha = (float)pGenome->express(pSpecies, emiggenelocn + 3 * sex + 1); + e.beta = (float)pGenome->express(pSpecies, emiggenelocn + 3 * sex + 2); + } + else { + e.d0 = (float)pGenome->express(pSpecies, emiggenelocn + sex); + } } else { - e.d0 = (float)pGenome->express(pSpecies,emiggenelocn+sex); - } - } - else { - e.d0 = (float)pGenome->express(pSpecies,emiggenelocn); - if (nemigtraits == 3) { // emigration is density-dependent - e.alpha = (float)pGenome->express(pSpecies,emiggenelocn+1); - e.beta = (float)pGenome->express(pSpecies,emiggenelocn+2); + e.d0 = (float)pGenome->express(pSpecies, emiggenelocn); + if (nemigtraits == 3) { // emigration is density-dependent + e.alpha = (float)pGenome->express(pSpecies, emiggenelocn + 1); + e.beta = (float)pGenome->express(pSpecies, emiggenelocn + 2); + } } } } -} #if RSDEBUG -//DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId -// << " e.d0=" << e.d0 << " e.alpha=" << e.alpha << " e.beta=" << e.beta -// << endl; + //DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId + // << " e.d0=" << e.d0 << " e.alpha=" << e.alpha << " e.beta=" << e.beta + // << endl; #endif -emigParams eparams; -if (sexdep) { - eparams = pSpecies->getEmigParams(0,sex); -} -else { - eparams = pSpecies->getEmigParams(0,0); -} + emigParams eparams; + if (sexdep) { + eparams = pSpecies->getEmigParams(0, sex); + } + else { + eparams = pSpecies->getEmigParams(0, 0); + } #if RSDEBUG -//DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId -// << " eparams.betaMean=" << eparams.betaMean << " eparams.betaSD=" << eparams.betaSD -// << " eparams.betaScale=" << eparams.betaScale -// << endl; + //DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId + // << " eparams.betaMean=" << eparams.betaMean << " eparams.betaSD=" << eparams.betaSD + // << " eparams.betaScale=" << eparams.betaScale + // << endl; #endif -emigtraits = new emigTraits; -emigtraits->d0 = (float)(e.d0*eparams.d0Scale + eparams.d0Mean); -emigtraits->alpha = (float)(e.alpha*eparams.alphaScale + eparams.alphaMean); -emigtraits->beta = (float)(e.beta*eparams.betaScale + eparams.betaMean); + emigtraits = new emigTraits; + emigtraits->d0 = (float)(e.d0 * eparams.d0Scale + eparams.d0Mean); + emigtraits->alpha = (float)(e.alpha * eparams.alphaScale + eparams.alphaMean); + emigtraits->beta = (float)(e.beta * eparams.betaScale + eparams.betaMean); #if RSDEBUG -//DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId -// << " emigtraits->d0=" << emigtraits->d0 -// << " emigtraits->alpha=" << emigtraits->alpha << " emigtraits->beta=" << emigtraits->beta -// << endl; + //DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId + // << " emigtraits->d0=" << emigtraits->d0 + // << " emigtraits->alpha=" << emigtraits->alpha << " emigtraits->beta=" << emigtraits->beta + // << endl; #endif -if (emigtraits->d0 < 0.0) emigtraits->d0 = 0.0; -if (emigtraits->d0 > 1.0) emigtraits->d0 = 1.0; + if (emigtraits->d0 < 0.0) emigtraits->d0 = 0.0; + if (emigtraits->d0 > 1.0) emigtraits->d0 = 1.0; #if RSDEBUG -//DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId -// << " emigtraits->d0=" << emigtraits->d0 -// << " emigtraits->alpha=" << emigtraits->alpha << " emigtraits->beta=" << emigtraits->beta -// << endl; + //DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId + // << " emigtraits->d0=" << emigtraits->d0 + // << " emigtraits->alpha=" << emigtraits->alpha << " emigtraits->beta=" << emigtraits->beta + // << endl; #endif -return; + return; } // Get phenotypic emigration traits emigTraits Individual::getEmigTraits(void) { #if RSDEBUG -//DEBUGLOG << "Individual::getEmigTraits(): indId=" << indId -// << endl; + //DEBUGLOG << "Individual::getEmigTraits(): indId=" << indId + // << endl; #endif -emigTraits e; e.d0 = e.alpha = e.beta = 0.0; -if (emigtraits != 0) { - e.d0 = emigtraits->d0; - e.alpha = emigtraits->alpha; - e.beta = emigtraits->beta; -} + emigTraits e; e.d0 = e.alpha = e.beta = 0.0; + if (emigtraits != 0) { + e.d0 = emigtraits->d0; + e.alpha = emigtraits->alpha; + e.beta = emigtraits->beta; + } #if RSDEBUG -//DEBUGLOG << "Individual::getEmigTraits(): indId=" << indId -// << " e.d0=" << e.d0 << " e.alpha=" << e.alpha << " e.beta=" << e.beta -// << endl; + //DEBUGLOG << "Individual::getEmigTraits(): indId=" << indId + // << " e.d0=" << e.d0 << " e.alpha=" << e.alpha << " e.beta=" << e.beta + // << endl; #endif -return e; + return e; } // Set phenotypic transfer by kernel traits -void Individual::setKernTraits(Species *pSpecies,short kerngenelocn,short nkerntraits, - int resol,bool sexdep) { -#if RSDEBUG -//DEBUGLOG << "Individual::setKernTraits(): indId=" << indId -// << " kerngenelocn=" << kerngenelocn << " nkerntraits=" << nkerntraits << " sexdep=" << sexdep -// << endl; -#endif -trfrKernTraits k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; -if (pGenome != 0) { - if (pSpecies->has1ChromPerTrait()) { - if (sexdep) { - if (nkerntraits == 3) { // twin kernel - k.meanDist1 = (float)pGenome->express(kerngenelocn+3*sex,0,sex); - k.meanDist2 = (float)pGenome->express(kerngenelocn+3*sex+1,0,sex); - k.probKern1 = (float)pGenome->express(kerngenelocn+3*sex+2,0,sex); +void Individual::setKernTraits(Species* pSpecies, short kerngenelocn, short nkerntraits, + int resol, bool sexdep) { +#if RSDEBUG + //DEBUGLOG << "Individual::setKernTraits(): indId=" << indId + // << " kerngenelocn=" << kerngenelocn << " nkerntraits=" << nkerntraits << " sexdep=" << sexdep + // << endl; +#endif + trfrKernTraits k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; + if (pGenome != 0) { + if (pSpecies->has1ChromPerTrait()) { + if (sexdep) { + if (nkerntraits == 3) { // twin kernel + k.meanDist1 = (float)pGenome->express(kerngenelocn + 3 * sex, 0, sex); + k.meanDist2 = (float)pGenome->express(kerngenelocn + 3 * sex + 1, 0, sex); + k.probKern1 = (float)pGenome->express(kerngenelocn + 3 * sex + 2, 0, sex); + } + else { + k.meanDist1 = (float)pGenome->express(kerngenelocn + sex, 0, sex); + } } else { - k.meanDist1 = (float)pGenome->express(kerngenelocn+sex,0,sex); + k.meanDist1 = (float)pGenome->express(kerngenelocn, 0, 0); + if (nkerntraits == 3) { // twin kernel + k.meanDist2 = (float)pGenome->express(kerngenelocn + 1, 0, 0); + k.probKern1 = (float)pGenome->express(kerngenelocn + 2, 0, 0); + } } } else { - k.meanDist1 = (float)pGenome->express(kerngenelocn,0,0); - if (nkerntraits == 3) { // twin kernel - k.meanDist2 = (float)pGenome->express(kerngenelocn+1,0,0); - k.probKern1 = (float)pGenome->express(kerngenelocn+2,0,0); - } - } - } - else { - if (sexdep) { - if (nkerntraits == 3) { // twin kernel - k.meanDist1 = (float)pGenome->express(pSpecies,kerngenelocn+3*sex); - k.meanDist2 = (float)pGenome->express(pSpecies,kerngenelocn+3*sex+1); - k.probKern1 = (float)pGenome->express(pSpecies,kerngenelocn+3*sex+2); + if (sexdep) { + if (nkerntraits == 3) { // twin kernel + k.meanDist1 = (float)pGenome->express(pSpecies, kerngenelocn + 3 * sex); + k.meanDist2 = (float)pGenome->express(pSpecies, kerngenelocn + 3 * sex + 1); + k.probKern1 = (float)pGenome->express(pSpecies, kerngenelocn + 3 * sex + 2); + } + else { + k.meanDist1 = (float)pGenome->express(pSpecies, kerngenelocn + sex); + } } else { - k.meanDist1 = (float)pGenome->express(pSpecies,kerngenelocn+sex); - } - } - else { - k.meanDist1 = (float)pGenome->express(pSpecies,kerngenelocn); - if (nkerntraits == 3) { // twin kernel - k.meanDist2 = (float)pGenome->express(pSpecies,kerngenelocn+1); - k.probKern1 = (float)pGenome->express(pSpecies,kerngenelocn+2); + k.meanDist1 = (float)pGenome->express(pSpecies, kerngenelocn); + if (nkerntraits == 3) { // twin kernel + k.meanDist2 = (float)pGenome->express(pSpecies, kerngenelocn + 1); + k.probKern1 = (float)pGenome->express(pSpecies, kerngenelocn + 2); + } } } - } -} + } #if RSDEBUG -//DEBUGLOG << "Individual::setKernTraits(): indId=" << indId -// << " k.meanDist1=" << k.meanDist1 << " k.meanDist2=" << k.meanDist2 -// << " k.probKern1=" << k.probKern1 -// << endl; + //DEBUGLOG << "Individual::setKernTraits(): indId=" << indId + // << " k.meanDist1=" << k.meanDist1 << " k.meanDist2=" << k.meanDist2 + // << " k.probKern1=" << k.probKern1 + // << endl; #endif -trfrKernParams kparams; -if (sexdep) { - kparams = pSpecies->getKernParams(0,sex); -} -else { - kparams = pSpecies->getKernParams(0,0); -} -kerntraits = new trfrKernTraits; -kerntraits->meanDist1 = (float)(k.meanDist1*kparams.dist1Scale + kparams.dist1Mean); -kerntraits->meanDist2 = (float)(k.meanDist2*kparams.dist2Scale + kparams.dist2Mean); -kerntraits->probKern1 = (float)(k.probKern1*kparams.PKern1Scale + kparams.PKern1Mean); -#if RSDEBUG -//DEBUGLOG << "Individual::setKernTraits(): indId=" << indId -// << " kerntraits->meanDist1=" << kerntraits->meanDist1 -// << " kerntraits->meanDist2=" << kerntraits->meanDist2 -// << " kerntraits->probKern1=" << kerntraits->probKern1 -// << endl; -#endif -if (!pSpecies->useFullKernel()) { - // kernel mean(s) may not be less than landscape resolution - if (kerntraits->meanDist1 < resol) kerntraits->meanDist1 = (float)resol; - if (kerntraits->meanDist2 < resol) kerntraits->meanDist2 = (float)resol; -} -if (kerntraits->probKern1 < 0.0) kerntraits->probKern1 = 0.0; -if (kerntraits->probKern1 > 1.0) kerntraits->probKern1 = 1.0; + trfrKernParams kparams; + if (sexdep) { + kparams = pSpecies->getKernParams(0, sex); + } + else { + kparams = pSpecies->getKernParams(0, 0); + } + kerntraits = new trfrKernTraits; + kerntraits->meanDist1 = (float)(k.meanDist1 * kparams.dist1Scale + kparams.dist1Mean); + kerntraits->meanDist2 = (float)(k.meanDist2 * kparams.dist2Scale + kparams.dist2Mean); + kerntraits->probKern1 = (float)(k.probKern1 * kparams.PKern1Scale + kparams.PKern1Mean); +#if RSDEBUG + //DEBUGLOG << "Individual::setKernTraits(): indId=" << indId + // << " kerntraits->meanDist1=" << kerntraits->meanDist1 + // << " kerntraits->meanDist2=" << kerntraits->meanDist2 + // << " kerntraits->probKern1=" << kerntraits->probKern1 + // << endl; +#endif + if (!pSpecies->useFullKernel()) { + // kernel mean(s) may not be less than landscape resolution + if (kerntraits->meanDist1 < resol) kerntraits->meanDist1 = (float)resol; + if (kerntraits->meanDist2 < resol) kerntraits->meanDist2 = (float)resol; + } + if (kerntraits->probKern1 < 0.0) kerntraits->probKern1 = 0.0; + if (kerntraits->probKern1 > 1.0) kerntraits->probKern1 = 1.0; #if RSDEBUG -//DEBUGLOG << "Individual::setKernTraits(): indId=" << indId -// << " kerntraits->meanDist1=" << kerntraits->meanDist1 -// << " kerntraits->meanDist2=" << kerntraits->meanDist2 -// << " kerntraits->probKern1=" << kerntraits->probKern1 -// << endl; + //DEBUGLOG << "Individual::setKernTraits(): indId=" << indId + // << " kerntraits->meanDist1=" << kerntraits->meanDist1 + // << " kerntraits->meanDist2=" << kerntraits->meanDist2 + // << " kerntraits->probKern1=" << kerntraits->probKern1 + // << endl; #endif -return; + return; } // Get phenotypic emigration traits trfrKernTraits Individual::getKernTraits(void) { #if RSDEBUG -//DEBUGLOG << "Individual::getKernTraits(): indId=" << indId -// << endl; + //DEBUGLOG << "Individual::getKernTraits(): indId=" << indId + // << endl; #endif -trfrKernTraits k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; -if (kerntraits != 0) { - k.meanDist1 = kerntraits->meanDist1; - k.meanDist2 = kerntraits->meanDist2; - k.probKern1 = kerntraits->probKern1; -} + trfrKernTraits k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; + if (kerntraits != 0) { + k.meanDist1 = kerntraits->meanDist1; + k.meanDist2 = kerntraits->meanDist2; + k.probKern1 = kerntraits->probKern1; + } #if RSDEBUG -//DEBUGLOG << "Individual::getKernTraits(): indId=" << indId -// << " k.meanDist1=" << k.meanDist1 << " k.meanDist2=" << k.meanDist1 -// << " k.probKern1=" << k.probKern1 -// << endl; + //DEBUGLOG << "Individual::getKernTraits(): indId=" << indId + // << " k.meanDist1=" << k.meanDist1 << " k.meanDist2=" << k.meanDist1 + // << " k.probKern1=" << k.probKern1 + // << endl; #endif -return k; + return k; } // Set phenotypic transfer by SMS traits -void Individual::setSMSTraits(Species *pSpecies,short SMSgenelocn,short nSMStraits, - bool sexdep) { -#if RSDEBUG -//DEBUGLOG << "Individual::setSMSTraits(): indId=" << indId -// << " SMSgenelocn=" << SMSgenelocn << " nSMStraits=" << nSMStraits << " sexdep=" << sexdep -// << endl; -#endif -trfrSMSTraits s = pSpecies->getSMSTraits(); -double dp,gb,alphaDB,betaDB; -dp = gb = alphaDB = betaDB = 0.0; -if (pGenome != 0) { - if (pSpecies->has1ChromPerTrait()) { - if (sexdep) { - dp = pGenome->express(SMSgenelocn,0,0); - gb = pGenome->express(SMSgenelocn+1,0,0); - if (nSMStraits == 4) { - alphaDB = pGenome->express(SMSgenelocn+2,0,0); - betaDB = pGenome->express(SMSgenelocn+3,0,0); - } - } - else { - dp = pGenome->express(SMSgenelocn,0,0); - gb = pGenome->express(SMSgenelocn+1,0,0); - if (nSMStraits == 4) { - alphaDB = pGenome->express(SMSgenelocn+2,0,0); - betaDB = pGenome->express(SMSgenelocn+3,0,0); +void Individual::setSMSTraits(Species* pSpecies, short SMSgenelocn, short nSMStraits, + bool sexdep) { +#if RSDEBUG + //DEBUGLOG << "Individual::setSMSTraits(): indId=" << indId + // << " SMSgenelocn=" << SMSgenelocn << " nSMStraits=" << nSMStraits << " sexdep=" << sexdep + // << endl; +#endif + trfrSMSTraits s = pSpecies->getSMSTraits(); + double dp, gb, alphaDB, betaDB; + dp = gb = alphaDB = betaDB = 0.0; + if (pGenome != 0) { + if (pSpecies->has1ChromPerTrait()) { + if (sexdep) { + dp = pGenome->express(SMSgenelocn, 0, 0); + gb = pGenome->express(SMSgenelocn + 1, 0, 0); + if (nSMStraits == 4) { + alphaDB = pGenome->express(SMSgenelocn + 2, 0, 0); + betaDB = pGenome->express(SMSgenelocn + 3, 0, 0); + } } - } - } - else { - if (sexdep) { - dp = pGenome->express(pSpecies,SMSgenelocn); - gb = pGenome->express(pSpecies,SMSgenelocn+1); - if (nSMStraits == 4) { - alphaDB = pGenome->express(pSpecies,SMSgenelocn+2); - betaDB = pGenome->express(pSpecies,SMSgenelocn+3); + else { + dp = pGenome->express(SMSgenelocn, 0, 0); + gb = pGenome->express(SMSgenelocn + 1, 0, 0); + if (nSMStraits == 4) { + alphaDB = pGenome->express(SMSgenelocn + 2, 0, 0); + betaDB = pGenome->express(SMSgenelocn + 3, 0, 0); + } } } else { - dp = pGenome->express(pSpecies,SMSgenelocn); - gb = pGenome->express(pSpecies,SMSgenelocn+1); - if (nSMStraits == 4) { - alphaDB = pGenome->express(pSpecies,SMSgenelocn+2); - betaDB = pGenome->express(pSpecies,SMSgenelocn+3); + if (sexdep) { + dp = pGenome->express(pSpecies, SMSgenelocn); + gb = pGenome->express(pSpecies, SMSgenelocn + 1); + if (nSMStraits == 4) { + alphaDB = pGenome->express(pSpecies, SMSgenelocn + 2); + betaDB = pGenome->express(pSpecies, SMSgenelocn + 3); + } + } + else { + dp = pGenome->express(pSpecies, SMSgenelocn); + gb = pGenome->express(pSpecies, SMSgenelocn + 1); + if (nSMStraits == 4) { + alphaDB = pGenome->express(pSpecies, SMSgenelocn + 2); + betaDB = pGenome->express(pSpecies, SMSgenelocn + 3); + } } } } -} #if RSDEBUG -//DEBUGLOG << "Individual::setSMSTraits(): indId=" << indId -// << " dp=" << dp << " gb=" << gb -// << " alphaDB=" << alphaDB << " betaDB=" << betaDB -// << endl; + //DEBUGLOG << "Individual::setSMSTraits(): indId=" << indId + // << " dp=" << dp << " gb=" << gb + // << " alphaDB=" << alphaDB << " betaDB=" << betaDB + // << endl; #endif -trfrSMSParams smsparams; -if (sexdep) { - smsparams = pSpecies->getSMSParams(0,0); -} -else { - smsparams = pSpecies->getSMSParams(0,0); -} -smsData->dp = (float)(dp*smsparams.dpScale + smsparams.dpMean); -smsData->gb = (float)(gb*smsparams.gbScale + smsparams.gbMean); -if (s.goalType == 2) { - smsData->alphaDB = (float)(alphaDB*smsparams.alphaDBScale + smsparams.alphaDBMean); - smsData->betaDB = (int)(betaDB*smsparams.betaDBScale + smsparams.betaDBMean + 0.5); -} -else { - smsData->alphaDB = s.alphaDB; - smsData->betaDB = s.betaDB; -} + trfrSMSParams smsparams; + if (sexdep) { + smsparams = pSpecies->getSMSParams(0, 0); + } + else { + smsparams = pSpecies->getSMSParams(0, 0); + } + smsData->dp = (float)(dp * smsparams.dpScale + smsparams.dpMean); + smsData->gb = (float)(gb * smsparams.gbScale + smsparams.gbMean); + if (s.goalType == 2) { + smsData->alphaDB = (float)(alphaDB * smsparams.alphaDBScale + smsparams.alphaDBMean); + smsData->betaDB = (int)(betaDB * smsparams.betaDBScale + smsparams.betaDBMean + 0.5); + } + else { + smsData->alphaDB = s.alphaDB; + smsData->betaDB = s.betaDB; + } #if RSDEBUG -//DEBUGLOG << "Individual::setSMSTraits() 1111: indId=" << indId -// << " smsData->dp=" << smsData->dp << " smsData->gb=" << smsData->gb -// << " smsData->alphaDB=" << smsData->alphaDB << " smsData->betaDB=" << smsData->betaDB -// << endl; + //DEBUGLOG << "Individual::setSMSTraits() 1111: indId=" << indId + // << " smsData->dp=" << smsData->dp << " smsData->gb=" << smsData->gb + // << " smsData->alphaDB=" << smsData->alphaDB << " smsData->betaDB=" << smsData->betaDB + // << endl; #endif -if (smsData->dp < 1.0) smsData->dp = 1.0; -if (smsData->gb < 1.0) smsData->gb = 1.0; -if (smsData->alphaDB <= 0.0) smsData->alphaDB = 0.000001f; -if (smsData->betaDB < 1) smsData->betaDB = 1; + if (smsData->dp < 1.0) smsData->dp = 1.0; + if (smsData->gb < 1.0) smsData->gb = 1.0; + if (smsData->alphaDB <= 0.0) smsData->alphaDB = 0.000001f; + if (smsData->betaDB < 1) smsData->betaDB = 1; #if RSDEBUG -//DEBUGLOG << "Individual::setSMSTraits() 2222: indId=" << indId -// << " smsData->dp=" << smsData->dp << " smsData->gb=" << smsData->gb -// << " smsData->alphaDB=" << smsData->alphaDB << " smsData->betaDB=" << smsData->betaDB -// << endl; + //DEBUGLOG << "Individual::setSMSTraits() 2222: indId=" << indId + // << " smsData->dp=" << smsData->dp << " smsData->gb=" << smsData->gb + // << " smsData->alphaDB=" << smsData->alphaDB << " smsData->betaDB=" << smsData->betaDB + // << endl; #endif -return; + return; } // Get phenotypic transfer by SMS traits trfrSMSTraits Individual::getSMSTraits(void) { #if RSDEBUG -//DEBUGLOG << "Individual::getSMSTraits(): indId=" << indId << " smsData=" << smsData -// << endl; + //DEBUGLOG << "Individual::getSMSTraits(): indId=" << indId << " smsData=" << smsData + // << endl; #endif -trfrSMSTraits s; s.dp = s.gb = s.alphaDB = 1.0; s.betaDB = 1; -if (smsData != 0) { - s.dp = smsData->dp; s.gb = smsData->gb; - s.alphaDB = smsData->alphaDB; s.betaDB = smsData->betaDB; -} + trfrSMSTraits s; s.dp = s.gb = s.alphaDB = 1.0; s.betaDB = 1; + if (smsData != 0) { + s.dp = smsData->dp; s.gb = smsData->gb; + s.alphaDB = smsData->alphaDB; s.betaDB = smsData->betaDB; + } #if RSDEBUG -//DEBUGLOG << "Individual::getSMSTraits(): indId=" << indId -// << " s.dp=" << s.dp << " s.gb=" << s.gb -// << " s.alphaDB=" << s.alphaDB << " s.betaDB=" << s.betaDB -// << endl; + //DEBUGLOG << "Individual::getSMSTraits(): indId=" << indId + // << " s.dp=" << s.dp << " s.gb=" << s.gb + // << " s.alphaDB=" << s.alphaDB << " s.betaDB=" << s.betaDB + // << endl; #endif -return s; + return s; } // Set phenotypic transfer by CRW traits -void Individual::setCRWTraits(Species *pSpecies,short CRWgenelocn,short nCRWtraits, +void Individual::setCRWTraits(Species* pSpecies, short CRWgenelocn, short nCRWtraits, bool sexdep) { #if RSDEBUG -//DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId -// << " CRWgenelocn=" << CRWgenelocn << " nCRWtraits=" << nCRWtraits << " sexdep=" << sexdep -// << endl; + //DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId + // << " CRWgenelocn=" << CRWgenelocn << " nCRWtraits=" << nCRWtraits << " sexdep=" << sexdep + // << endl; #endif -trfrCRWTraits c; c.stepLength = c.rho = 0.0; -if (pGenome != 0) { - if (pSpecies->has1ChromPerTrait()) { - if (sexdep) { - c.stepLength = (float)pGenome->express(CRWgenelocn+sex,0,sex); - c.rho = (float)pGenome->express(CRWgenelocn+2+sex,0,sex); - } - else { - c.stepLength = (float)pGenome->express(CRWgenelocn,0,0); - c.rho = (float)pGenome->express(CRWgenelocn+1,0,0); - } - } - else { - if (sexdep) { - c.stepLength = (float)pGenome->express(pSpecies,CRWgenelocn+sex); - c.rho = (float)pGenome->express(pSpecies,CRWgenelocn+2+sex); + trfrCRWTraits c; c.stepLength = c.rho = 0.0; + if (pGenome != 0) { + if (pSpecies->has1ChromPerTrait()) { + if (sexdep) { + c.stepLength = (float)pGenome->express(CRWgenelocn + sex, 0, sex); + c.rho = (float)pGenome->express(CRWgenelocn + 2 + sex, 0, sex); + } + else { + c.stepLength = (float)pGenome->express(CRWgenelocn, 0, 0); + c.rho = (float)pGenome->express(CRWgenelocn + 1, 0, 0); + } } else { - c.stepLength = (float)pGenome->express(pSpecies,CRWgenelocn); - c.rho = (float)pGenome->express(pSpecies,CRWgenelocn+1); + if (sexdep) { + c.stepLength = (float)pGenome->express(pSpecies, CRWgenelocn + sex); + c.rho = (float)pGenome->express(pSpecies, CRWgenelocn + 2 + sex); + } + else { + c.stepLength = (float)pGenome->express(pSpecies, CRWgenelocn); + c.rho = (float)pGenome->express(pSpecies, CRWgenelocn + 1); + } } } -} #if RSDEBUG -//DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId -// << " c.stepLength=" << c.stepLength << " c.rho=" << c.rho -// << endl; + //DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId + // << " c.stepLength=" << c.stepLength << " c.rho=" << c.rho + // << endl; #endif -trfrCRWParams cparams; -if (sexdep) { - cparams = pSpecies->getCRWParams(0,sex); -} -else { - cparams = pSpecies->getCRWParams(0,0); -} -crw->stepL = (float)(c.stepLength*cparams.stepLScale + cparams.stepLgthMean); -crw->rho = (float)(c.rho*cparams.rhoScale + cparams.rhoMean); + trfrCRWParams cparams; + if (sexdep) { + cparams = pSpecies->getCRWParams(0, sex); + } + else { + cparams = pSpecies->getCRWParams(0, 0); + } + crw->stepL = (float)(c.stepLength * cparams.stepLScale + cparams.stepLgthMean); + crw->rho = (float)(c.rho * cparams.rhoScale + cparams.rhoMean); #if RSDEBUG -//DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId -// << " crw->stepL=" << crw->stepL << " crw->rho=" << crw->rho -// << endl; + //DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId + // << " crw->stepL=" << crw->stepL << " crw->rho=" << crw->rho + // << endl; #endif -if (crw->stepL < 1.0) crw->stepL = 1.0; -if (crw->rho < 0.0) crw->rho = 0.0; -if (crw->rho > 0.999) crw->rho = 0.999f; + if (crw->stepL < 1.0) crw->stepL = 1.0; + if (crw->rho < 0.0) crw->rho = 0.0; + if (crw->rho > 0.999) crw->rho = 0.999f; #if RSDEBUG -//DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId -// << " crw->stepL=" << crw->stepL << " crw->rho=" << crw->rho -// << endl; + //DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId + // << " crw->stepL=" << crw->stepL << " crw->rho=" << crw->rho + // << endl; #endif -return; + return; } // Get phenotypic transfer by CRW traits trfrCRWTraits Individual::getCRWTraits(void) { #if RSDEBUG -//DEBUGLOG << "Individual::getCRWTraits(): indId=" << indId -// << endl; + //DEBUGLOG << "Individual::getCRWTraits(): indId=" << indId + // << endl; #endif -trfrCRWTraits c; c.stepLength = c.rho = 0.0; -if (crw != 0) { - c.stepLength = crw->stepL; - c.rho = crw->rho; -} + trfrCRWTraits c; c.stepLength = c.rho = 0.0; + if (crw != 0) { + c.stepLength = crw->stepL; + c.rho = crw->rho; + } #if RSDEBUG -//DEBUGLOG << "Individual::getCRWTraits(): indId=" << indId -// << " c.stepLength=" << c.stepLength << " c.rho=" << c.rho -// << endl; + //DEBUGLOG << "Individual::getCRWTraits(): indId=" << indId + // << " c.stepLength=" << c.stepLength << " c.rho=" << c.rho + // << endl; #endif -return c; + return c; } // Set phenotypic settlement traits -void Individual::setSettTraits(Species *pSpecies,short settgenelocn,short nsetttraits, +void Individual::setSettTraits(Species* pSpecies, short settgenelocn, short nsetttraits, bool sexdep) { #if RSDEBUG -//DEBUGLOG << "Individual::setSettTraits(): indId=" << indId << " sex=" << sex -// << " settgenelocn=" << settgenelocn << " nsetttraits=" << nsetttraits << " sexdep=" << sexdep -// << endl; + //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId << " sex=" << sex + // << " settgenelocn=" << settgenelocn << " nsetttraits=" << nsetttraits << " sexdep=" << sexdep + // << endl; #endif //simParams sim = paramsSim->getSim(); -settleTraits s; s.s0 = s.alpha = s.beta = 0.0; -if (pGenome != 0) { - if (pSpecies->has1ChromPerTrait()) { - if (sexdep) { - s.s0 = (float)pGenome->express(settgenelocn+3*sex,0,0); - s.alpha = (float)pGenome->express(settgenelocn+3*sex+1,0,0); - s.beta = (float)pGenome->express(settgenelocn+3*sex+2,0,0); + settleTraits s; s.s0 = s.alpha = s.beta = 0.0; + if (pGenome != 0) { + if (pSpecies->has1ChromPerTrait()) { + if (sexdep) { + s.s0 = (float)pGenome->express(settgenelocn + 3 * sex, 0, 0); + s.alpha = (float)pGenome->express(settgenelocn + 3 * sex + 1, 0, 0); + s.beta = (float)pGenome->express(settgenelocn + 3 * sex + 2, 0, 0); + } + else { + s.s0 = (float)pGenome->express(settgenelocn, 0, 0); + s.alpha = (float)pGenome->express(settgenelocn + 1, 0, 0); + s.beta = (float)pGenome->express(settgenelocn + 2, 0, 0); + } } else { - s.s0 = (float)pGenome->express(settgenelocn,0,0); - s.alpha = (float)pGenome->express(settgenelocn+1,0,0); - s.beta = (float)pGenome->express(settgenelocn+2,0,0); + if (sexdep) { + s.s0 = (float)pGenome->express(pSpecies, settgenelocn + 3 * sex); + s.alpha = (float)pGenome->express(pSpecies, settgenelocn + 3 * sex + 1); + s.beta = (float)pGenome->express(pSpecies, settgenelocn + 3 * sex + 2); + } + else { + s.s0 = (float)pGenome->express(pSpecies, settgenelocn); + s.alpha = (float)pGenome->express(pSpecies, settgenelocn + 1); + s.beta = (float)pGenome->express(pSpecies, settgenelocn + 2); + } + } } - else { - if (sexdep) { - s.s0 = (float)pGenome->express(pSpecies,settgenelocn+3*sex); - s.alpha = (float)pGenome->express(pSpecies,settgenelocn+3*sex+1); - s.beta = (float)pGenome->express(pSpecies,settgenelocn+3*sex+2); - } - else { - s.s0 = (float)pGenome->express(pSpecies,settgenelocn); - s.alpha = (float)pGenome->express(pSpecies,settgenelocn+1); - s.beta = (float)pGenome->express(pSpecies,settgenelocn+2); - } - - } -} #if RSDEBUG -//DEBUGLOG << "Individual::setSettTraits(): indId=" << indId -// << " s.s0=" << s.s0 << " s.alpha=" << s.alpha << " s.beta=" << s.beta -// << endl; + //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId + // << " s.s0=" << s.s0 << " s.alpha=" << s.alpha << " s.beta=" << s.beta + // << endl; #endif -settParams sparams; -if (sexdep) { - sparams = pSpecies->getSettParams(0,sex); -} -else { - sparams = pSpecies->getSettParams(0,0); -} + settParams sparams; + if (sexdep) { + sparams = pSpecies->getSettParams(0, sex); + } + else { + sparams = pSpecies->getSettParams(0, 0); + } #if RSDEBUG -//DEBUGLOG << "Individual::setSettTraits(): indId=" << indId -// << " sparams.s0Mean=" << sparams.s0Mean << " sparams.s0SD=" << sparams.s0SD -// << " sparams.s0Scale=" << sparams.s0Scale -// << endl; + //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId + // << " sparams.s0Mean=" << sparams.s0Mean << " sparams.s0SD=" << sparams.s0SD + // << " sparams.s0Scale=" << sparams.s0Scale + // << endl; #endif -setttraits = new settleTraits; -setttraits->s0 = (float)(s.s0*sparams.s0Scale + sparams.s0Mean); -setttraits->alpha = (float)(s.alpha*sparams.alphaSScale + sparams.alphaSMean); -setttraits->beta = (float)(s.beta*sparams.betaSScale + sparams.betaSMean); + setttraits = new settleTraits; + setttraits->s0 = (float)(s.s0 * sparams.s0Scale + sparams.s0Mean); + setttraits->alpha = (float)(s.alpha * sparams.alphaSScale + sparams.alphaSMean); + setttraits->beta = (float)(s.beta * sparams.betaSScale + sparams.betaSMean); #if RSDEBUG -//DEBUGLOG << "Individual::setSettTraits(): indId=" << indId -// << " setttraits->s0=" << setttraits->s0 -// << " setttraits->alpha=" << setttraits->alpha << " setttraits->beta=" << setttraits->beta -// << endl; + //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId + // << " setttraits->s0=" << setttraits->s0 + // << " setttraits->alpha=" << setttraits->alpha << " setttraits->beta=" << setttraits->beta + // << endl; #endif -if (setttraits->s0 < 0.0) setttraits->s0 = 0.0; -if (setttraits->s0 > 1.0) setttraits->s0 = 1.0; + if (setttraits->s0 < 0.0) setttraits->s0 = 0.0; + if (setttraits->s0 > 1.0) setttraits->s0 = 1.0; #if RSDEBUG -//DEBUGLOG << "Individual::setSettTraits(): indId=" << indId -// << " setttraits->s0=" << setttraits->s0 -// << " setttraits->alpha=" << setttraits->alpha << " setttraits->beta=" << setttraits->beta -// << endl; + //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId + // << " setttraits->s0=" << setttraits->s0 + // << " setttraits->alpha=" << setttraits->alpha << " setttraits->beta=" << setttraits->beta + // << endl; #endif -return; + return; } // Get phenotypic settlement traits settleTraits Individual::getSettTraits(void) { #if RSDEBUG -//DEBUGLOG << "Individual::getSettTraits(): indId=" << indId -// << endl; + //DEBUGLOG << "Individual::getSettTraits(): indId=" << indId + // << endl; #endif -settleTraits s; s.s0 = s.alpha = s.beta = 0.0; -if (setttraits != 0) { - s.s0 = setttraits->s0; - s.alpha = setttraits->alpha; - s.beta = setttraits->beta; -} + settleTraits s; s.s0 = s.alpha = s.beta = 0.0; + if (setttraits != 0) { + s.s0 = setttraits->s0; + s.alpha = setttraits->alpha; + s.beta = setttraits->beta; + } #if RSDEBUG -//DEBUGLOG << "Individual::getSettTraits(): indId=" << indId -// << " s.s0=" << s.s0 << " s.alpha=" << s.alpha << " s.beta=" << s.beta -// << endl; + //DEBUGLOG << "Individual::getSettTraits(): indId=" << indId + // << " s.s0=" << s.s0 << " s.alpha=" << s.alpha << " s.beta=" << s.beta + // << endl; #endif -return s; + return s; } /* @@ -1093,29 +1093,29 @@ return l; */ void Individual::setStatus(short s) { -if (s >= 0 && s <= 9) status = s; -status = s; + if (s >= 0 && s <= 9) status = s; + status = s; } void Individual::developing(void) { -isDeveloping = true; + isDeveloping = true; } void Individual::develop(void) { -stage++; isDeveloping = false; + stage++; isDeveloping = false; } void Individual::ageIncrement(short maxage) { -if (status < 6) { // alive - age++; - if (age > maxage) status = 9; // exceeds max. age - dies - else { - if (path != 0) path->year = 0; // reset annual step count for movement models - if (status == 3) // waiting to continue dispersal - status = 1; + if (status < 6) { // alive + age++; + if (age > maxage) status = 9; // exceeds max. age - dies + else { + if (path != 0) path->year = 0; // reset annual step count for movement models + if (status == 3) // waiting to continue dispersal + status = 1; + } } } -} void Individual::incFallow(void) { fallow++; } @@ -1123,105 +1123,105 @@ void Individual::resetFallow(void) { fallow = 0; } //--------------------------------------------------------------------------- // Move to a specified neighbouring cell -void Individual::moveto(Cell *newCell) { -// check that location is indeed a neighbour of the current cell -locn currloc = pCurrCell->getLocn(); -locn newloc = newCell->getLocn(); -double d = sqrt(((double)currloc.x-(double)newloc.x)*((double)currloc.x-(double)newloc.x) - + ((double)currloc.y-(double)newloc.y)*((double)currloc.y-(double)newloc.y)); -if (d >= 1.0 && d < 1.5) { // ok - pCurrCell = newCell; status = 5; -} +void Individual::moveto(Cell* newCell) { + // check that location is indeed a neighbour of the current cell + locn currloc = pCurrCell->getLocn(); + locn newloc = newCell->getLocn(); + double d = sqrt(((double)currloc.x - (double)newloc.x) * ((double)currloc.x - (double)newloc.x) + + ((double)currloc.y - (double)newloc.y) * ((double)currloc.y - (double)newloc.y)); + if (d >= 1.0 && d < 1.5) { // ok + pCurrCell = newCell; status = 5; + } } //--------------------------------------------------------------------------- // Move to a new cell by sampling a dispersal distance from a single or double // negative exponential kernel // Returns 1 if still dispersing (including having found a potential patch), otherwise 0 -int Individual::moveKernel(Landscape *pLandscape,Species *pSpecies, - const short repType,const bool absorbing) +int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, + const short repType, const bool absorbing) { -intptr patch; -int patchNum = 0; -int newX = 0,newY = 0; -int dispersing = 1; -double xrand,yrand,meandist,dist,r1,rndangle,nx,ny; -float localK; -trfrKernTraits kern; -Cell* pCell; -Patch* pPatch; -locn loc = pCurrCell->getLocn(); - -landData land = pLandscape->getLandData(); - -bool usefullkernel = pSpecies->useFullKernel(); -trfrRules trfr = pSpecies->getTrfr(); -settleRules sett = pSpecies->getSettRules(stage,sex); - -pCell = NULL; -pPatch = NULL; - -if (trfr.indVar) { // get individual's kernel parameters - kern.meanDist1 = kern.meanDist2 = kern.probKern1 = 0.0; -// kparams = pSpecies->getKernParams(stage,sex); - if (pGenome != 0) { - kern.meanDist1 = kerntraits->meanDist1; - if (trfr.twinKern) - { - kern.meanDist2 = kerntraits->meanDist2; - kern.probKern1 = kerntraits->probKern1; - } - } -} -else { // get kernel parameters for the species - if (trfr.sexDep) { - if (trfr.stgDep) { - kern = pSpecies->getKernTraits(stage,sex); - } - else { - kern = pSpecies->getKernTraits(0,sex); + intptr patch; + int patchNum = 0; + int newX = 0, newY = 0; + int dispersing = 1; + double xrand, yrand, meandist, dist, r1, rndangle, nx, ny; + float localK; + trfrKernTraits kern; + Cell* pCell; + Patch* pPatch; + locn loc = pCurrCell->getLocn(); + + landData land = pLandscape->getLandData(); + + bool usefullkernel = pSpecies->useFullKernel(); + trfrRules trfr = pSpecies->getTrfr(); + settleRules sett = pSpecies->getSettRules(stage, sex); + + pCell = NULL; + pPatch = NULL; + + if (trfr.indVar) { // get individual's kernel parameters + kern.meanDist1 = kern.meanDist2 = kern.probKern1 = 0.0; + // kparams = pSpecies->getKernParams(stage,sex); + if (pGenome != 0) { + kern.meanDist1 = kerntraits->meanDist1; + if (trfr.twinKern) + { + kern.meanDist2 = kerntraits->meanDist2; + kern.probKern1 = kerntraits->probKern1; + } } } - else { - if (trfr.stgDep) { - kern = pSpecies->getKernTraits(stage,0); + else { // get kernel parameters for the species + if (trfr.sexDep) { + if (trfr.stgDep) { + kern = pSpecies->getKernTraits(stage, sex); + } + else { + kern = pSpecies->getKernTraits(0, sex); + } } else { - kern = pSpecies->getKernTraits(0,0); + if (trfr.stgDep) { + kern = pSpecies->getKernTraits(stage, 0); + } + else { + kern = pSpecies->getKernTraits(0, 0); + } } } -} #if RSDEBUG -//Patch *startPatch = (Patch*)startpatch; -//DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " x=" << loc.x << " y=" << loc.y -//// << " natalPatch = " << natalPatch -//// << " startpatch = " << startpatch << " patchNum = " << startPatch->getPatchNum() -// << " kern.meanDist1=" << kern.meanDist1; -//if (trfr.twinKern) { -// DEBUGLOG << " meanDist2=" << kern.meanDist2 << " probKern1=" << kern.probKern1; -//} -//DEBUGLOG << endl; + //Patch *startPatch = (Patch*)startpatch; + //DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " x=" << loc.x << " y=" << loc.y + //// << " natalPatch = " << natalPatch + //// << " startpatch = " << startpatch << " patchNum = " << startPatch->getPatchNum() + // << " kern.meanDist1=" << kern.meanDist1; + //if (trfr.twinKern) { + // DEBUGLOG << " meanDist2=" << kern.meanDist2 << " probKern1=" << kern.probKern1; + //} + //DEBUGLOG << endl; #endif // scale the appropriate kernel mean to the cell size -if (trfr.twinKern) -{ - if (pRandom->Bernoulli(kern.probKern1)) - meandist = kern.meanDist1 / (float)land.resol; + if (trfr.twinKern) + { + if (pRandom->Bernoulli(kern.probKern1)) + meandist = kern.meanDist1 / (float)land.resol; + else + meandist = kern.meanDist2 / (float)land.resol; + } else - meandist = kern.meanDist2 / (float)land.resol; -} -else - meandist = kern.meanDist1 / (float)land.resol; + meandist = kern.meanDist1 / (float)land.resol; #if RSDEBUG -//DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " meandist=" << meandist << endl; + //DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " meandist=" << meandist << endl; #endif // scaled mean may not be less than 1 unless emigration derives from the kernel // (i.e. the 'use full kernel' option is applied) -if (!usefullkernel && meandist < 1.0) meandist = 1.0; + if (!usefullkernel && meandist < 1.0) meandist = 1.0; #if RSDEBUG -//DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " meandist=" << meandist << endl; + //DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " meandist=" << meandist << endl; #endif #if RSDEBUG @@ -1236,392 +1236,390 @@ if (!usefullkernel && meandist < 1.0) meandist = 1.0; //DEBUGLOG << " meandist = " << meandist << endl; #endif -int loopsteps = 0; // new counter to prevent infinite loop added 14/8/15 -do { + int loopsteps = 0; // new counter to prevent infinite loop added 14/8/15 do { do { - // randomise the cell within the patch, provided that the individual is still in - // its natal cell (i.e. not waiting in the matrix) - // this is because, if the patch is very large, the individual is near the centre - // and the (single) kernel mean is (not much more than) the cell size, an infinite - // loop could otherwise result, as the individual never reaches the patch edge - // (in a cell-based model, this has no effect, other than as a processing overhead) - if (status == 1) { - pCell = pNatalPatch->getRandomCell(); - if (pCell != 0) { - loc = pCell->getLocn(); + do { + // randomise the cell within the patch, provided that the individual is still in + // its natal cell (i.e. not waiting in the matrix) + // this is because, if the patch is very large, the individual is near the centre + // and the (single) kernel mean is (not much more than) the cell size, an infinite + // loop could otherwise result, as the individual never reaches the patch edge + // (in a cell-based model, this has no effect, other than as a processing overhead) + if (status == 1) { + pCell = pNatalPatch->getRandomCell(); + if (pCell != 0) { + loc = pCell->getLocn(); + } } - } - // randomise the position of the individual inside the cell - xrand = (double)loc.x + pRandom->Random()*0.999; - yrand = (double)loc.y + pRandom->Random()*0.999; + // randomise the position of the individual inside the cell + xrand = (double)loc.x + pRandom->Random() * 0.999; + yrand = (double)loc.y + pRandom->Random() * 0.999; + + r1 = 0.0000001 + pRandom->Random() * (1.0 - 0.0000001); + // dist = (-1.0*meandist)*std::log(r1); + dist = (-1.0 * meandist) * log(r1); // for LINUX_CLUSTER - r1 = 0.0000001 + pRandom->Random()*(1.0-0.0000001); -// dist = (-1.0*meandist)*std::log(r1); - dist = (-1.0*meandist)*log(r1); // for LINUX_CLUSTER - - rndangle = pRandom->Random() * 2.0 * PI; - nx = xrand + dist * sin(rndangle); - ny = yrand + dist * cos(rndangle); - if (nx < 0.0) newX = -1; else newX = (int)nx; - if (ny < 0.0) newY = -1; else newY = (int)ny; + rndangle = pRandom->Random() * 2.0 * PI; + nx = xrand + dist * sin(rndangle); + ny = yrand + dist * cos(rndangle); + if (nx < 0.0) newX = -1; else newX = (int)nx; + if (ny < 0.0) newY = -1; else newY = (int)ny; #if RSDEBUG - if (path != 0) (path->year)++; + if (path != 0) (path->year)++; #endif - loopsteps++; + loopsteps++; #if RSDEBUG -//DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " status=" << status -// << " loopsteps=" << loopsteps << " newX=" << newX << " newY=" << newY -// << " loc.x=" << loc.x << " loc.y=" << loc.y -// << endl; + //DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " status=" << status + // << " loopsteps=" << loopsteps << " newX=" << newX << " newY=" << newY + // << " loc.x=" << loc.x << " loc.y=" << loc.y + // << endl; #endif - } while (loopsteps < 1000 && + } while (loopsteps < 1000 && ((!absorbing && (newX < land.minX || newX > land.maxX - || newY < land.minY || newY > land.maxY)) - || (!usefullkernel && newX == loc.x && newY == loc.y)) + || newY < land.minY || newY > land.maxY)) + || (!usefullkernel && newX == loc.x && newY == loc.y)) ); - if (loopsteps < 1000) { - if (newX < land.minX || newX > land.maxX + if (loopsteps < 1000) { + if (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY) { // beyond absorbing boundary - pCell = 0; - patch = 0; - patchNum = -1; - } - else { - pCell = pLandscape->findCell(newX,newY); - if (pCell == 0) { // no-data cell + pCell = 0; patch = 0; patchNum = -1; } else { - patch = pCell->getPatch(); - if (patch == 0) { // matrix - pPatch = 0; - patchNum = 0; + pCell = pLandscape->findCell(newX, newY); + if (pCell == 0) { // no-data cell + patch = 0; + patchNum = -1; } else { - pPatch = (Patch*)patch; - patchNum = pPatch->getPatchNum(); + patch = pCell->getPatch(); + if (patch == 0) { // matrix + pPatch = 0; + patchNum = 0; + } + else { + pPatch = (Patch*)patch; + patchNum = pPatch->getPatchNum(); + } } } } - } - else { - patch = 0; - patchNum = -1; - } + else { + patch = 0; + patchNum = -1; + } #if RSDEBUG -//DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " status=" << status -// << " loopsteps=" << loopsteps << " newX=" << newX << " newY=" << newY -// << " pCell=" << pCell << " patch=" << patch << " patchNum=" << patchNum -// << endl; + //DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " status=" << status + // << " loopsteps=" << loopsteps << " newX=" << newX << " newY=" << newY + // << " pCell=" << pCell << " patch=" << patch << " patchNum=" << patchNum + // << endl; #endif - } while (!absorbing && patchNum < 0 && loopsteps < 1000); // in a no-data region -} -while (!usefullkernel && pPatch == pNatalPatch && loopsteps < 1000); // still in the original (natal) patch + } while (!absorbing && patchNum < 0 && loopsteps < 1000); // in a no-data region + } while (!usefullkernel && pPatch == pNatalPatch && loopsteps < 1000); // still in the original (natal) patch -if (loopsteps < 1000) { - if (pCell == 0) { // beyond absorbing boundary or in no-data cell - pCurrCell = 0; - status = 6; - dispersing = 0; - } - else { - pCurrCell = pCell; - if (pPatch == 0) localK = 0.0; // matrix - else localK = pPatch->getK(); - if (patchNum > 0 && localK > 0.0) { // found a new patch - status = 2; // record as potential settler + if (loopsteps < 1000) { + if (pCell == 0) { // beyond absorbing boundary or in no-data cell + pCurrCell = 0; + status = 6; + dispersing = 0; } else { - dispersing = 0; - // can wait in matrix if population is stage structured ... - if (pSpecies->stageStructured()) { - // ... and wait option is applied ... - if (sett.wait) { // ... it is - status = 3; // waiting + pCurrCell = pCell; + if (pPatch == 0) localK = 0.0; // matrix + else localK = pPatch->getK(); + if (patchNum > 0 && localK > 0.0) { // found a new patch + status = 2; // record as potential settler + } + else { + dispersing = 0; + // can wait in matrix if population is stage structured ... + if (pSpecies->stageStructured()) { + // ... and wait option is applied ... + if (sett.wait) { // ... it is + status = 3; // waiting + } + else // ... it is not + status = 6; // dies (unless there is a suitable neighbouring cell) } - else // ... it is not + else status = 6; // dies (unless there is a suitable neighbouring cell) } - else - status = 6; // dies (unless there is a suitable neighbouring cell) } } -} -else { - status = 6; - dispersing = 0; -} -#if RSDEBUG -//DEBUGLOG << "Individual::moveKernel(): indId=" << indId -// << " newX=" << newX << " newY=" << newY -// << " patch=" << patch -// << " patchNum=" << patchNum << " status=" << status; -//DEBUGLOG << endl; -#endif - -// apply dispersal-related mortality, which may be distance-dependent -dist *= (float)land.resol; // re-scale distance moved to landscape scale -if (status < 7) { - double dispmort; - trfrMortParams mort = pSpecies->getMortParams(); - if (trfr.distMort) { - dispmort = 1.0 / (1.0 + exp(-(dist - mort.mortBeta)*mort.mortAlpha)); - } else { - dispmort = mort.fixedMort; - } - if (pRandom->Bernoulli(dispmort)) { - status = 7; // dies + status = 6; dispersing = 0; } -} +#if RSDEBUG + //DEBUGLOG << "Individual::moveKernel(): indId=" << indId + // << " newX=" << newX << " newY=" << newY + // << " patch=" << patch + // << " patchNum=" << patchNum << " status=" << status; + //DEBUGLOG << endl; +#endif + +// apply dispersal-related mortality, which may be distance-dependent + dist *= (float)land.resol; // re-scale distance moved to landscape scale + if (status < 7) { + double dispmort; + trfrMortParams mort = pSpecies->getMortParams(); + if (trfr.distMort) { + dispmort = 1.0 / (1.0 + exp(-(dist - mort.mortBeta) * mort.mortAlpha)); + } + else { + dispmort = mort.fixedMort; + } + if (pRandom->Bernoulli(dispmort)) { + status = 7; // dies + dispersing = 0; + } + } -return dispersing; + return dispersing; } //--------------------------------------------------------------------------- // Make a single movement step according to a mechanistic movement model // Returns 1 if still dispersing (including having found a potential patch), otherwise 0 -int Individual::moveStep(Landscape *pLandscape,Species *pSpecies, - const short landIx,const bool absorbing) +int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, + const short landIx, const bool absorbing) { -if (status != 1) return 0; // not currently dispersing + if (status != 1) return 0; // not currently dispersing -intptr patch; -int patchNum; -int newX,newY; -locn loc; -int dispersing = 1; -double xcnew,ycnew; -double angle; -double mortprob,rho,steplen; -movedata move; -Patch* pPatch = 0; -bool absorbed = false; -//int popsize; + intptr patch; + int patchNum; + int newX, newY; + locn loc; + int dispersing = 1; + double xcnew, ycnew; + double angle; + double mortprob, rho, steplen; + movedata move; + Patch* pPatch = 0; + bool absorbed = false; + //int popsize; -landData land = pLandscape->getLandData(); -simParams sim = paramsSim->getSim(); + landData land = pLandscape->getLandData(); + simParams sim = paramsSim->getSim(); -trfrRules trfr = pSpecies->getTrfr(); -trfrCRWTraits movt = pSpecies->getCRWTraits(); -settleSteps settsteps = pSpecies->getSteps(stage,sex); + trfrRules trfr = pSpecies->getTrfr(); + trfrCRWTraits movt = pSpecies->getCRWTraits(); + settleSteps settsteps = pSpecies->getSteps(stage, sex); -patch = pCurrCell->getPatch(); + patch = pCurrCell->getPatch(); #if RSDEBUG -//DEBUGLOG << "Individual::moveStep() AAAA: indId=" << indId -// << " pCurrCell=" << pCurrCell << " patch=" << patch -// << endl; + //DEBUGLOG << "Individual::moveStep() AAAA: indId=" << indId + // << " pCurrCell=" << pCurrCell << " patch=" << patch + // << endl; #endif -if (patch == 0) { // matrix - pPatch = 0; - patchNum = 0; -} -else { - pPatch = (Patch*)patch; - patchNum = pPatch->getPatchNum(); -} -// apply step-dependent mortality risk ... -if (trfr.habMort) -{ // habitat-dependent - int h = pCurrCell->getHabIndex(landIx); - if (h < 0) { // no-data cell - should not occur, but if it does, individual dies - mortprob = 1.0; + if (patch == 0) { // matrix + pPatch = 0; + patchNum = 0; + } + else { + pPatch = (Patch*)patch; + patchNum = pPatch->getPatchNum(); } - else mortprob = pSpecies->getHabMort(h); + // apply step-dependent mortality risk ... + if (trfr.habMort) + { // habitat-dependent + int h = pCurrCell->getHabIndex(landIx); + if (h < 0) { // no-data cell - should not occur, but if it does, individual dies + mortprob = 1.0; + } + else mortprob = pSpecies->getHabMort(h); #if RSDEBUG -//locn temploc = pCurrCell->getLocn(); -//DEBUGLOG << "Individual::moveStep(): x=" << temploc.x << " y=" << temploc.x -// << " landIx=" << landIx << " h=" << h << " mortprob=" << mortprob -// << endl; + //locn temploc = pCurrCell->getLocn(); + //DEBUGLOG << "Individual::moveStep(): x=" << temploc.x << " y=" << temploc.x + // << " landIx=" << landIx << " h=" << h << " mortprob=" << mortprob + // << endl; #endif -} -else mortprob = movt.stepMort; -// ... unless individual has not yet left natal patch in emigration year -if (pPatch == pNatalPatch && path->out == 0 && path->year == path->total) { - mortprob = 0.0; -} + } + else mortprob = movt.stepMort; + // ... unless individual has not yet left natal patch in emigration year + if (pPatch == pNatalPatch && path->out == 0 && path->year == path->total) { + mortprob = 0.0; + } #if RSDEBUG -locn loc0,loc1,loc2; -//loc0 = pCurrCell->getLocn(); -//DEBUGLOG << "Individual::moveStep() BBBB: indId=" << indId << " status=" << status -// << " path->year=" << path->year << " path->out=" << path->out -// << " settleStatus=" << path->settleStatus -// << " x=" << loc0.x << " y=" << loc0.y -//// << " patch=" << patch -// << " pPatch=" << pPatch -// << " patchNum=" << patchNum; -//// << " natalPatch=" << natalPatch; -////if (crw != 0) { -//// DEBUGLOG << " xc=" << crw->xc << " yc=" << crw->yc; -//// DEBUGLOG << " rho=" << movt.rho << " stepLength=" << movt.stepLength; -////} -//DEBUGLOG << endl; -#endif -if (pRandom->Bernoulli(mortprob)) { // individual dies - status = 7; - dispersing = 0; -} -else { // take a step - (path->year)++; - (path->total)++; -// if (pPatch != pNatalPatch || path->out > 0) (path->out)++; - if (patch == 0 || pPatch == 0 || patchNum == 0) { // not in a patch - if (path != 0) path->settleStatus = 0; // reset path settlement status - (path->out)++; + locn loc0, loc1, loc2; + //loc0 = pCurrCell->getLocn(); + //DEBUGLOG << "Individual::moveStep() BBBB: indId=" << indId << " status=" << status + // << " path->year=" << path->year << " path->out=" << path->out + // << " settleStatus=" << path->settleStatus + // << " x=" << loc0.x << " y=" << loc0.y + //// << " patch=" << patch + // << " pPatch=" << pPatch + // << " patchNum=" << patchNum; + //// << " natalPatch=" << natalPatch; + ////if (crw != 0) { + //// DEBUGLOG << " xc=" << crw->xc << " yc=" << crw->yc; + //// DEBUGLOG << " rho=" << movt.rho << " stepLength=" << movt.stepLength; + ////} + //DEBUGLOG << endl; +#endif + if (pRandom->Bernoulli(mortprob)) { // individual dies + status = 7; + dispersing = 0; } - loc = pCurrCell->getLocn(); - newX = loc.x; newY = loc.y; + else { // take a step + (path->year)++; + (path->total)++; + // if (pPatch != pNatalPatch || path->out > 0) (path->out)++; + if (patch == 0 || pPatch == 0 || patchNum == 0) { // not in a patch + if (path != 0) path->settleStatus = 0; // reset path settlement status + (path->out)++; + } + loc = pCurrCell->getLocn(); + newX = loc.x; newY = loc.y; - switch (trfr.moveType) { + switch (trfr.moveType) { - case 1: // SMS + case 1: // SMS #if RSDEBUG -//loc1 = pCurrCell->getLocn(); -//DEBUGLOG << "Individual::moveStep() FFFF: indId=" << indId << " status=" << status -//// << " path->year=" << path->year -// << " path->season=" << path->season -// << " x=" << loc1.x << " y=" << loc1.y -// << " smsData->goalType=" << smsData->goalType -// << " goal.x=" << smsData->goal.x -// << " goal.y=" << smsData->goal.y -// << endl; -#endif - move = smsMove(pLandscape,pSpecies,landIx,pPatch==pNatalPatch,trfr.indVar,absorbing); -#if RSDEBUG -//DEBUGLOG << "Individual::moveStep() GGGG: indId=" << indId << " status=" << status -// << " move.dist=" << move.dist -// << endl; -#endif - if (move.dist < 0.0) { - // either INTERNAL ERROR CONDITION - INDIVIDUAL IS IN NO-DATA SQUARE - // or individual has crossed absorbing boundary ... - // ... individual dies - status = 6; - dispersing = 0; - } - else { + //loc1 = pCurrCell->getLocn(); + //DEBUGLOG << "Individual::moveStep() FFFF: indId=" << indId << " status=" << status + //// << " path->year=" << path->year + // << " path->season=" << path->season + // << " x=" << loc1.x << " y=" << loc1.y + // << " smsData->goalType=" << smsData->goalType + // << " goal.x=" << smsData->goal.x + // << " goal.y=" << smsData->goal.y + // << endl; +#endif + move = smsMove(pLandscape, pSpecies, landIx, pPatch == pNatalPatch, trfr.indVar, absorbing); +#if RSDEBUG + //DEBUGLOG << "Individual::moveStep() GGGG: indId=" << indId << " status=" << status + // << " move.dist=" << move.dist + // << endl; +#endif + if (move.dist < 0.0) { + // either INTERNAL ERROR CONDITION - INDIVIDUAL IS IN NO-DATA SQUARE + // or individual has crossed absorbing boundary ... + // ... individual dies + status = 6; + dispersing = 0; + } + else { #if RSDEBUG -//loc1 = pCurrCell->getLocn(); -//DEBUGLOG << "Individual::moveStep() HHHH: indId=" << indId << " status=" << status -// << " path->year=" << path->year -// << " x=" << loc1.x << " y=" << loc1.y -//// << " smsData = " << smsData -// << endl; + //loc1 = pCurrCell->getLocn(); + //DEBUGLOG << "Individual::moveStep() HHHH: indId=" << indId << " status=" << status + // << " path->year=" << path->year + // << " x=" << loc1.x << " y=" << loc1.y + //// << " smsData = " << smsData + // << endl; #endif // WOULD IT BE MORE EFFICIENT FOR smsMove TO RETURN A POINTER TO THE NEW CELL? ... - patch = pCurrCell->getPatch(); - //int patchnum; - if (patch == 0) { - pPatch = 0; - //patchnum = 0; - } - else { - pPatch = (Patch*)patch; - //patchnum = pPatch->getPatchNum(); - } - if (sim.saveVisits && pPatch != pNatalPatch) { - pCurrCell->incrVisits(); + patch = pCurrCell->getPatch(); + //int patchnum; + if (patch == 0) { + pPatch = 0; + //patchnum = 0; + } + else { + pPatch = (Patch*)patch; + //patchnum = pPatch->getPatchNum(); + } + if (sim.saveVisits && pPatch != pNatalPatch) { + pCurrCell->incrVisits(); + } } - } - break; + break; - case 2: // CRW - if (trfr.indVar) { - if (crw != 0) { - movt.stepLength = crw->stepL; - movt.rho = crw->rho; + case 2: // CRW + if (trfr.indVar) { + if (crw != 0) { + movt.stepLength = crw->stepL; + movt.rho = crw->rho; + } } - } - steplen = movt.stepLength; if (steplen < 0.2*land.resol) steplen = 0.2*land.resol; - rho = movt.rho; if (rho > 0.99) rho = 0.99; - if (pPatch == pNatalPatch) { - rho = 0.99; // to promote leaving natal patch - path->out = 0; - } - if (movt.straigtenPath && path->settleStatus > 0) { - // individual is in a patch and has already determined whether to settle - rho = 0.99; // to promote leaving the patch - path->out = 0; - } - int loopsteps = 0; // new counter to prevent infinite loop added 14/8/15 - do { + steplen = movt.stepLength; if (steplen < 0.2 * land.resol) steplen = 0.2 * land.resol; + rho = movt.rho; if (rho > 0.99) rho = 0.99; + if (pPatch == pNatalPatch) { + rho = 0.99; // to promote leaving natal patch + path->out = 0; + } + if (movt.straigtenPath && path->settleStatus > 0) { + // individual is in a patch and has already determined whether to settle + rho = 0.99; // to promote leaving the patch + path->out = 0; + } + int loopsteps = 0; // new counter to prevent infinite loop added 14/8/15 do { - // new direction - if (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY - || pCurrCell == 0) { - // individual has tried to go out-of-bounds or into no-data area - // allow random move to prevent repeated similar move - angle = wrpcauchy(crw->prevdrn,0.0); + do { + // new direction + if (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY + || pCurrCell == 0) { + // individual has tried to go out-of-bounds or into no-data area + // allow random move to prevent repeated similar move + angle = wrpcauchy(crw->prevdrn, 0.0); + } + else + angle = wrpcauchy(crw->prevdrn, rho); + // new continuous cell coordinates + xcnew = crw->xc + sin(angle) * steplen / (float)land.resol; + ycnew = crw->yc + cos(angle) * steplen / (float)land.resol; + if (xcnew < 0.0) newX = -1; else newX = (int)xcnew; + if (ycnew < 0.0) newY = -1; else newY = (int)ycnew; + loopsteps++; +#if RSDEBUG + //DEBUGLOG << "Individual::moveStep(): indId=" << indId + // << " xc=" << crw->xc << " yc=" << crw->yc << " pCurrCell=" << pCurrCell + // << " steps=" << path->year << " loopsteps=" << loopsteps + // << " steplen=" << steplen << " rho=" << rho << " angle=" << angle + // << " xcnew=" << xcnew << " ycnew=" << ycnew << " newX=" << newX << " newY=" << newY << endl; +#endif + } while (!absorbing && loopsteps < 1000 && + (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY)); + if (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY) + pCurrCell = 0; + else + pCurrCell = pLandscape->findCell(newX, newY); + if (pCurrCell == 0) { // no-data cell or beyond absorbing boundary + patch = 0; + if (absorbing) absorbed = true; } else - angle = wrpcauchy(crw->prevdrn,rho); - // new continuous cell coordinates - xcnew = crw->xc + sin(angle) * steplen/(float)land.resol; - ycnew = crw->yc + cos(angle) * steplen/(float)land.resol; - if (xcnew < 0.0) newX = -1; else newX = (int)xcnew; - if (ycnew < 0.0) newY = -1; else newY = (int)ycnew; - loopsteps++; -#if RSDEBUG -//DEBUGLOG << "Individual::moveStep(): indId=" << indId -// << " xc=" << crw->xc << " yc=" << crw->yc << " pCurrCell=" << pCurrCell -// << " steps=" << path->year << " loopsteps=" << loopsteps -// << " steplen=" << steplen << " rho=" << rho << " angle=" << angle -// << " xcnew=" << xcnew << " ycnew=" << ycnew << " newX=" << newX << " newY=" << newY << endl; -#endif - } - while (!absorbing && loopsteps < 1000 && - (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY)); - if (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY) - pCurrCell = 0; - else - pCurrCell = pLandscape->findCell(newX,newY); - if (pCurrCell == 0) { // no-data cell or beyond absorbing boundary - patch = 0; - if (absorbing) absorbed = true; - } - else - patch = pCurrCell->getPatch(); + patch = pCurrCell->getPatch(); #if RSDEBUG -//DEBUGLOG << "Individual::moveStep(): indId=" << indId -// << " loopsteps=" << loopsteps << " absorbed=" << absorbed -// << " pCurrCell=" << pCurrCell << " patch=" << patch << endl; + //DEBUGLOG << "Individual::moveStep(): indId=" << indId + // << " loopsteps=" << loopsteps << " absorbed=" << absorbed + // << " pCurrCell=" << pCurrCell << " patch=" << patch << endl; #endif - } while (!absorbing && pCurrCell == 0 && loopsteps < 1000); - crw->prevdrn = (float)angle; - crw->xc = (float)xcnew; crw->yc = (float)ycnew; - if (absorbed) { // beyond absorbing boundary or in no-data square - status = 6; - dispersing = 0; - pCurrCell = 0; - } - else { - if (loopsteps >= 1000) { // unable to make a move - // INTERNAL ERROR CONDITION - INDIVIDUAL IS IN NO-DATA SQUARE - // NEED TO TAKE SOME FORM OF INFORMATIVE ACTION ... - // ... individual dies as it cannot move + } while (!absorbing && pCurrCell == 0 && loopsteps < 1000); + crw->prevdrn = (float)angle; + crw->xc = (float)xcnew; crw->yc = (float)ycnew; + if (absorbed) { // beyond absorbing boundary or in no-data square status = 6; dispersing = 0; - // current cell will be invalid (zero), so set back to previous cell - pCurrCell = pPrevCell; + pCurrCell = 0; + } + else { + if (loopsteps >= 1000) { // unable to make a move + // INTERNAL ERROR CONDITION - INDIVIDUAL IS IN NO-DATA SQUARE + // NEED TO TAKE SOME FORM OF INFORMATIVE ACTION ... + // ... individual dies as it cannot move + status = 6; + dispersing = 0; + // current cell will be invalid (zero), so set back to previous cell + pCurrCell = pPrevCell; + } } - } #if RSDEBUG -//DEBUGLOG << "Individual::moveStep(): indId=" << indId -// << " status=" << status -// << " pCurrCell=" << pCurrCell << " patch=" << patch << endl; + //DEBUGLOG << "Individual::moveStep(): indId=" << indId + // << " status=" << status + // << " pCurrCell=" << pCurrCell << " patch=" << patch << endl; #endif - break; + break; - } // end of switch (trfr.moveType) + } // end of switch (trfr.moveType) #if RSDEBUG //locn loc2; @@ -1644,30 +1642,30 @@ else { // take a step //} // DEBUGLOG << endl; #endif - if (patch > 0 // not no-data area or matrix - && path->total >= settsteps.minSteps) { - pPatch = (Patch*)patch; - if (pPatch != pNatalPatch) - { - // determine whether the new patch is potentially suitable - if (pPatch->getK() > 0.0) - { // patch is suitable + if (patch > 0 // not no-data area or matrix + && path->total >= settsteps.minSteps) { + pPatch = (Patch*)patch; + if (pPatch != pNatalPatch) + { + // determine whether the new patch is potentially suitable + if (pPatch->getK() > 0.0) + { // patch is suitable status = 2; + } } } - } - if (status != 2 && status != 6) { // suitable patch not found, not already dead - if (path->year >= settsteps.maxStepsYr) { - status = 3; // waits until next year - } - if (path->total >= settsteps.maxSteps) { - status = 6; // dies - dispersing = 0; + if (status != 2 && status != 6) { // suitable patch not found, not already dead + if (path->year >= settsteps.maxStepsYr) { + status = 3; // waits until next year + } + if (path->total >= settsteps.maxSteps) { + status = 6; // dies + dispersing = 0; + } } - } -} // end of single movement step + } // end of single movement step -return dispersing; + return dispersing; } @@ -1676,59 +1674,59 @@ return dispersing; // Functions to implement the SMS algorithm // Move to a neighbouring cell according to the SMS algorithm -movedata Individual::smsMove(Landscape *pLand,Species *pSpecies, - const short landIx,const bool natalPatch,const bool indvar,const bool absorbing) +movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, + const short landIx, const bool natalPatch, const bool indvar, const bool absorbing) { -array3x3d nbr; // to hold weights/costs/probs of moving to neighbouring cells -array3x3d goal; // to hold weights for moving towards a goal location -array3x3f hab; // to hold weights for habitat (includes percep range) -int x2,y2; // x index from 0=W to 2=E, y index from 0=N to 2=S -int newX = 0,newY = 0; -Cell *pCell; -Cell *pNewCell = NULL; -double sum_nbrs = 0.0; -movedata move; -int cellcost,newcellcost; -locn current; - -//if (write_out) { -// out<findCell(x,y); -if (pCurrCell == 0) -{ -// x,y is a NODATA square - this should not occur here -// return a negative distance to indicate an error - move.dist = -69.0; move.cost = 0.0; - return move; -} + array3x3d nbr; // to hold weights/costs/probs of moving to neighbouring cells + array3x3d goal; // to hold weights for moving towards a goal location + array3x3f hab; // to hold weights for habitat (includes percep range) + int x2, y2; // x index from 0=W to 2=E, y index from 0=N to 2=S + int newX = 0, newY = 0; + Cell* pCell; + Cell* pNewCell = NULL; + double sum_nbrs = 0.0; + movedata move; + int cellcost, newcellcost; + locn current; + + //if (write_out) { + // out<findCell(x,y); + if (pCurrCell == 0) + { + // x,y is a NODATA square - this should not occur here + // return a negative distance to indicate an error + move.dist = -69.0; move.cost = 0.0; + return move; + } #if RSDEBUG -//DEBUGLOG << "Individual::smsMove(): this=" << this << endl; + //DEBUGLOG << "Individual::smsMove(): this=" << this << endl; #endif -landData land = pLand->getLandData(); -trfrSMSTraits movt = pSpecies->getSMSTraits(); -current = pCurrCell->getLocn(); + landData land = pLand->getLandData(); + trfrSMSTraits movt = pSpecies->getSMSTraits(); + current = pCurrCell->getLocn(); -//get weights for directional persistence.... -//if ((path->out > 0 && path->out < 10 && path->out < 2*movt.pr) -if ((path->out > 0 && path->out <= (movt.pr+1)) -|| natalPatch -|| (movt.straigtenPath && path->settleStatus > 0)) { - // inflate directional persistence to promote leaving the patch - if (indvar) nbr = getSimDir(current.x,current.y,10.0f*smsData->dp); - else nbr = getSimDir(current.x,current.y,10.0f*movt.dp); -} -else { - if (indvar) nbr = getSimDir(current.x,current.y,smsData->dp); - else nbr = getSimDir(current.x,current.y,movt.dp); -} -if (natalPatch || path->settleStatus > 0) path->out = 0; -//if (natalPatch) path->out = 0; + //get weights for directional persistence.... + //if ((path->out > 0 && path->out < 10 && path->out < 2*movt.pr) + if ((path->out > 0 && path->out <= (movt.pr + 1)) + || natalPatch + || (movt.straigtenPath && path->settleStatus > 0)) { + // inflate directional persistence to promote leaving the patch + if (indvar) nbr = getSimDir(current.x, current.y, 10.0f * smsData->dp); + else nbr = getSimDir(current.x, current.y, 10.0f * movt.dp); + } + else { + if (indvar) nbr = getSimDir(current.x, current.y, smsData->dp); + else nbr = getSimDir(current.x, current.y, movt.dp); + } + if (natalPatch || path->settleStatus > 0) path->out = 0; + //if (natalPatch) path->out = 0; #if RSDEBUG //DEBUGLOG << "Individual::smsMove() 0000: nbr matrix" << endl; //for (y2 = 2; y2 > -1; y2--) { @@ -1747,56 +1745,56 @@ if (natalPatch || path->settleStatus > 0) path->out = 0; // out2< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) out< -1; y2--) { + // for (x2 = 0; x2 < 3; x2++) out<getEffCosts(); // out< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) DEBUGLOG << hab.cell[x2][y2] << " "; -// DEBUGLOG << endl; -//} + //DEBUGLOG << "Individual::smsMove() 2222: " << endl; + //for (y2 = 2; y2 > -1; y2--) { + // for (x2 = 0; x2 < 3; x2++) DEBUGLOG << hab.cell[x2][y2] << " "; + // DEBUGLOG << endl; + //} #endif - pCurrCell->setEffCosts(hab); -} -else { // they have already been calculated - no action required -// if (write_out) { -// out<<"*** using previous effective costs ***"< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) { -// out< -1; y2--) { - for (x2 = 0; x2 < 3; x2++) { - if(x2 == 1 && y2 == 1) nbr.cell[x2][y2] = 0.0; - else { - if(x2 == 1 || y2 == 1) //not diagonal - nbr.cell[x2][y2] = nbr.cell[x2][y2]*goal.cell[x2][y2]*hab.cell[x2][y2]; - else // diagonal - nbr.cell[x2][y2] = (float)SQRT2*nbr.cell[x2][y2]*goal.cell[x2][y2]*hab.cell[x2][y2]; - } -// if (write_out) { -// out<setEffCosts(hab); + } + else { // they have already been calculated - no action required + // if (write_out) { + // out<<"*** using previous effective costs ***"< -1; y2--) { + // for (x2 = 0; x2 < 3; x2++) { + // out< -1; y2--) { + for (x2 = 0; x2 < 3; x2++) { + if (x2 == 1 && y2 == 1) nbr.cell[x2][y2] = 0.0; + else { + if (x2 == 1 || y2 == 1) //not diagonal + nbr.cell[x2][y2] = nbr.cell[x2][y2] * goal.cell[x2][y2] * hab.cell[x2][y2]; + else // diagonal + nbr.cell[x2][y2] = (float)SQRT2 * nbr.cell[x2][y2] * goal.cell[x2][y2] * hab.cell[x2][y2]; + } + // if (write_out) { + // out< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) DEBUGLOG << nbr.cell[x2][y2] << " "; -// DEBUGLOG << endl; -//} + //DEBUGLOG << "Individual::smsMove() 3333: " << endl; + //for (y2 = 2; y2 > -1; y2--) { + // for (x2 = 0; x2 < 3; x2++) DEBUGLOG << nbr.cell[x2][y2] << " "; + // DEBUGLOG << endl; + //} #endif // determine reciprocal of effective cost for the 8 neighbours //if (write_out) out<<"reciprocal weighted effective costs:"< -1; y2--) { - for (x2 = 0; x2 < 3; x2++) { - if (nbr.cell[x2][y2] > 0.0) nbr.cell[x2][y2] = 1.0f/nbr.cell[x2][y2]; -// if (write_out) { -// out< -1; y2--) { + for (x2 = 0; x2 < 3; x2++) { + if (nbr.cell[x2][y2] > 0.0) nbr.cell[x2][y2] = 1.0f / nbr.cell[x2][y2]; + // if (write_out) { + // out< -1; y2--) { //} #endif -for (y2 = 2; y2 > -1; y2--) { - for (x2 = 0; x2 < 3; x2++) { - if (!absorbing) { - if ((current.y+y2-1) < land.minY || (current.y+y2-1) > land.maxY - || (current.x+x2-1) < land.minX || (current.x+x2-1) > land.maxX) - // cell is beyond current landscape limits - nbr.cell[x2][y2] = 0.0; - else { // check if no-data cell - pCell = pLand->findCell((current.x+x2-1),(current.y+y2-1)); - if (pCell == 0) nbr.cell[x2][y2] = 0.0; // no-data cell + for (y2 = 2; y2 > -1; y2--) { + for (x2 = 0; x2 < 3; x2++) { + if (!absorbing) { + if ((current.y + y2 - 1) < land.minY || (current.y + y2 - 1) > land.maxY + || (current.x + x2 - 1) < land.minX || (current.x + x2 - 1) > land.maxX) + // cell is beyond current landscape limits + nbr.cell[x2][y2] = 0.0; + else { // check if no-data cell + pCell = pLand->findCell((current.x + x2 - 1), (current.y + y2 - 1)); + if (pCell == 0) nbr.cell[x2][y2] = 0.0; // no-data cell + } } - } #if RSDEBUG -//DEBUGLOG << "Individual::smsMove(): this=" << this -// << " y=" << current.y << " x=" << current.x -// << " y2=" << y2 << " x2=" << x2 -// << " pCell=" << pCell -// << endl; + //DEBUGLOG << "Individual::smsMove(): this=" << this + // << " y=" << current.y << " x=" << current.x + // << " y2=" << y2 << " x2=" << x2 + // << " pCell=" << pCell + // << endl; #endif // if (write_out) { // out< 0.0) { // should always be the case, but safest to check... - for (y2 = 2; y2 > -1; y2--) { - for (x2 = 0; x2 < 3; x2++) { - nbr.cell[x2][y2] = nbr.cell[x2][y2]/(float)sum_nbrs; -// if (write_out) { -// out< 0.0) { // should always be the case, but safest to check... + for (y2 = 2; y2 > -1; y2--) { + for (x2 = 0; x2 < 3; x2++) { + nbr.cell[x2][y2] = nbr.cell[x2][y2] / (float)sum_nbrs; + // if (write_out) { + // out< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) DEBUGLOG << nbr.cell[x2][y2] << " "; -// DEBUGLOG << endl; -//} + //DEBUGLOG << "Individual::smsMove() 4444: " << endl; + //for (y2 = 2; y2 > -1; y2--) { + // for (x2 = 0; x2 < 3; x2++) DEBUGLOG << nbr.cell[x2][y2] << " "; + // DEBUGLOG << endl; + //} #endif // set up cell selection probabilities //if (write_out) out<<"rnd = "<Random(); + j = 0; + for (y2 = 0; y2 < 3; y2++) { + for (x2 = 0; x2 < 3; x2++) { +#if RSDEBUG + //DEBUGLOG << "Individual::smsMove() 7777: rnd=" << rnd + // << " j=" << j << " cumulative[j]=" << cumulative[j] + // << endl; +#endif + if (rnd < cumulative[j]) { + newX = current.x + x2 - 1; + newY = current.y + y2 - 1; + if (x2 == 1 || y2 == 1) move.dist = (float)(land.resol); + else move.dist = (float)(land.resol) * (float)SQRT2; + // if (write_out) { + // out<<"relative x and y "< land.maxX - || newY < land.minY || newY > land.maxY))); - if (loopsteps >= 1000) pNewCell = 0; + loopsteps++; + } while (loopsteps < 1000 + && (!absorbing && (newX < land.minX || newX > land.maxX + || newY < land.minY || newY > land.maxY))); + if (loopsteps >= 1000) pNewCell = 0; + else { + if (newX < land.minX || newX > land.maxX + || newY < land.minY || newY > land.maxY) { + pNewCell = 0; + } + pNewCell = pLand->findCell(newX, newY); + } + } while (!absorbing && pNewCell == 0 && loopsteps < 1000); // no-data cell +#if RSDEBUG + //DEBUGLOG << "Individual::smsMove() 8888: pNewCell=" << pNewCell + // << " loopsteps=" << loopsteps + // << " current.x=" << current.x << " current.y=" << current.y + // << " newX=" << newX << " newY=" << newY + // << " land.minX=" << land.minX << " land.minY=" << land.minY + // << " land.maxX=" << land.maxX << " land.maxY=" << land.maxY + // << endl; +#endif + if (loopsteps >= 1000 || pNewCell == 0) { + // unable to make a move or crossed absorbing boundary + // flag individual to die + move.dist = -123.0; + if (pNewCell == 0) pCurrCell = pNewCell; + } else { - if (newX < land.minX || newX > land.maxX - || newY < land.minY || newY > land.maxY) { - pNewCell = 0; - } - pNewCell = pLand->findCell(newX,newY); + newcellcost = pNewCell->getCost(); + move.cost = move.dist * 0.5f * ((float)cellcost + (float)newcellcost); + // make the selected move + if ((short)memory.size() == movt.memSize) { + memory.pop(); // remove oldest memory element + } + memory.push(current); // record previous location in memory + //if (write_out) out << "queue length is " << memory.size() << endl; + pCurrCell = pNewCell; } -} -while (!absorbing && pNewCell == 0 && loopsteps < 1000); // no-data cell -#if RSDEBUG -//DEBUGLOG << "Individual::smsMove() 8888: pNewCell=" << pNewCell -// << " loopsteps=" << loopsteps -// << " current.x=" << current.x << " current.y=" << current.y -// << " newX=" << newX << " newY=" << newY -// << " land.minX=" << land.minX << " land.minY=" << land.minY -// << " land.maxX=" << land.maxX << " land.maxY=" << land.maxY -// << endl; -#endif -if (loopsteps >= 1000 || pNewCell == 0) { - // unable to make a move or crossed absorbing boundary - // flag individual to die - move.dist = -123.0; - if (pNewCell == 0) pCurrCell = pNewCell; -} -else { - newcellcost = pNewCell->getCost(); - move.cost = move.dist*0.5f*((float)cellcost + (float)newcellcost); - // make the selected move - if ((short)memory.size() == movt.memSize) { - memory.pop(); // remove oldest memory element - } - memory.push(current); // record previous location in memory - //if (write_out) out << "queue length is " << memory.size() << endl; - pCurrCell = pNewCell; -} -return move; + return move; } // Weight neighbouring cells on basis of current movement direction -array3x3d Individual::getSimDir(const int x, const int y, const float dp) +array3x3d Individual::getSimDir(const int x, const int y, const float dp) { -array3x3d d; -locn prev; -double theta; -int xx,yy; - -//if (write_out) out<<"step 0"<goal.x) == 0 && (y - smsData->goal.y) == 0) { - // at goal, set matrix to unity -// if (write_out) out<<"*** at goal: x,y = "<goal.x) == 0 && (y - smsData->goal.y) == 0) { + // at goal, set matrix to unity + // if (write_out) out<<"*** at goal: x,y = "<goal.x), ((double)y - (double)smsData->goal.y)); + // if (write_out) out<<"goalx,goaly: "<goal.x),((double)y-(double)smsData->goal.y)); -// if (write_out) out<<"goalx,goaly: "< 7.0 * PI / 8.0) { dx = 0; dy = -1; } -else { - if (fabs(theta) > 5.0 * PI / 8.0) { dy = -1; if (theta > 0) dx = 1; else dx = -1; } + if (fabs(theta) > 7.0 * PI / 8.0) { dx = 0; dy = -1; } else { - if (fabs(theta) > 3.0 * PI / 8.0) { dy = 0; if (theta > 0) dx = 1; else dx = -1; } + if (fabs(theta) > 5.0 * PI / 8.0) { dy = -1; if (theta > 0) dx = 1; else dx = -1; } else { - if (fabs(theta) > PI / 8.0) { dy = 1; if (theta > 0) dx = 1; else dx = -1; } - else { dy = 1; dx = 0; } + if (fabs(theta) > 3.0 * PI / 8.0) { dy = 0; if (theta > 0) dx = 1; else dx = -1; } + else { + if (fabs(theta) > PI / 8.0) { dy = 1; if (theta > 0) dx = 1; else dx = -1; } + else { dy = 1; dx = 0; } + } } - } -} -// if (write_out) out<<"goalx,goaly: "< 1) dx -= 2; yy = dy; - d.cell[xx+1][yy+1] = (float)i1; d.cell[-xx+1][yy+1] = (float)i1; - d.cell[xx+1][-yy+1] = (float)i3; d.cell[-xx+1][-yy+1] = (float)i3; - } - else { // theta points W or E - yy = dy+1; if (yy > 1) dy -= 2; xx = dx; - d.cell[xx+1][yy+1] = (float)i1; d.cell[xx+1][-yy+1] = (float)i1; - d.cell[-xx+1][yy+1] = (float)i3; d.cell[-xx+1][-yy+1] = (float)i3; - } -} -else { // theta points to an ordinal direction - d.cell[dx+1][-dy+1] = (float)i2; d.cell[-dx+1][dy+1] = (float)i2; - xx = dx+1; if (xx > 1) xx -= 2; d.cell[xx+1][dy+1] = (float)i1; - yy = dy+1; if (yy > 1) yy -= 2; d.cell[dx+1][yy+1] = (float)i1; - d.cell[-xx+1][-dy+1] = (float)i3; d.cell[-dx+1][-yy+1] = (float)i3; - } - -return d; + } + // if (write_out) out<<"goalx,goaly: "< 1) dx -= 2; yy = dy; + d.cell[xx + 1][yy + 1] = (float)i1; d.cell[-xx + 1][yy + 1] = (float)i1; + d.cell[xx + 1][-yy + 1] = (float)i3; d.cell[-xx + 1][-yy + 1] = (float)i3; + } + else { // theta points W or E + yy = dy + 1; if (yy > 1) dy -= 2; xx = dx; + d.cell[xx + 1][yy + 1] = (float)i1; d.cell[xx + 1][-yy + 1] = (float)i1; + d.cell[-xx + 1][yy + 1] = (float)i3; d.cell[-xx + 1][-yy + 1] = (float)i3; + } + } + else { // theta points to an ordinal direction + d.cell[dx + 1][-dy + 1] = (float)i2; d.cell[-dx + 1][dy + 1] = (float)i2; + xx = dx + 1; if (xx > 1) xx -= 2; d.cell[xx + 1][dy + 1] = (float)i1; + yy = dy + 1; if (yy > 1) yy -= 2; d.cell[dx + 1][yy + 1] = (float)i1; + d.cell[-xx + 1][-dy + 1] = (float)i3; d.cell[-dx + 1][-yy + 1] = (float)i3; + } + + return d; } // Weight neighbouring cells on basis of (habitat) costs -array3x3f Individual::getHabMatrix(Landscape *pLand,Species *pSpecies, - const int x,const int y,const short pr,const short prmethod,const short landIx, +array3x3f Individual::getHabMatrix(Landscape* pLand, Species* pSpecies, + const int x, const int y, const short pr, const short prmethod, const short landIx, const bool absorbing) { -array3x3f w; // array of effective costs to be returned -int ncells,x4,y4; -double weight,sumweights; -// NW and SE corners of effective cost array relative to the current cell (x,y): -int xmin = 0,ymin = 0,xmax = 0,ymax = 0; -int cost,nodatacost,h; -Cell *pCell; + array3x3f w; // array of effective costs to be returned + int ncells, x4, y4; + double weight, sumweights; + // NW and SE corners of effective cost array relative to the current cell (x,y): + int xmin = 0, ymin = 0, xmax = 0, ymax = 0; + int cost, nodatacost, h; + Cell* pCell; -landData land = pLand->getLandData(); -if (absorbing) nodatacost = ABSNODATACOST; -else nodatacost = NODATACOST; + landData land = pLand->getLandData(); + if (absorbing) nodatacost = ABSNODATACOST; + else nodatacost = NODATACOST; -for (int x2=-1; x2<2; x2++) { // index of relative move in x direction - for (int y2=-1; y2<2; y2++) { // index of relative move in x direction + for (int x2 = -1; x2 < 2; x2++) { // index of relative move in x direction + for (int y2 = -1; y2 < 2; y2++) { // index of relative move in x direction - w.cell[x2+1][y2+1] = 0.0; // initialise costs array to zeroes + w.cell[x2 + 1][y2 + 1] = 0.0; // initialise costs array to zeroes - // set up corners of perceptual range relative to current cell - if (x2==0 && y2==0) { // current cell - do nothing - xmin=0; ymin=0; xmax=0; ymax=0; - } - else { - if (x2==0 || y2==0) { // not diagonal (rook move) - if (x2==0){ // vertical (N-S) move - //out<<"ROOK N-S: x2 = "< land.maxX) x4 = x+x3-land.maxX-1; else x4 = x+x3; } - if ((y+y3) < 0) y4 = y+y3+land.maxY+1; - else { if ((y+y3) > land.maxY) y4 = y+y3-land.maxY-1; else y4 = y+y3; } -// if (write_out && (x4 < 0 || y4 < 0)) { -// out<<"ERROR: x "< land.maxX || y4 < 0 || y4 > land.maxY) { - // unexpected problem - e.g. due to ridiculously large PR - // treat as a no-data cell - cost = nodatacost; - } - else { - // add cost of cell to total PR cost - pCell = pLand->findCell(x4,y4); - if (pCell == 0) { // no-data cell + //out<<"pre swap: xmin = "< land.maxX) x4 = x + x3 - land.maxX - 1; else x4 = x + x3; } + if ((y + y3) < 0) y4 = y + y3 + land.maxY + 1; + else { if ((y + y3) > land.maxY) y4 = y + y3 - land.maxY - 1; else y4 = y + y3; } + // if (write_out && (x4 < 0 || y4 < 0)) { + // out<<"ERROR: x "< land.maxX || y4 < 0 || y4 > land.maxY) { + // unexpected problem - e.g. due to ridiculously large PR + // treat as a no-data cell cost = nodatacost; } else { - cost = pCell->getCost(); - if (cost < 0) cost = nodatacost; + // add cost of cell to total PR cost + pCell = pLand->findCell(x4, y4); + if (pCell == 0) { // no-data cell + cost = nodatacost; + } else { - if (cost == 0) { // cost not yet set for the cell - h = pCell->getHabIndex(landIx); - cost = pSpecies->getHabCost(h); + cost = pCell->getCost(); + if (cost < 0) cost = nodatacost; + else { + if (cost == 0) { // cost not yet set for the cell + h = pCell->getHabIndex(landIx); + cost = pSpecies->getHabCost(h); #if RSDEBUG -//DEBUGLOG << "Individual::getHabMatrix(): x4=" << x4 << " y4=" << y4 -// << " landIx=" << landIx << " h=" << h << " cost=" << cost -// << endl; + //DEBUGLOG << "Individual::getHabMatrix(): x4=" << x4 << " y4=" << y4 + // << " landIx=" << landIx << " h=" << h << " cost=" << cost + // << endl; #endif - pCell->setCost(cost); - } - else { + pCell->setCost(cost); + } + else { #if RSDEBUG -//DEBUGLOG << "Individual::getHabMatrix(): x4=" << x4 << " y4=" << y4 -// << " cost=" << cost -// << endl; + //DEBUGLOG << "Individual::getHabMatrix(): x4=" << x4 << " y4=" << y4 + // << " cost=" << cost + // << endl; #endif - } + } + } } } + if (prmethod == 1) { // arithmetic mean + w.cell[x2 + 1][y2 + 1] += cost; + ncells++; + } + if (prmethod == 2) { // harmonic mean + if (cost > 0) { + w.cell[x2 + 1][y2 + 1] += (1.0f / (float)cost); + ncells++; + } + } + if (prmethod == 3) { // arithmetic mean weighted by inverse distance + if (cost > 0) { + // NB distance is still given by (x3,y3) + weight = 1.0f / (double)sqrt((pow((double)x3, 2) + pow((double)y3, 2))); + w.cell[x2 + 1][y2 + 1] += (float)(weight * (double)cost); + ncells++; sumweights += weight; + } + } + // if (write_out2) out2<get_target() > 50) targetseen++; + // } + //#endif + } //end of y3 loop + } //end of x3 loop + // if (write_out) out<<"ncells in PR = "<get_target() > 50) targetseen++; -// } -//#endif - } //end of y3 loop - } //end of x3 loop -// if (write_out) out<<"ncells in PR = "<total << "\t" << loc.x << "\t" << loc.y << "\t" - << status << "\t" - << endl; + << path->total << "\t" << loc.x << "\t" << loc.y << "\t" + << status << "\t" + << endl; } // if not anymore dispersing... - if(status > 1 && status < 10){ + if (status > 1 && status < 10) { prev_loc = pPrevCell->getLocn(); // record only if this is the first step as non-disperser if (path->pathoutput) { // if this is also the first step taken at all, record the start cell first - if(path->total == 1){ + if (path->total == 1) { outMovePaths << year << "\t" << indId << "\t" - << "0\t" << prev_loc.x << "\t" << prev_loc.y << "\t" - << "0\t" // status at start cell is 0 - << endl; + << "0\t" << prev_loc.x << "\t" << prev_loc.y << "\t" + << "0\t" // status at start cell is 0 + << endl; } outMovePaths << year << "\t" << indId << "\t" - << path->total << "\t" << loc.x << "\t" << loc.y << "\t" - << status << "\t" - << endl; + << path->total << "\t" << loc.x << "\t" << loc.y << "\t" + << status << "\t" + << endl; // current cell will be invalid (zero), so set back to previous cell //pPrevCell = pCurrCell; path->pathoutput = 0; @@ -2422,29 +2419,29 @@ void Individual::outMovePath(const int year) //--------------------------------------------------------------------------- -double wrpcauchy (double location, double rho) { -double result; - -if(rho < 0.0 || rho > 1.0) { -// ML_ERR_return_NAN; - result = location; -} +double wrpcauchy(double location, double rho) { + double result; -if(rho == 0) - result = pRandom->Random() * M_2PI; -else - if(rho == 1) result = location; - else { - result = fmod(cauchy(location, -log(rho)), M_2PI); + if (rho < 0.0 || rho > 1.0) { + // ML_ERR_return_NAN; + result = location; } -return result; + + if (rho == 0) + result = pRandom->Random() * M_2PI; + else + if (rho == 1) result = location; + else { + result = fmod(cauchy(location, -log(rho)), M_2PI); + } + return result; } double cauchy(double location, double scale) { -if (scale < 0) return location; -//return location + scale * tan(M_PI * unif_rand()); -return location + scale * tan(PI * pRandom->Random()); -//return location + scale * tan(M_PI * pRandom->Random()); + if (scale < 0) return location; + //return location + scale * tan(M_PI * unif_rand()); + return location + scale * tan(PI * pRandom->Random()); + //return location + scale * tan(M_PI * pRandom->Random()); } //#endif //#endif diff --git a/Individual.h b/Individual.h index d843d7e..fc9c4cf 100644 --- a/Individual.h +++ b/Individual.h @@ -1,45 +1,45 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ -RangeShifter v2.0 Individual -Implements the Individual class + /*------------------------------------------------------------------------------ -Various optional attributes (genes for traits, movement parameters, etc.) are -allocated dynamically and accessed by pointers if required. + RangeShifter v2.0 Individual -For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. -and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. -Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 + Implements the Individual class -Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + Various optional attributes (genes for traits, movement parameters, etc.) are + allocated dynamically and accessed by pointers if required. -Last updated: 26 October 2021 by Steve Palmer + For full details of RangeShifter, please see: + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. + and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial + eco-evolutionary dynamics and species’ responses to environmental changes. + Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 -------------------------------------------------------------------------------*/ + Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + + Last updated: 26 October 2021 by Steve Palmer + + ------------------------------------------------------------------------------*/ #ifndef IndividualH #define IndividualH @@ -71,8 +71,8 @@ struct pathData { // to hold path data common to SMS and CRW models int year, total, out; // nos. of steps Patch* pSettPatch; // pointer to most recent patch tested for settlement short settleStatus; // whether ind may settle in current patch - // 0 = not set, 1 = debarred through density dependence rule - // 2 = OK to settle subject to finding a mate + // 0 = not set, 1 = debarred through density dependence rule + // 2 = OK to settle subject to finding a mate // bool leftNatalPatch; // individual has moved out of its natal patch #if RS_RCPP short pathoutput; @@ -86,7 +86,7 @@ struct settlePatch { }; struct crwParams { // to hold data for CRW movement model float prevdrn; // direction of previous step (UNITS) - float xc,yc; // continuous cell co-ordinates + float xc, yc; // continuous cell co-ordinates float stepL; // phenotypic step length (m) float rho; // phenotypic step correlation coefficient }; @@ -210,7 +210,7 @@ class Individual { const bool // absorbing boundaries? ); void drawMove( // Visualise paths resulting from movement simulation model - // NULL for the batch version + // NULL for the batch version const float, // initial x co-ordinate const float, // initial y co-ordinate const float, // final x co-ordinate @@ -268,42 +268,42 @@ class Individual { short sex; short age; short status; // 0 = initial status in natal patch / philopatric recruit - // 1 = disperser - // 2 = disperser awaiting settlement in possible suitable patch - // 3 = waiting between dispersal events - // 4 = completed settlement - // 5 = completed settlement in a suitable neighbouring cell - // 6 = died during transfer by failing to find a suitable patch - // (includes exceeding maximum number of steps or crossing - // absorbing boundary) - // 7 = died during transfer by constant, step-dependent, - // habitat-dependent or distance-dependent mortality - // 8 = failed to survive annual (demographic) mortality - // 9 = exceeded maximum age + // 1 = disperser + // 2 = disperser awaiting settlement in possible suitable patch + // 3 = waiting between dispersal events + // 4 = completed settlement + // 5 = completed settlement in a suitable neighbouring cell + // 6 = died during transfer by failing to find a suitable patch + // (includes exceeding maximum number of steps or crossing + // absorbing boundary) + // 7 = died during transfer by constant, step-dependent, + // habitat-dependent or distance-dependent mortality + // 8 = failed to survive annual (demographic) mortality + // 9 = exceeded maximum age short fallow; // reproductive seasons since last reproduction bool isDeveloping; - Cell *pPrevCell; // pointer to previous Cell - Cell *pCurrCell; // pointer to current Cell - Patch *pNatalPatch; // pointer to natal Patch - emigTraits *emigtraits; // pointer to emigration traits - trfrKernTraits *kerntraits; // pointers to transfer by kernel traits - pathData *path; // pointer to path data for movement model - crwParams *crw; // pointer to CRW traits and data - smsdata *smsData; // pointer to variables required for SMS - settleTraits *setttraits; // pointer to settlement traits + Cell* pPrevCell; // pointer to previous Cell + Cell* pCurrCell; // pointer to current Cell + Patch* pNatalPatch; // pointer to natal Patch + emigTraits* emigtraits; // pointer to emigration traits + trfrKernTraits* kerntraits; // pointers to transfer by kernel traits + pathData* path; // pointer to path data for movement model + crwParams* crw; // pointer to CRW traits and data + smsdata* smsData; // pointer to variables required for SMS + settleTraits* setttraits; // pointer to settlement traits std::queue memory; // memory of last N squares visited for SMS - Genome *pGenome; + Genome* pGenome; }; //--------------------------------------------------------------------------- -double cauchy(double location, double scale) ; -double wrpcauchy (double location, double rho = exp(double(-1))); +double cauchy(double location, double scale); +double wrpcauchy(double location, double rho = exp(double(-1))); -extern RSrandom *pRandom; +extern RSrandom* pRandom; #if RSDEBUG extern ofstream DEBUGLOG; diff --git a/Landscape.cpp b/Landscape.cpp index f663cb2..efa88a4 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Landscape.h" //--------------------------------------------------------------------------- @@ -37,119 +37,119 @@ ofstream outMovePaths; // Initial species distribution functions -InitDist::InitDist(Species *pSp) +InitDist::InitDist(Species* pSp) { -pSpecies = pSp; -resol = 0; -maxX = 0; -maxY = 0; -minEast = 0.0; -minNorth = 0.0; + pSpecies = pSp; + resol = 0; + maxX = 0; + maxY = 0; + minEast = 0.0; + minNorth = 0.0; } InitDist::~InitDist() { -int ncells = (int)cells.size(); -for (int i = 0; i < ncells; i++) - if (cells[i] != NULL) delete cells[i]; -cells.clear(); + int ncells = (int)cells.size(); + for (int i = 0; i < ncells; i++) + if (cells[i] != NULL) delete cells[i]; + cells.clear(); } void InitDist::setDistribution(int nInit) { -int rr = 0; -int ncells = (int)cells.size(); -if (nInit == 0) { // set all cells to be initialised - for (int i = 0; i < ncells; i++) { - cells[i]->setCell(true); - } -} -else { // set specified number of cells at random to be initialised - if (nInit > ncells/2) { // use backwards selection method - for (int i = 0; i < ncells; i++) cells[i]->setCell(true); - for (int i = 0; i < (ncells-nInit); i++) { - do { - rr = pRandom->IRandom(0,ncells-1); - } while (!cells[rr]->selected()); - cells[rr]->setCell(false); + int rr = 0; + int ncells = (int)cells.size(); + if (nInit == 0) { // set all cells to be initialised + for (int i = 0; i < ncells; i++) { + cells[i]->setCell(true); } } - else { // use forwards selection method - for (int i = 0; i < ncells; i++) cells[i]->setCell(false); - for (int i = 0; i < nInit; i++) { - do { - rr = pRandom->IRandom(0,ncells-1); - } while (cells[rr]->selected()); - cells[rr]->setCell(true); + else { // set specified number of cells at random to be initialised + if (nInit > ncells / 2) { // use backwards selection method + for (int i = 0; i < ncells; i++) cells[i]->setCell(true); + for (int i = 0; i < (ncells - nInit); i++) { + do { + rr = pRandom->IRandom(0, ncells - 1); + } while (!cells[rr]->selected()); + cells[rr]->setCell(false); + } + } + else { // use forwards selection method + for (int i = 0; i < ncells; i++) cells[i]->setCell(false); + for (int i = 0; i < nInit; i++) { + do { + rr = pRandom->IRandom(0, ncells - 1); + } while (cells[rr]->selected()); + cells[rr]->setCell(true); + } } } } -} // Set a specified cell (by position in cells vector) -void InitDist::setDistCell(int ix,bool init) { -cells[ix]->setCell(init); +void InitDist::setDistCell(int ix, bool init) { + cells[ix]->setCell(init); } // Set a specified cell (by co-ordinates) -void InitDist::setDistCell(locn loc,bool init) { -locn cellloc; -int ncells = (int)cells.size(); -for (int i = 0; i < ncells; i++) { - cellloc = cells[i]->getLocn(); - if (cellloc.x == loc.x && cellloc.y == loc.y) { - cells[i]->setCell(init); - i = ncells; +void InitDist::setDistCell(locn loc, bool init) { + locn cellloc; + int ncells = (int)cells.size(); + for (int i = 0; i < ncells; i++) { + cellloc = cells[i]->getLocn(); + if (cellloc.x == loc.x && cellloc.y == loc.y) { + cells[i]->setCell(init); + i = ncells; + } } } -} // Specified location is within the initial distribution? bool InitDist::inInitialDist(locn loc) { -int ncells = (int)cells.size(); -for (int i = 0; i < ncells; i++) { - if (cells[i]->toInitialise(loc)) { // cell is to be initialised - return true; + int ncells = (int)cells.size(); + for (int i = 0; i < ncells; i++) { + if (cells[i]->toInitialise(loc)) { // cell is to be initialised + return true; + } } -} -return false; + return false; } int InitDist::cellCount(void) { -return (int)cells.size(); + return (int)cells.size(); } // Return the co-ordinates of a specified initial distribution cell locn InitDist::getCell(int ix) { -locn loc; -if (ix >= 0 && ix < (int)cells.size()) { - loc = cells[ix]->getLocn(); -} -else { - loc.x = loc.y = -666; // indicates invalid index specified -} -return loc; + locn loc; + if (ix >= 0 && ix < (int)cells.size()) { + loc = cells[ix]->getLocn(); + } + else { + loc.x = loc.y = -666; // indicates invalid index specified + } + return loc; } // Return the co-ordinates of a specified initial distribution cell if it has been // selected - otherwise return negative co-ordinates locn InitDist::getSelectedCell(int ix) { -locn loc; loc.x = loc.y = -666; -if (ix < (int)cells.size()) { - if (cells[ix]->selected()) { - loc = cells[ix]->getLocn(); + locn loc; loc.x = loc.y = -666; + if (ix < (int)cells.size()) { + if (cells[ix]->selected()) { + loc = cells[ix]->getLocn(); + } } -} -return loc; + return loc; } locn InitDist::getDimensions(void) { -locn d; d.x = maxX; d.y = maxY; return d; + locn d; d.x = maxX; d.y = maxY; return d; } void InitDist::resetDistribution(void) { -int ncells = (int)cells.size(); -for (int i = 0; i < ncells; i++) { - cells[i]->setCell(false); -} + int ncells = (int)cells.size(); + for (int i = 0; i < ncells; i++) { + cells[i]->setCell(false); + } } //--------------------------------------------------------------------------- @@ -158,66 +158,66 @@ for (int i = 0; i < ncells; i++) { int InitDist::readDistribution(string distfile) { #if RS_RCPP -wstring header; + wstring header; #else -string header; + string header; #endif -int p,nodata; -int ncols,nrows; + int p, nodata; + int ncols, nrows; #if RS_RCPP -wifstream dfile; // species distribution file input stream + wifstream dfile; // species distribution file input stream #else -ifstream dfile; // species distribution file input stream + ifstream dfile; // species distribution file input stream #endif -// open distribution file + // open distribution file #if !RS_RCPP || RSWIN64 dfile.open(distfile.c_str()); #else dfile.open(distfile, std::ios::binary); - if(spdistraster.utf) { + if (spdistraster.utf) { // apply BOM-sensitive UTF-16 facet dfile.imbue(std::locale(dfile.getloc(), new std::codecvt_utf16)); } #endif -if (!dfile.is_open()) return 21; + if (!dfile.is_open()) return 21; -// read landscape data from header records of distribution file -// NB headers of all files have already been compared -double tmpresol; -dfile >> header >> ncols >> header >> nrows >> header >> minEast >> header >> minNorth - >> header >> tmpresol >> header >> nodata; -resol = (int) tmpresol; + // read landscape data from header records of distribution file + // NB headers of all files have already been compared + double tmpresol; + dfile >> header >> ncols >> header >> nrows >> header >> minEast >> header >> minNorth + >> header >> tmpresol >> header >> nodata; + resol = (int)tmpresol; #if RS_RCPP -if (!dfile.good()) { - // corrupt file stream - StreamErrorR(distfile); - dfile.close(); - dfile.clear(); - return 144; -} + if (!dfile.good()) { + // corrupt file stream + StreamErrorR(distfile); + dfile.close(); + dfile.clear(); + return 144; + } #endif -maxX = ncols-1; maxY = nrows-1; + maxX = ncols - 1; maxY = nrows - 1; -// set up bad integer value to ensure that valid values are read -int badvalue = -9; if (nodata == -9) badvalue = -99; + // set up bad integer value to ensure that valid values are read + int badvalue = -9; if (nodata == -9) badvalue = -99; -for (int y = nrows-1; y >= 0; y--) { - for (int x = 0; x < ncols; x++) { - p = badvalue; + for (int y = nrows - 1; y >= 0; y--) { + for (int x = 0; x < ncols; x++) { + p = badvalue; #if RS_RCPP - if(dfile >> p) { + if (dfile >> p) { #else - dfile >> p; + dfile >> p; #endif #if RSDEBUG -//DEBUGLOG << "InitDist::readDistribution():" -// << " y = " << y << " x = " << x << " p = " << p << endl; + //DEBUGLOG << "InitDist::readDistribution():" + // << " y = " << y << " x = " << x << " p = " << p << endl; #endif if (p == nodata || p == 0 || p == 1) { // only valid values if (p == 1) { // species present - cells.push_back(new DistCell(x,y)); + cells.push_back(new DistCell(x, y)); } } else { // error in file @@ -225,22 +225,23 @@ for (int y = nrows-1; y >= 0; y--) { return 22; } #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR(distfile); - dfile.close(); - dfile.clear(); - return 144; - } + } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif + StreamErrorR(distfile); + dfile.close(); + dfile.clear(); + return 144; + } +#endif + } } -} #if RS_RCPP - dfile >> p; - if (!dfile.eof()) EOFerrorR(distfile); +dfile >> p; +if (!dfile.eof()) EOFerrorR(distfile); #endif dfile.close(); dfile.clear(); @@ -253,34 +254,34 @@ return 0; // Landscape functions Landscape::Landscape(void) { -patchModel = false; spDist = false; generated = false; fractal = false; continuous = false; -dynamic = false; habIndexed = false; -resol = spResol = landNum = 0; -rasterType = 0; -nHab = nHabMax = 0; -dimX = dimY = 100; -minX = minY = 0; -maxX = maxY = 99; -minPct = maxPct = propSuit = hurst = 0.0; -maxCells = 100; -gpix = 1.0; -pix = (int)gpix; -minEast = minNorth = 0.0; -cells = 0; -#if RSDEBUG -// NOTE: do NOT write to output stream before it has been opened - it will be empty -//DebugGUI("Landscape::Landscape(): this = " + Int2Str((int)this) -// + " pCell = " + Int2Str((int)pCell)); -//DEBUGLOGGUI << "Landscape::Landscape(): this = " << this << " pCell = " << pCell << endl; -#endif -connectMatrix = 0; -epsGlobal = 0; -patchChgMatrix = 0; -costsChgMatrix = 0; - -#if RSDEBUG -//DEBUGLOG << "Landscape::Landscape():" -// << " rasterType= " << rasterType << endl; + patchModel = false; spDist = false; generated = false; fractal = false; continuous = false; + dynamic = false; habIndexed = false; + resol = spResol = landNum = 0; + rasterType = 0; + nHab = nHabMax = 0; + dimX = dimY = 100; + minX = minY = 0; + maxX = maxY = 99; + minPct = maxPct = propSuit = hurst = 0.0; + maxCells = 100; + gpix = 1.0; + pix = (int)gpix; + minEast = minNorth = 0.0; + cells = 0; +#if RSDEBUG + // NOTE: do NOT write to output stream before it has been opened - it will be empty + //DebugGUI("Landscape::Landscape(): this = " + Int2Str((int)this) + // + " pCell = " + Int2Str((int)pCell)); + //DEBUGLOGGUI << "Landscape::Landscape(): this = " << this << " pCell = " << pCell << endl; +#endif + connectMatrix = 0; + epsGlobal = 0; + patchChgMatrix = 0; + costsChgMatrix = 0; + +#if RSDEBUG + //DEBUGLOG << "Landscape::Landscape():" + // << " rasterType= " << rasterType << endl; #endif #if RSDEBUG //MemoLine(("Landscape::Landscape(): landscape created " + Int2Str(0) @@ -291,65 +292,65 @@ costsChgMatrix = 0; Landscape::~Landscape() { #if RSDEBUG -//DebugGUI(("Landscape::~Landscape(): this=" + Int2Str((int)this) + " cells=" + Int2Str((int)cells) -// + " maxX=" + Int2Str(maxX) + " maxY=" + Int2Str(maxY)).c_str()); + //DebugGUI(("Landscape::~Landscape(): this=" + Int2Str((int)this) + " cells=" + Int2Str((int)cells) + // + " maxX=" + Int2Str(maxX) + " maxY=" + Int2Str(maxY)).c_str()); #endif -if (cells != 0) { - for (int y = dimY-1; y >= 0; y--) { + if (cells != 0) { + for (int y = dimY - 1; y >= 0; y--) { #if RSDEBUG -//DebugGUI(("Landscape::~Landscape(): y=" + Int2Str(y) + " cells[y]=" + Int2Str((int)cells[y])).c_str()); + //DebugGUI(("Landscape::~Landscape(): y=" + Int2Str(y) + " cells[y]=" + Int2Str((int)cells[y])).c_str()); #endif - for (int x = 0; x < dimX; x++) { + for (int x = 0; x < dimX; x++) { #if RSDEBUG -//DebugGUI(("Landscape::~Landscape(): y=" + Int2Str(y) + " x=" + Int2Str(x) -// + " cells[y][x]=" + Int2Str((int)cells[y][x])).c_str()); + //DebugGUI(("Landscape::~Landscape(): y=" + Int2Str(y) + " x=" + Int2Str(x) + // + " cells[y][x]=" + Int2Str((int)cells[y][x])).c_str()); #endif - if (cells[y][x] != 0) delete cells[y][x]; - } - if (cells[y] != 0) { + if (cells[y][x] != 0) delete cells[y][x]; + } + if (cells[y] != 0) { #if RSDEBUG -//DebugGUI(("Landscape::~Landscape(): deleting cells[y]=" + Int2Str((int)cells[y])).c_str()); + //DebugGUI(("Landscape::~Landscape(): deleting cells[y]=" + Int2Str((int)cells[y])).c_str()); #endif // delete cells[y]; - delete[] cells[y]; + delete[] cells[y]; + } } + delete[] cells; + cells = 0; } - delete[] cells; - cells = 0; -} #if RSDEBUG -//DebugGUI(("Landscape::~Landscape(): this=" + Int2Str((int)this) -// + " cells=" + Int2Str((int)cells)).c_str()); + //DebugGUI(("Landscape::~Landscape(): this=" + Int2Str((int)this) + // + " cells=" + Int2Str((int)cells)).c_str()); #endif -int npatches = (int)patches.size(); -for (int i = 0; i < npatches; i++) - if (patches[i] != NULL) delete patches[i]; -patches.clear(); + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) + if (patches[i] != NULL) delete patches[i]; + patches.clear(); -int ndistns = (int)distns.size(); -for (int i = 0; i < ndistns; i++) - if (distns[i] != NULL) delete distns[i]; -distns.clear(); + int ndistns = (int)distns.size(); + for (int i = 0; i < ndistns; i++) + if (distns[i] != NULL) delete distns[i]; + distns.clear(); -int ninitcells = (int)initcells.size(); -for (int i = 0; i < ninitcells; i++) - if (initcells[i] != NULL) delete initcells[i]; -initcells.clear(); + int ninitcells = (int)initcells.size(); + for (int i = 0; i < ninitcells; i++) + if (initcells[i] != NULL) delete initcells[i]; + initcells.clear(); -patchnums.clear(); -habCodes.clear(); -colours.clear(); -landchanges.clear(); -patchchanges.clear(); + patchnums.clear(); + habCodes.clear(); + colours.clear(); + landchanges.clear(); + patchchanges.clear(); -deleteConnectMatrix(); -deletePatchChgMatrix(); -if (epsGlobal != 0) delete[] epsGlobal; + deleteConnectMatrix(); + deletePatchChgMatrix(); + if (epsGlobal != 0) delete[] epsGlobal; #if RSDEBUG -//MemoLine(("Landscape::~Landscape(): landscape deleted " + Int2Str(1) -// ).c_str()); + //MemoLine(("Landscape::~Landscape(): landscape deleted " + Int2Str(1) + // ).c_str()); #endif } @@ -358,163 +359,163 @@ if (epsGlobal != 0) delete[] epsGlobal; void Landscape::resetLand(void) { #if RSDEBUG -//DebugGUI("Landscape::resetLand(): starting..."); + //DebugGUI("Landscape::resetLand(): starting..."); #endif -resetLandLimits(); -int npatches = (int)patches.size(); + resetLandLimits(); + int npatches = (int)patches.size(); #if RSDEBUG -//DebugGUI(("Landscape::resetLand(): npatches=" + Int2Str(npatches) -// ).c_str()); + //DebugGUI(("Landscape::resetLand(): npatches=" + Int2Str(npatches) + // ).c_str()); #endif -for (int i = 0; i < npatches; i++) if (patches[i] != NULL) delete patches[i]; -patches.clear(); + for (int i = 0; i < npatches; i++) if (patches[i] != NULL) delete patches[i]; + patches.clear(); #if RSDEBUG -//DebugGUI("Landscape::resetLand(): finished resetting patches"); + //DebugGUI("Landscape::resetLand(): finished resetting patches"); #endif #if RSDEBUG //DebugGUI(("Landscape::resetLand(): this=" + Int2Str((int)this) // + " cells=" + Int2Str((int)cells)).c_str()); #endif -if (cells != 0) { - for(int y = dimY-1; y >= 0; y--){ + if (cells != 0) { + for (int y = dimY - 1; y >= 0; y--) { #if RSDEBUG -//DebugGUI(("Landscape::resetLand(): y=" + Int2Str(y) + " cells[y]=" + Int2Str((int)cells[y])).c_str()); + //DebugGUI(("Landscape::resetLand(): y=" + Int2Str(y) + " cells[y]=" + Int2Str((int)cells[y])).c_str()); #endif - for (int x = 0; x < dimX; x++) { + for (int x = 0; x < dimX; x++) { #if RSDEBUG -//DebugGUI(("Landscape::resetLand(): y=" + Int2Str(y) + " x=" + Int2Str(x) -// + " cells[y][x]=" + Int2Str((int)cells[y][x])).c_str()); + //DebugGUI(("Landscape::resetLand(): y=" + Int2Str(y) + " x=" + Int2Str(x) + // + " cells[y][x]=" + Int2Str((int)cells[y][x])).c_str()); #endif - if (cells[y][x] != 0) delete cells[y][x]; - } - if (cells[y] != 0) { + if (cells[y][x] != 0) delete cells[y][x]; + } + if (cells[y] != 0) { #if RSDEBUG -//DebugGUI(("Landscape::resetLand(): deleting cells[y]=" + Int2Str((int)cells[y])).c_str()); + //DebugGUI(("Landscape::resetLand(): deleting cells[y]=" + Int2Str((int)cells[y])).c_str()); #endif - delete[] cells[y]; + delete[] cells[y]; + } } + delete[] cells; + cells = 0; } - delete[] cells; - cells = 0; -} #if RSDEBUG -//DebugGUI(("Landscape::resetLand(): this=" + Int2Str((int)this) -// + " cells=" + Int2Str((int)cells)).c_str()); + //DebugGUI(("Landscape::resetLand(): this=" + Int2Str((int)this) + // + " cells=" + Int2Str((int)cells)).c_str()); #endif } -void Landscape::setLandParams(landParams ppp,bool batchMode) +void Landscape::setLandParams(landParams ppp, bool batchMode) { -generated = ppp.generated; patchModel = ppp.patchModel; spDist = ppp.spDist; -dynamic = ppp.dynamic; -landNum = ppp.landNum; -if (ppp.resol > 0) resol = ppp.resol; -if (ppp.spResol > 0 && ppp.spResol%ppp.resol == 0) spResol = ppp.spResol; -if ((ppp.rasterType >= 0 && ppp.rasterType <= 2) || ppp.rasterType == 9) - rasterType = ppp.rasterType; -if (ppp.nHab >= 1) nHab = ppp.nHab; -if (ppp.nHabMax >= 1) nHabMax = ppp.nHabMax; -if (ppp.dimX > 0) dimX = ppp.dimX; -if (ppp.dimY > 0) dimY = ppp.dimY; -if (ppp.minX >= 0 && ppp.maxX >= 0 && ppp.minX <= ppp.maxX && ppp.maxX < dimX) { - minX = ppp.minX; maxX = ppp.maxX; -} -else { - minX = 0; maxX = dimX - 1; -} -if (ppp.minY >= 0 && ppp.maxY >= 0 && ppp.minY <= ppp.maxY && ppp.maxY < dimY) { - minY = ppp.minY; maxY = ppp.maxY; -} -else { - minY = 0; maxY = dimY - 1; -} -if (batchMode && rasterType == 0) { - // in batch mode, set up sequential habitat codes if not already present - if (habCodes.size() == 0) { - for (int i = 0; i < nHabMax; i++) { - habCodes.push_back(i+1); + generated = ppp.generated; patchModel = ppp.patchModel; spDist = ppp.spDist; + dynamic = ppp.dynamic; + landNum = ppp.landNum; + if (ppp.resol > 0) resol = ppp.resol; + if (ppp.spResol > 0 && ppp.spResol % ppp.resol == 0) spResol = ppp.spResol; + if ((ppp.rasterType >= 0 && ppp.rasterType <= 2) || ppp.rasterType == 9) + rasterType = ppp.rasterType; + if (ppp.nHab >= 1) nHab = ppp.nHab; + if (ppp.nHabMax >= 1) nHabMax = ppp.nHabMax; + if (ppp.dimX > 0) dimX = ppp.dimX; + if (ppp.dimY > 0) dimY = ppp.dimY; + if (ppp.minX >= 0 && ppp.maxX >= 0 && ppp.minX <= ppp.maxX && ppp.maxX < dimX) { + minX = ppp.minX; maxX = ppp.maxX; + } + else { + minX = 0; maxX = dimX - 1; + } + if (ppp.minY >= 0 && ppp.maxY >= 0 && ppp.minY <= ppp.maxY && ppp.maxY < dimY) { + minY = ppp.minY; maxY = ppp.maxY; + } + else { + minY = 0; maxY = dimY - 1; + } + if (batchMode && rasterType == 0) { + // in batch mode, set up sequential habitat codes if not already present + if (habCodes.size() == 0) { + for (int i = 0; i < nHabMax; i++) { + habCodes.push_back(i + 1); + } } } } -} landParams Landscape::getLandParams(void) { -landParams ppp; -ppp.generated = generated; ppp.patchModel = patchModel; ppp.spDist = spDist; -ppp.dynamic = dynamic; -ppp.landNum = landNum; -ppp.resol = resol; ppp.spResol = spResol; -ppp.rasterType = rasterType; -ppp.nHab = nHab; ppp.nHabMax = nHabMax; -ppp.dimX = dimX; ppp.dimY = dimY; -ppp.minX = minX; ppp.minY = minY; -ppp.maxX = maxX; ppp.maxY = maxY; -return ppp; + landParams ppp; + ppp.generated = generated; ppp.patchModel = patchModel; ppp.spDist = spDist; + ppp.dynamic = dynamic; + ppp.landNum = landNum; + ppp.resol = resol; ppp.spResol = spResol; + ppp.rasterType = rasterType; + ppp.nHab = nHab; ppp.nHabMax = nHabMax; + ppp.dimX = dimX; ppp.dimY = dimY; + ppp.minX = minX; ppp.minY = minY; + ppp.maxX = maxX; ppp.maxY = maxY; + return ppp; } landData Landscape::getLandData(void) { -landData dd; -dd.resol = resol; -dd.dimX = dimX; dd.dimY = dimY; -dd.minX = minX; dd.minY = minY; -dd.maxX = maxX; dd.maxY = maxY; -return dd; + landData dd; + dd.resol = resol; + dd.dimX = dimX; dd.dimY = dimY; + dd.minX = minX; dd.minY = minY; + dd.maxX = maxX; dd.maxY = maxY; + return dd; } void Landscape::setGenLandParams(genLandParams ppp) { -fractal = ppp.fractal; -continuous = ppp.continuous; -if (ppp.minPct > 0.0 && ppp.minPct < 100.0) minPct = ppp.minPct; -if (ppp.maxPct > 0.0 && ppp.maxPct <= 100.0) maxPct = ppp.maxPct; -if (ppp.propSuit >= 0.0 && ppp.propSuit <= 1.0) propSuit = ppp.propSuit; -if (ppp.hurst > 0.0 && ppp.hurst < 1.0) hurst = ppp.hurst; -if (ppp.maxCells > 0) maxCells = ppp.maxCells; + fractal = ppp.fractal; + continuous = ppp.continuous; + if (ppp.minPct > 0.0 && ppp.minPct < 100.0) minPct = ppp.minPct; + if (ppp.maxPct > 0.0 && ppp.maxPct <= 100.0) maxPct = ppp.maxPct; + if (ppp.propSuit >= 0.0 && ppp.propSuit <= 1.0) propSuit = ppp.propSuit; + if (ppp.hurst > 0.0 && ppp.hurst < 1.0) hurst = ppp.hurst; + if (ppp.maxCells > 0) maxCells = ppp.maxCells; } genLandParams Landscape::getGenLandParams(void) { -genLandParams ppp; -ppp.fractal = fractal; ppp.continuous = continuous; -ppp.minPct = minPct; ppp.maxPct = maxPct; ppp.propSuit = propSuit; ppp.hurst = hurst; -ppp.maxCells = maxCells; -return ppp; + genLandParams ppp; + ppp.fractal = fractal; ppp.continuous = continuous; + ppp.minPct = minPct; ppp.maxPct = maxPct; ppp.propSuit = propSuit; ppp.hurst = hurst; + ppp.maxCells = maxCells; + return ppp; } -void Landscape::setLandLimits(int x0,int y0,int x1,int y1) { -if (x0 >= 0 && x1 >= 0 && x0 <= x1 && x1 < dimX -&& y0 >= 0 && y1 >= 0 && y0 <= y1 && y1 < dimY) { - minX = x0; maxX = x1; minY = y0; maxY = y1; -} +void Landscape::setLandLimits(int x0, int y0, int x1, int y1) { + if (x0 >= 0 && x1 >= 0 && x0 <= x1 && x1 < dimX + && y0 >= 0 && y1 >= 0 && y0 <= y1 && y1 < dimY) { + minX = x0; maxX = x1; minY = y0; maxY = y1; + } } void Landscape::resetLandLimits(void) { -minX = minY = 0; maxX = dimX-1; maxY = dimY-1; + minX = minY = 0; maxX = dimX - 1; maxY = dimY - 1; } //--------------------------------------------------------------------------- void Landscape::setLandPix(landPix p) { -if (p.pix > 0) pix = p.pix; -if (p.gpix > 0.0) gpix = p.gpix; + if (p.pix > 0) pix = p.pix; + if (p.gpix > 0.0) gpix = p.gpix; } landPix Landscape::getLandPix(void) { -landPix p; -p.pix = pix; p.gpix = gpix; -return p; + landPix p; + p.pix = pix; p.gpix = gpix; + return p; } void Landscape::setOrigin(landOrigin origin) { -minEast = origin.minEast; minNorth = origin.minNorth; + minEast = origin.minEast; minNorth = origin.minNorth; } landOrigin Landscape::getOrigin(void) { -landOrigin origin; -origin.minEast = minEast; origin.minNorth = minNorth; -return origin; + landOrigin origin; + origin.minEast = minEast; origin.minNorth = minNorth; + return origin; } //--------------------------------------------------------------------------- @@ -524,110 +525,110 @@ return origin; bool Landscape::habitatsIndexed(void) { return habIndexed; } void Landscape::listHabCodes(void) { -int nhab = (int)habCodes.size(); + int nhab = (int)habCodes.size(); #if RS_RCPP && !R_CMD -Rcpp::Rcout << endl; -for (int i = 0; i < nhab; i++) { - Rcpp::Rcout << "Habitat code[ " << i << "] = " << habCodes[i] << endl; -} -Rcpp::Rcout << endl; + Rcpp::Rcout << endl; + for (int i = 0; i < nhab; i++) { + Rcpp::Rcout << "Habitat code[ " << i << "] = " << habCodes[i] << endl; + } + Rcpp::Rcout << endl; #else -cout << endl; -for (int i = 0; i < nhab; i++) { - cout << "Habitat code[ " << i << "] = " << habCodes[i] << endl; -} -cout << endl; + cout << endl; + for (int i = 0; i < nhab; i++) { + cout << "Habitat code[ " << i << "] = " << habCodes[i] << endl; + } + cout << endl; #endif } void Landscape::addHabCode(int hab) { -int nhab = (int)habCodes.size(); -bool addCode = true; -for (int i = 0; i < nhab; i++) { - if (hab == habCodes[i]) { - addCode = false; i = nhab+1; + int nhab = (int)habCodes.size(); + bool addCode = true; + for (int i = 0; i < nhab; i++) { + if (hab == habCodes[i]) { + addCode = false; i = nhab + 1; + } } -} -if (addCode) { habCodes.push_back(hab); nHab++; } + if (addCode) { habCodes.push_back(hab); nHab++; } } // Get the index number of the specified habitat in the habitats vector int Landscape::findHabCode(int hab) { -int nhab = (int)habCodes.size(); -for (int i = 0; i < nhab; i++) { - if (hab == habCodes[i]) return i; -} -return -999; + int nhab = (int)habCodes.size(); + for (int i = 0; i < nhab; i++) { + if (hab == habCodes[i]) return i; + } + return -999; } // Get the specified habitat code int Landscape::getHabCode(int ixhab) { -if (ixhab < (int)habCodes.size()) return habCodes[ixhab]; -else return -999; + if (ixhab < (int)habCodes.size()) return habCodes[ixhab]; + else return -999; } void Landscape::clearHabitats(void) { -habCodes.clear(); -colours.clear(); + habCodes.clear(); + colours.clear(); } void Landscape::addColour(rgb c) { -colours.push_back(c); + colours.push_back(c); } -void Landscape::changeColour(int i,rgb col) { -int ncolours = (int)colours.size(); -if (i >= 0 && i < ncolours) { - if (col.r >=0 && col.r <= 255 && col.g >=0 && col.g <= 255 && col.b >=0 && col.b <= 255) - colours[i] = col; -} +void Landscape::changeColour(int i, rgb col) { + int ncolours = (int)colours.size(); + if (i >= 0 && i < ncolours) { + if (col.r >= 0 && col.r <= 255 && col.g >= 0 && col.g <= 255 && col.b >= 0 && col.b <= 255) + colours[i] = col; + } } rgb Landscape::getColour(int ix) { -return colours[ix]; + return colours[ix]; } int Landscape::colourCount(void) { -return (int)colours.size(); + return (int)colours.size(); } //--------------------------------------------------------------------------- void Landscape::setCellArray(void) { #if RSDEBUG -//DebugGUI(("Landscape::setCellArray(): start: this=" + Int2Str((int)this) -// + " cells=" + Int2Str((int)cells)).c_str()); + //DebugGUI(("Landscape::setCellArray(): start: this=" + Int2Str((int)this) + // + " cells=" + Int2Str((int)cells)).c_str()); #endif -if (cells != 0) resetLand(); -//cells = new Cell **[maxY+1]; -cells = new Cell **[dimY]; + if (cells != 0) resetLand(); + //cells = new Cell **[maxY+1]; + cells = new Cell * *[dimY]; #if RSDEBUG -//DebugGUI(("Landscape::setCellArray(): cells=" + Int2Str((int)cells)).c_str()); + //DebugGUI(("Landscape::setCellArray(): cells=" + Int2Str((int)cells)).c_str()); #endif -for (int y = dimY-1; y >= 0; y--) { - cells[y] = new Cell *[dimX]; + for (int y = dimY - 1; y >= 0; y--) { + cells[y] = new Cell * [dimX]; #if RSDEBUG -//DebugGUI(("Landscape::setCellArray(): y=" + Int2Str(y) -// + " cells[y]=" + Int2Str((int)cells[y])).c_str()); + //DebugGUI(("Landscape::setCellArray(): y=" + Int2Str(y) + // + " cells[y]=" + Int2Str((int)cells[y])).c_str()); #endif - for (int x = 0; x < dimX; x++) { - cells[y][x] = 0; + for (int x = 0; x < dimX; x++) { + cells[y][x] = 0; + } } -} #if RSDEBUG -//DebugGUI(("Landscape::setCellArray(): end: this=" + Int2Str((int)this) -// + " cells=" + Int2Str((int)cells)).c_str()); + //DebugGUI(("Landscape::setCellArray(): end: this=" + Int2Str((int)this) + // + " cells=" + Int2Str((int)cells)).c_str()); #endif } void Landscape::addPatchNum(int p) { -int npatches = (int)patchnums.size(); -bool addpatch = true; -for (int i = 0; i < npatches; i++) { - if (p == patchnums[i]) { - addpatch = false; i = npatches+1; + int npatches = (int)patchnums.size(); + bool addpatch = true; + for (int i = 0; i < npatches; i++) { + if (p == patchnums[i]) { + addpatch = false; i = npatches + 1; + } } -} -if (addpatch) patchnums.push_back(p); + if (addpatch) patchnums.push_back(p); } @@ -637,143 +638,143 @@ either binary (habitat index 0 is the matrix, 1 is suitable habitat) or continuous (0 is the matrix, >0 is suitable habitat) */ void Landscape::generatePatches(void) { -int x,y,ncells; -double p; -Patch *pPatch; -Cell *pCell; + int x, y, ncells; + double p; + Patch* pPatch; + Cell* pCell; -vector ArtLandscape; + vector ArtLandscape; #if RSDEBUG -//int iiiiii = (int)fractal; -//DEBUGLOG << "Landscape::generatePatches(): (int)fractal=" << iiiiii -// << " rasterType=" << rasterType -// << " continuous=" << continuous -// << " dimX=" << dimX << " dimY=" << dimY -// << " propSuit=" << propSuit -// << " hurst=" << hurst -// << " maxPct=" << maxPct << " minPct=" << minPct -// << endl; + //int iiiiii = (int)fractal; + //DEBUGLOG << "Landscape::generatePatches(): (int)fractal=" << iiiiii + // << " rasterType=" << rasterType + // << " continuous=" << continuous + // << " dimX=" << dimX << " dimY=" << dimY + // << " propSuit=" << propSuit + // << " hurst=" << hurst + // << " maxPct=" << maxPct << " minPct=" << minPct + // << endl; #endif -setCellArray(); + setCellArray(); -int patchnum = 0; // initial patch number for cell-based landscape -// create patch 0 - the matrix patch (even if there is no matrix) -newPatch(patchnum++); + int patchnum = 0; // initial patch number for cell-based landscape + // create patch 0 - the matrix patch (even if there is no matrix) + newPatch(patchnum++); -// as landscape generator returns cells in a random sequence, first set up all cells -// in the landscape in the correct sequence, then update them and create patches for -// habitat cells -for (int yy = dimY-1; yy >= 0; yy--) { - for (int xx = 0; xx < dimX; xx++) { + // as landscape generator returns cells in a random sequence, first set up all cells + // in the landscape in the correct sequence, then update them and create patches for + // habitat cells + for (int yy = dimY - 1; yy >= 0; yy--) { + for (int xx = 0; xx < dimX; xx++) { #if RSDEBUG -//DEBUGLOG << "Landscape::generatePatches(): yy=" << yy << " xx=" << xx << endl; + //DEBUGLOG << "Landscape::generatePatches(): yy=" << yy << " xx=" << xx << endl; #endif - addNewCellToLand(xx,yy,0); + addNewCellToLand(xx, yy, 0); + } } -} -if (continuous) rasterType = 2; -else rasterType = 0; -if (fractal) { - p = 1.0 - propSuit; - // fractal_landscape() requires Max_prop > 1 (but does not check it!) - // as in turn it calls runif(1.0,Max_prop) - double maxpct; - if (maxPct < 1.0) maxpct = 100.0; else maxpct = maxPct; + if (continuous) rasterType = 2; + else rasterType = 0; + if (fractal) { + p = 1.0 - propSuit; + // fractal_landscape() requires Max_prop > 1 (but does not check it!) + // as in turn it calls runif(1.0,Max_prop) + double maxpct; + if (maxPct < 1.0) maxpct = 100.0; else maxpct = maxPct; - ArtLandscape = fractal_landscape(dimY,dimX,hurst,p,maxpct,minPct); + ArtLandscape = fractal_landscape(dimY, dimX, hurst, p, maxpct, minPct); - vector::iterator iter = ArtLandscape.begin(); - while (iter != ArtLandscape.end()) { - x = iter->y_coord; y = iter->x_coord; + vector::iterator iter = ArtLandscape.begin(); + while (iter != ArtLandscape.end()) { + x = iter->y_coord; y = iter->x_coord; #if RSDEBUG -//DEBUGLOG << "Landscape::generatePatches(): x=" << x << " y=" << y -// << " iter->avail=" << iter->avail -// << " iter->value=" << iter->value << endl; + //DEBUGLOG << "Landscape::generatePatches(): x=" << x << " y=" << y + // << " iter->avail=" << iter->avail + // << " iter->value=" << iter->value << endl; #endif - pCell = findCell(x,y); - if (continuous) { - if (iter->value > 0.0) { // habitat - pPatch = newPatch(patchnum++); - addCellToPatch(pCell,pPatch,iter->value); - } - else { // matrix - addCellToPatch(pCell,patches[0],iter->value); - } - } - else { // discrete - if (iter->avail == 0) { // matrix - addCellToPatch(pCell,patches[0]); + pCell = findCell(x, y); + if (continuous) { + if (iter->value > 0.0) { // habitat + pPatch = newPatch(patchnum++); + addCellToPatch(pCell, pPatch, iter->value); + } + else { // matrix + addCellToPatch(pCell, patches[0], iter->value); + } } - else { // habitat - pPatch = newPatch(patchnum++); - addCellToPatch(pCell,pPatch); - pCell->changeHabIndex(0,1); + else { // discrete + if (iter->avail == 0) { // matrix + addCellToPatch(pCell, patches[0]); + } + else { // habitat + pPatch = newPatch(patchnum++); + addCellToPatch(pCell, pPatch); + pCell->changeHabIndex(0, 1); + } } + iter++; } - iter++; } -} -else { // random landscape - int hab = 0; - ncells = (int)((float)(dimX) * (float)(dimY) * propSuit + 0.00001); // no. of cells to initialise + else { // random landscape + int hab = 0; + ncells = (int)((float)(dimX) * (float)(dimY)*propSuit + 0.00001); // no. of cells to initialise #if RSDEBUG -//DEBUGLOG << "Landscape::generatePatches(): dimX=" << dimX << " dimY=" << dimY -// << " propSuit=" << propSuit -// << " PRODUCT=" << ((float)(dimX) * (float)(dimY) * propSuit + 0.00001) -// << " ncells=" << ncells << endl; + //DEBUGLOG << "Landscape::generatePatches(): dimX=" << dimX << " dimY=" << dimY + // << " propSuit=" << propSuit + // << " PRODUCT=" << ((float)(dimX) * (float)(dimY) * propSuit + 0.00001) + // << " ncells=" << ncells << endl; #endif - int i = 0; - do { + int i = 0; do { - x = pRandom->IRandom(0,dimX-1); y = pRandom->IRandom(0,dimY-1); - pCell = findCell(x,y); - hab = pCell->getHabIndex(0); - } while (hab > 0); -#if RSDEBUG -//DEBUGLOG << "Landscape::generatePatches() 00000: y=" << y << " x=" << x -// << " i=" << i << " hab=" << hab << " patchnum=" << patchnum -// << endl; -#endif - pPatch = newPatch(patchnum++); - pCell = findCell(x,y); - addCellToPatch(pCell,pPatch); - pCell->changeHabIndex(0,1); - if (continuous) { - pCell->setHabitat((float)(minPct + pRandom->Random() * (maxPct - minPct))); - } - i++; - } while (i < ncells); - // remaining cells need to be added to the matrix patch - p = 0.0; - x = 0; - for (int yy = dimY-1; yy >= 0; yy--) { - for (int xx = 0; xx < dimX; xx++) { - pCell = findCell(xx,yy); + do { + x = pRandom->IRandom(0, dimX - 1); y = pRandom->IRandom(0, dimY - 1); + pCell = findCell(x, y); + hab = pCell->getHabIndex(0); + } while (hab > 0); +#if RSDEBUG + //DEBUGLOG << "Landscape::generatePatches() 00000: y=" << y << " x=" << x + // << " i=" << i << " hab=" << hab << " patchnum=" << patchnum + // << endl; +#endif + pPatch = newPatch(patchnum++); + pCell = findCell(x, y); + addCellToPatch(pCell, pPatch); + pCell->changeHabIndex(0, 1); if (continuous) { - if (pCell->getHabitat(0) <= 0.0) - { - addCellToPatch(pCell,patches[0],(float)p); - } + pCell->setHabitat((float)(minPct + pRandom->Random() * (maxPct - minPct))); } - else { // discrete - if (pCell->getHabIndex(0) == 0) { + i++; + } while (i < ncells); + // remaining cells need to be added to the matrix patch + p = 0.0; + x = 0; + for (int yy = dimY - 1; yy >= 0; yy--) { + for (int xx = 0; xx < dimX; xx++) { + pCell = findCell(xx, yy); + if (continuous) { + if (pCell->getHabitat(0) <= 0.0) + { + addCellToPatch(pCell, patches[0], (float)p); + } + } + else { // discrete + if (pCell->getHabIndex(0) == 0) { #if RSDEBUG -//DEBUGLOG << "Landscape::generatePatches() 11111: yy=" << yy << " xx=" << xx -// << endl; + //DEBUGLOG << "Landscape::generatePatches() 11111: yy=" << yy << " xx=" << xx + // << endl; #endif - addCellToPatch(pCell,patches[0],x); + addCellToPatch(pCell, patches[0], x); + } } } } } -} #if RSDEBUG -//DEBUGLOG << "Landscape::generatePatches(): finished, no. of patches = " -// << patchCount() << endl; + //DEBUGLOG << "Landscape::generatePatches(): finished, no. of patches = " + // << patchCount() << endl; #endif } @@ -785,145 +786,145 @@ else { // random landscape //--------------------------------------------------------------------------- /* Create a patch for each suitable cell of a cell-based landscape (all other habitat cells are added to the matrix patch) */ -void Landscape::allocatePatches(Species *pSpecies) +void Landscape::allocatePatches(Species* pSpecies) { #if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): pSpecies=" << pSpecies -// << " N patches=" << (int)patches.size() << endl; + //DEBUGLOG << "Landscape::allocatePatches(): pSpecies=" << pSpecies + // << " N patches=" << (int)patches.size() << endl; #endif //int hx; -float habK; -Patch *pPatch; -Cell *pCell; + float habK; + Patch* pPatch; + Cell* pCell; -// delete all existing patches -int npatches = (int)patches.size(); -for (int i = 0; i < npatches; i++) { + // delete all existing patches + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) { #if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): i=" << i -// << " patches[i]=" << patches[i] << endl; + //DEBUGLOG << "Landscape::allocatePatches(): i=" << i + // << " patches[i]=" << patches[i] << endl; #endif - if (patches[i] != NULL) delete patches[i]; -} -patches.clear(); -// create the matrix patch -patches.push_back(new Patch(0,0)); -Patch *matrixPatch = patches[0]; + if (patches[i] != NULL) delete patches[i]; + } + patches.clear(); + // create the matrix patch + patches.push_back(new Patch(0, 0)); + Patch* matrixPatch = patches[0]; #if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): npatches=" << npatches -// << " N patches=" << (int)patches.size() << endl; + //DEBUGLOG << "Landscape::allocatePatches(): npatches=" << npatches + // << " N patches=" << (int)patches.size() << endl; #endif -int patchnum = 1; + int patchnum = 1; -switch (rasterType) { + switch (rasterType) { -case 0: // habitat codes - for (int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { + case 0: // habitat codes + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { #if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y -// << " cells=" << cells[y][x] << endl; + //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y + // << " cells=" << cells[y][x] << endl; #endif - if (cells[y][x] != 0) { // not no-data cell - pCell = cells[y][x]; -// hx = pCell->getHabIndex(); -// habK = pSpecies->getHabK(hx); - habK = 0.0; - int nhab = pCell->nHabitats(); - for (int i = 0; i < nhab; i++) { - habK += pSpecies->getHabK(pCell->getHabIndex(i)); + if (cells[y][x] != 0) { // not no-data cell + pCell = cells[y][x]; + // hx = pCell->getHabIndex(); + // habK = pSpecies->getHabK(hx); + habK = 0.0; + int nhab = pCell->nHabitats(); + for (int i = 0; i < nhab; i++) { + habK += pSpecies->getHabK(pCell->getHabIndex(i)); #if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y -// << " i=" << i -// << " cells[y][x]=" << cells[y][x] -// << " pCell=" << pCell -// << " habK=" << habK << endl; + //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y + // << " i=" << i + // << " cells[y][x]=" << cells[y][x] + // << " pCell=" << pCell + // << " habK=" << habK << endl; #endif - } - if (habK > 0.0) { // cell is suitable - create a patch for it - pPatch = newPatch(patchnum++); - addCellToPatch(pCell,pPatch); - } - else { // cell is not suitable - add to the matrix patch - addCellToPatch(pCell,matrixPatch); - pPatch = 0; + } + if (habK > 0.0) { // cell is suitable - create a patch for it + pPatch = newPatch(patchnum++); + addCellToPatch(pCell, pPatch); + } + else { // cell is not suitable - add to the matrix patch + addCellToPatch(pCell, matrixPatch); + pPatch = 0; + } } } } - } - break; -case 1: // habitat cover - for (int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { -#if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y -// << " cells=" << cells[y][x] << endl; -#endif - if (cells[y][x] != 0) { // not no-data cell - pCell = cells[y][x]; - habK = 0.0; - int nhab = pCell->nHabitats(); -// for (int i = 0; i < nHab; i++) - for (int i = 0; i < nhab; i++) - { - habK += pSpecies->getHabK(i) * pCell->getHabitat(i) / 100.0f; -#if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y -// << " i=" << i -// << " cells[y][x]=" << cells[y][x] -// << " pCell=" << pCell -// << " habK=" << habK << endl; + break; + case 1: // habitat cover + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { +#if RSDEBUG + //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y + // << " cells=" << cells[y][x] << endl; +#endif + if (cells[y][x] != 0) { // not no-data cell + pCell = cells[y][x]; + habK = 0.0; + int nhab = pCell->nHabitats(); + // for (int i = 0; i < nHab; i++) + for (int i = 0; i < nhab; i++) + { + habK += pSpecies->getHabK(i) * pCell->getHabitat(i) / 100.0f; +#if RSDEBUG + //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y + // << " i=" << i + // << " cells[y][x]=" << cells[y][x] + // << " pCell=" << pCell + // << " habK=" << habK << endl; #endif - } - if (habK > 0.0) { // cell is suitable - create a patch for it - pPatch = newPatch(patchnum++); - addCellToPatch(pCell,pPatch); - } - else { // cell is not suitable - add to the matrix patch - addCellToPatch(pCell,matrixPatch); - pPatch = 0; + } + if (habK > 0.0) { // cell is suitable - create a patch for it + pPatch = newPatch(patchnum++); + addCellToPatch(pCell, pPatch); + } + else { // cell is not suitable - add to the matrix patch + addCellToPatch(pCell, matrixPatch); + pPatch = 0; + } } } } - } - break; -case 2: // habitat quality - for (int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { -#if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y -// << " cells=" << cells[y][x] << endl; -#endif - if (cells[y][x] != 0) { // not no-data cell - pCell = cells[y][x]; - habK = 0.0; - int nhab = pCell->nHabitats(); -// for (int i = 0; i < nHab; i++) - for (int i = 0; i < nhab; i++) - { - habK += pSpecies->getHabK(0) * pCell->getHabitat(i) / 100.0f; -#if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y -// << " i=" << i -// << " cells[y][x]=" << cells[y][x] -// << " pCell=" << pCell -// << " habK=" << habK << endl; + break; + case 2: // habitat quality + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { +#if RSDEBUG + //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y + // << " cells=" << cells[y][x] << endl; +#endif + if (cells[y][x] != 0) { // not no-data cell + pCell = cells[y][x]; + habK = 0.0; + int nhab = pCell->nHabitats(); + // for (int i = 0; i < nHab; i++) + for (int i = 0; i < nhab; i++) + { + habK += pSpecies->getHabK(0) * pCell->getHabitat(i) / 100.0f; +#if RSDEBUG + //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y + // << " i=" << i + // << " cells[y][x]=" << cells[y][x] + // << " pCell=" << pCell + // << " habK=" << habK << endl; #endif - } - if (habK > 0.0) { // cell is suitable (at some time) - create a patch for it - pPatch = newPatch(patchnum++); - addCellToPatch(pCell,pPatch); - } - else { // cell is never suitable - add to the matrix patch - addCellToPatch(pCell,matrixPatch); - pPatch = 0; + } + if (habK > 0.0) { // cell is suitable (at some time) - create a patch for it + pPatch = newPatch(patchnum++); + addCellToPatch(pCell, pPatch); + } + else { // cell is never suitable - add to the matrix patch + addCellToPatch(pCell, matrixPatch); + pPatch = 0; + } } } } - } - break; + break; -} // end of switch (rasterType) + } // end of switch (rasterType) #if RSDEBUG //DEBUGLOG << "Landscape::allocatePatches(): finished, N patches = " << (int)patches.size() << endl; @@ -931,372 +932,372 @@ case 2: // habitat quality } -Patch* Landscape::newPatch(int num) +Patch* Landscape::newPatch(int num) { -int npatches = (int)patches.size(); -patches.push_back(new Patch(num,num)); -return patches[npatches]; + int npatches = (int)patches.size(); + patches.push_back(new Patch(num, num)); + return patches[npatches]; } -Patch* Landscape::newPatch(int seqnum,int num) +Patch* Landscape::newPatch(int seqnum, int num) { -int npatches = (int)patches.size(); -patches.push_back(new Patch(seqnum,num)); -return patches[npatches]; + int npatches = (int)patches.size(); + patches.push_back(new Patch(seqnum, num)); + return patches[npatches]; } void Landscape::resetPatches(void) { -int npatches = (int)patches.size(); -for (int i = 0; i < npatches; i++) { - patches[i]->resetLimits(); -} + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) { + patches[i]->resetLimits(); + } } -void Landscape::addNewCellToLand(int x,int y,float q) { -if (q < 0.0) // no-data cell - no Cell created - cells[y][x] = 0; -else - cells[y][x] = new Cell(x,y,0,q); +void Landscape::addNewCellToLand(int x, int y, float q) { + if (q < 0.0) // no-data cell - no Cell created + cells[y][x] = 0; + else + cells[y][x] = new Cell(x, y, 0, q); } -void Landscape::addNewCellToLand(int x,int y,int hab) { -if (hab < 0) // no-data cell - no Cell created - cells[y][x] = 0; -else - cells[y][x] = new Cell(x,y,0,hab); +void Landscape::addNewCellToLand(int x, int y, int hab) { + if (hab < 0) // no-data cell - no Cell created + cells[y][x] = 0; + else + cells[y][x] = new Cell(x, y, 0, hab); } -void Landscape::addNewCellToPatch(Patch *pPatch,int x,int y,float q) { -if (q < 0.0) { // no-data cell - no Cell created - cells[y][x] = 0; -} -else { // create the new cell - cells[y][x] = new Cell(x,y,(intptr)pPatch,q); - if (pPatch != 0) { // not the matrix patch - // add the cell to the patch - pPatch->addCell(cells[y][x],x,y); +void Landscape::addNewCellToPatch(Patch* pPatch, int x, int y, float q) { + if (q < 0.0) { // no-data cell - no Cell created + cells[y][x] = 0; + } + else { // create the new cell + cells[y][x] = new Cell(x, y, (intptr)pPatch, q); + if (pPatch != 0) { // not the matrix patch + // add the cell to the patch + pPatch->addCell(cells[y][x], x, y); + } } -} } -void Landscape::addNewCellToPatch(Patch *pPatch,int x,int y,int hab) { -if (hab < 0) // no-data cell - no Cell created - cells[y][x] = 0; -else { // create the new cell - cells[y][x] = new Cell(x,y,(intptr)pPatch,hab); - if (pPatch != 0) { // not the matrix patch - // add the cell to the patch - pPatch->addCell(cells[y][x],x,y); +void Landscape::addNewCellToPatch(Patch* pPatch, int x, int y, int hab) { + if (hab < 0) // no-data cell - no Cell created + cells[y][x] = 0; + else { // create the new cell + cells[y][x] = new Cell(x, y, (intptr)pPatch, hab); + if (pPatch != 0) { // not the matrix patch + // add the cell to the patch + pPatch->addCell(cells[y][x], x, y); + } } } -} -void Landscape::addCellToPatch(Cell *pCell,Patch *pPatch) { -pCell->setPatch((intptr)pPatch); -locn loc = pCell->getLocn(); -// add the cell to the patch -pPatch->addCell(pCell,loc.x,loc.y); +void Landscape::addCellToPatch(Cell* pCell, Patch* pPatch) { + pCell->setPatch((intptr)pPatch); + locn loc = pCell->getLocn(); + // add the cell to the patch + pPatch->addCell(pCell, loc.x, loc.y); } -void Landscape::addCellToPatch(Cell *pCell,Patch *pPatch,float q) { -pCell->setPatch((intptr)pPatch); -// update the habitat type of the cell -pCell->setHabitat(q); -locn loc = pCell->getLocn(); -// add the cell to the patch -pPatch->addCell(pCell,loc.x,loc.y); +void Landscape::addCellToPatch(Cell* pCell, Patch* pPatch, float q) { + pCell->setPatch((intptr)pPatch); + // update the habitat type of the cell + pCell->setHabitat(q); + locn loc = pCell->getLocn(); + // add the cell to the patch + pPatch->addCell(pCell, loc.x, loc.y); } -void Landscape::addCellToPatch(Cell *pCell,Patch *pPatch,int hab) { -pCell->setPatch((intptr)pPatch); -// update the habitat type of the cell -pCell->setHabIndex(hab); -locn loc = pCell->getLocn(); -// add the cell to the patch -pPatch->addCell(pCell,loc.x,loc.y); +void Landscape::addCellToPatch(Cell* pCell, Patch* pPatch, int hab) { + pCell->setPatch((intptr)pPatch); + // update the habitat type of the cell + pCell->setHabIndex(hab); + locn loc = pCell->getLocn(); + // add the cell to the patch + pPatch->addCell(pCell, loc.x, loc.y); } patchData Landscape::getPatchData(int ix) { -patchData ppp; -ppp.pPatch = patches[ix]; ppp.patchNum = patches[ix]->getPatchNum(); -ppp.nCells = patches[ix]->getNCells(); -locn randloc; randloc.x = -666; randloc.y = -666; -Cell *pCell = patches[ix]->getRandomCell(); -if (pCell != 0) { - randloc = pCell->getLocn(); -} -ppp.x = randloc.x; ppp.y = randloc.y; -return ppp; + patchData ppp; + ppp.pPatch = patches[ix]; ppp.patchNum = patches[ix]->getPatchNum(); + ppp.nCells = patches[ix]->getNCells(); + locn randloc; randloc.x = -666; randloc.y = -666; + Cell* pCell = patches[ix]->getRandomCell(); + if (pCell != 0) { + randloc = pCell->getLocn(); + } + ppp.x = randloc.x; ppp.y = randloc.y; + return ppp; } bool Landscape::existsPatch(int num) { -int npatches = (int)patches.size(); -for (int i = 0; i < npatches; i++) { - if (num == patches[i]->getPatchNum()) return true; -} -return false; + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) { + if (num == patches[i]->getPatchNum()) return true; + } + return false; } Patch* Landscape::findPatch(int num) { -int npatches = (int)patches.size(); -for (int i = 0; i < npatches; i++) { - if (num == patches[i]->getPatchNum()) return patches[i]; -} -return 0; + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) { + if (num == patches[i]->getPatchNum()) return patches[i]; + } + return 0; } void Landscape::resetPatchPopns(void) { -int npatches = (int)patches.size(); -for (int i = 0; i < npatches; i++) { - patches[i]->resetPopn(); -} + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) { + patches[i]->resetPopn(); + } } -void Landscape::updateCarryingCapacity(Species *pSpecies,int yr,short landIx) { -envGradParams grad = paramsGrad->getGradient(); -bool gradK = false; -if (grad.gradient && grad.gradType == 1) gradK = true; // gradient in carrying capacity -patchLimits landlimits; -landlimits.xMin = minX; landlimits.xMax = maxX; -landlimits.yMin = minY; landlimits.yMax = maxY; +void Landscape::updateCarryingCapacity(Species* pSpecies, int yr, short landIx) { + envGradParams grad = paramsGrad->getGradient(); + bool gradK = false; + if (grad.gradient && grad.gradType == 1) gradK = true; // gradient in carrying capacity + patchLimits landlimits; + landlimits.xMin = minX; landlimits.xMax = maxX; + landlimits.yMin = minY; landlimits.yMax = maxY; #if RSDEBUG -//DEBUGLOG << "Landscape::updateCarryingCapacity(): yr=" << yr -// << " xMin=" << landlimits.xMin << " yMin=" << landlimits.yMin -// << " xMax=" << landlimits.xMax << " yMax=" << landlimits.yMax -// << endl; + //DEBUGLOG << "Landscape::updateCarryingCapacity(): yr=" << yr + // << " xMin=" << landlimits.xMin << " yMin=" << landlimits.yMin + // << " xMax=" << landlimits.xMax << " yMax=" << landlimits.yMax + // << endl; #endif -int npatches = (int)patches.size(); -for (int i = 0; i < npatches; i++) { - if (patches[i]->getPatchNum() != 0) { // not matrix patch - patches[i]->setCarryingCapacity(pSpecies,landlimits, - getGlobalStoch(yr),nHab,rasterType,landIx,gradK); + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) { + if (patches[i]->getPatchNum() != 0) { // not matrix patch + patches[i]->setCarryingCapacity(pSpecies, landlimits, + getGlobalStoch(yr), nHab, rasterType, landIx, gradK); + } } -} } -Cell* Landscape::findCell(int x,int y) { -if (x >= 0 && x < dimX && y >= 0 && y < dimY) return cells[y][x]; -else return 0; +Cell* Landscape::findCell(int x, int y) { + if (x >= 0 && x < dimX && y >= 0 && y < dimY) return cells[y][x]; + else return 0; } int Landscape::patchCount(void) { -return (int)patches.size(); + return (int)patches.size(); } void Landscape::listPatches(void) { -patchLimits p; -int npatches = (int)patches.size(); + patchLimits p; + int npatches = (int)patches.size(); #if RS_RCPP && !R_CMD -Rcpp::Rcout << endl; -for (int i = 0; i < npatches; i++) { - p = patches[i]->getLimits(); - Rcpp::Rcout << "Patch " << patches[i]->getPatchNum() - << " xMin = " << p.xMin << " xMax = " << p.xMax - << " \tyMin = " << p.yMin << " yMax = " << p.yMax - << endl; -} -Rcpp::Rcout << endl; + Rcpp::Rcout << endl; + for (int i = 0; i < npatches; i++) { + p = patches[i]->getLimits(); + Rcpp::Rcout << "Patch " << patches[i]->getPatchNum() + << " xMin = " << p.xMin << " xMax = " << p.xMax + << " \tyMin = " << p.yMin << " yMax = " << p.yMax + << endl; + } + Rcpp::Rcout << endl; #else -cout << endl; -for (int i = 0; i < npatches; i++) { - p = patches[i]->getLimits(); - cout << "Patch " << patches[i]->getPatchNum() - << " xMin = " << p.xMin << " xMax = " << p.xMax - << " \tyMin = " << p.yMin << " yMax = " << p.yMax - << endl; -} -cout << endl; + cout << endl; + for (int i = 0; i < npatches; i++) { + p = patches[i]->getLimits(); + cout << "Patch " << patches[i]->getPatchNum() + << " xMin = " << p.xMin << " xMax = " << p.xMax + << " \tyMin = " << p.yMin << " yMax = " << p.yMax + << endl; + } + cout << endl; #endif } // Check that total cover of any cell does not exceed 100% // and identify matrix cells int Landscape::checkTotalCover(void) { -if (rasterType != 1) return 0; // not appropriate test -int nCells = 0; -for(int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { - if (cells[y][x] != 0) - { // not a no-data cell - float sumCover = 0.0; - for (int i = 0; i < nHab; i++) { - sumCover += cells[y][x]->getHabitat(i); -#if RSDEBUG -//DebugGUI(("Landscape::checkTotalCover(): y=" + Int2Str(y) -// + " x=" + Int2Str(x) -// + " i=" + Int2Str(i) -// + " sumCover=" + Float2Str(sumCover) -// ).c_str()); + if (rasterType != 1) return 0; // not appropriate test + int nCells = 0; + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (cells[y][x] != 0) + { // not a no-data cell + float sumCover = 0.0; + for (int i = 0; i < nHab; i++) { + sumCover += cells[y][x]->getHabitat(i); +#if RSDEBUG + //DebugGUI(("Landscape::checkTotalCover(): y=" + Int2Str(y) + // + " x=" + Int2Str(x) + // + " i=" + Int2Str(i) + // + " sumCover=" + Float2Str(sumCover) + // ).c_str()); #endif + } + if (sumCover > 100.00001) nCells++; // decimal part to allow for floating point error + if (sumCover <= 0.0) // cell is a matrix cell + cells[y][x]->setHabIndex(0); + else + cells[y][x]->setHabIndex(1); } - if (sumCover > 100.00001) nCells++; // decimal part to allow for floating point error - if (sumCover <= 0.0) // cell is a matrix cell - cells[y][x]->setHabIndex(0); - else - cells[y][x]->setHabIndex(1); } } -} -return nCells; + return nCells; } // Convert habitat codes stored on loading habitat codes landscape to // sequential sorted index numbers void Landscape::updateHabitatIndices(void) { -// sort codes -sort (habCodes.begin(),habCodes.end()); -nHab = (int)habCodes.size(); -// convert codes in landscape -int h; -int changes = (int)landchanges.size(); -#if RSDEBUG -//DebugGUI(("Landscape::updateHabitatIndices(): nHab=" + Int2Str(nHab) -// + " changes=" + Int2Str(changes) -// ).c_str()); -#endif -for(int y = dimY-1; y >= 0; y--){ - for (int x = 0; x < dimX; x++) { - if (cells[y][x] != 0) { // not a no-data cell - for (int c = 0; c <= changes; c++) { - h = cells[y][x]->getHabIndex(c); + // sort codes + sort(habCodes.begin(), habCodes.end()); + nHab = (int)habCodes.size(); + // convert codes in landscape + int h; + int changes = (int)landchanges.size(); +#if RSDEBUG + //DebugGUI(("Landscape::updateHabitatIndices(): nHab=" + Int2Str(nHab) + // + " changes=" + Int2Str(changes) + // ).c_str()); +#endif + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (cells[y][x] != 0) { // not a no-data cell + for (int c = 0; c <= changes; c++) { + h = cells[y][x]->getHabIndex(c); #if RSDEBUG -//DebugGUI(("Landscape::updateHabitatIndices() 00000: y=" + Int2Str(y) -// + " x=" + Int2Str(x) + " c=" + Int2Str(c) + " h=" + Int2Str(h) -// ).c_str()); + //DebugGUI(("Landscape::updateHabitatIndices() 00000: y=" + Int2Str(y) + // + " x=" + Int2Str(x) + " c=" + Int2Str(c) + " h=" + Int2Str(h) + // ).c_str()); #endif - if (h >= 0) { - h = findHabCode(h); + if (h >= 0) { + h = findHabCode(h); #if RSDEBUG -//DebugGUI(("Landscape::updateHabitatIndices() 11111: y=" + Int2Str(y) -// + " x=" + Int2Str(x) + " c=" + Int2Str(c) + " h=" + Int2Str(h) -// ).c_str()); + //DebugGUI(("Landscape::updateHabitatIndices() 11111: y=" + Int2Str(y) + // + " x=" + Int2Str(x) + " c=" + Int2Str(c) + " h=" + Int2Str(h) + // ).c_str()); #endif - cells[y][x]->changeHabIndex(c,h); + cells[y][x]->changeHabIndex(c, h); + } } } } } -} -habIndexed = true; + habIndexed = true; } -void Landscape::setEnvGradient(Species *pSpecies,bool initial) +void Landscape::setEnvGradient(Species* pSpecies, bool initial) { -float dist_from_opt,dev; -float habK; -//int hab; -double envval; -// gradient parameters -envGradParams grad = paramsGrad->getGradient(); -#if RSDEBUG -//DEBUGLOG << "Landscape::setEnvGradient(): grad.opt_y = " << grad.opt_y -// << " grad.grad_inc = " << grad.grad_inc << " grad.factor " << grad.factor -// << endl; -#endif -for(int y = dimY-1; y >= 0; y--){ - for (int x = 0; x < dimX; x++) { - // NB: gradient lies in range 0-1 for all types, and is applied when necessary... - // ... implies gradient increment will be dimensionless in range 0-1 (but << 1) - if (cells[y][x] != 0) { // not no-data cell - habK = 0.0; - int nhab = cells[y][x]->nHabitats(); - for (int i = 0; i < nhab; i++) { - switch (rasterType) { - case 0: - habK += pSpecies->getHabK(cells[y][x]->getHabIndex(i)); - break; - case 1: - habK += pSpecies->getHabK(i) * cells[y][x]->getHabitat(i) / 100.0f; - break; - case 2: - habK += pSpecies->getHabK(0) * cells[y][x]->getHabitat(i) / 100.0f; - break; + float dist_from_opt, dev; + float habK; + //int hab; + double envval; + // gradient parameters + envGradParams grad = paramsGrad->getGradient(); +#if RSDEBUG + //DEBUGLOG << "Landscape::setEnvGradient(): grad.opt_y = " << grad.opt_y + // << " grad.grad_inc = " << grad.grad_inc << " grad.factor " << grad.factor + // << endl; +#endif + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + // NB: gradient lies in range 0-1 for all types, and is applied when necessary... + // ... implies gradient increment will be dimensionless in range 0-1 (but << 1) + if (cells[y][x] != 0) { // not no-data cell + habK = 0.0; + int nhab = cells[y][x]->nHabitats(); + for (int i = 0; i < nhab; i++) { + switch (rasterType) { + case 0: + habK += pSpecies->getHabK(cells[y][x]->getHabIndex(i)); + break; + case 1: + habK += pSpecies->getHabK(i) * cells[y][x]->getHabitat(i) / 100.0f; + break; + case 2: + habK += pSpecies->getHabK(0) * cells[y][x]->getHabitat(i) / 100.0f; + break; + } } - } #if RSDEBUG -//DEBUGLOG << "Landscape::setEnvGradient(): y=" << y << " x=" << x -// << " dist_from_opt=" << dist_from_opt << " rasterType=" << rasterType << " hab=" << hab -// << endl; + //DEBUGLOG << "Landscape::setEnvGradient(): y=" << y << " x=" << x + // << " dist_from_opt=" << dist_from_opt << " rasterType=" << rasterType << " hab=" << hab + // << endl; #endif - if (habK > 0.0) { // suitable cell - if (initial) { // set local environmental deviation - cells[y][x]->setEnvDev((float)pRandom->Random()*(2.0f) - 1.0f); - } - dist_from_opt = (float)(fabs((double)grad.opt_y - (double)y)); - dev = cells[y][x]->getEnvDev(); - envval = 1.0 - dist_from_opt*grad.grad_inc + dev*grad.factor; + if (habK > 0.0) { // suitable cell + if (initial) { // set local environmental deviation + cells[y][x]->setEnvDev((float)pRandom->Random() * (2.0f) - 1.0f); + } + dist_from_opt = (float)(fabs((double)grad.opt_y - (double)y)); + dev = cells[y][x]->getEnvDev(); + envval = 1.0 - dist_from_opt * grad.grad_inc + dev * grad.factor; #if RSDEBUG -//DEBUGLOG << "Landscape::setEnvGradient(): y=" << y << " x=" << x -// << " dist_from_opt=" << dist_from_opt << " dev=" << dev << " p=" << p -// << endl; + //DEBUGLOG << "Landscape::setEnvGradient(): y=" << y << " x=" << x + // << " dist_from_opt=" << dist_from_opt << " dev=" << dev << " p=" << p + // << endl; #endif - if (envval < 0.000001) envval = 0.0; - if (envval > 1.0) envval = 1.0; + if (envval < 0.000001) envval = 0.0; + if (envval > 1.0) envval = 1.0; + } + else envval = 0.0; + cells[y][x]->setEnvVal((float)envval); } - else envval = 0.0; - cells[y][x]->setEnvVal((float)envval); } } -} } void Landscape::setGlobalStoch(int nyears) { -envStochParams env = paramsStoch->getStoch(); -if (epsGlobal != 0) delete[] epsGlobal; -epsGlobal = new float[nyears]; -epsGlobal[0] = (float)(pRandom->Normal(0.0,env.std)*sqrt(1.0-(env.ac*env.ac))); -for (int i = 1; i < nyears; i++){ - epsGlobal[i] = (float)(env.ac*epsGlobal[i-1] + pRandom->Normal(0.0,env.std)*sqrt(1.0-(env.ac*env.ac))); -} + envStochParams env = paramsStoch->getStoch(); + if (epsGlobal != 0) delete[] epsGlobal; + epsGlobal = new float[nyears]; + epsGlobal[0] = (float)(pRandom->Normal(0.0, env.std) * sqrt(1.0 - (env.ac * env.ac))); + for (int i = 1; i < nyears; i++) { + epsGlobal[i] = (float)(env.ac * epsGlobal[i - 1] + pRandom->Normal(0.0, env.std) * sqrt(1.0 - (env.ac * env.ac))); + } } float Landscape::getGlobalStoch(int yr) { -if (epsGlobal != 0 && yr >= 0) { - return epsGlobal[yr]; -} -else return 0.0; + if (epsGlobal != 0 && yr >= 0) { + return epsGlobal[yr]; + } + else return 0.0; } void Landscape::updateLocalStoch(void) { -envStochParams env = paramsStoch->getStoch(); -float randpart; -for(int y = dimY-1; y >= 0; y--){ - for (int x = 0; x < dimX; x++) { - if (cells[y][x] != 0) { // not a no-data cell - randpart = (float)(pRandom->Normal(0.0,env.std) * sqrt(1.0-(env.ac*env.ac))); + envStochParams env = paramsStoch->getStoch(); + float randpart; + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (cells[y][x] != 0) { // not a no-data cell + randpart = (float)(pRandom->Normal(0.0, env.std) * sqrt(1.0 - (env.ac * env.ac))); #if RSDEBUG -//DEBUGLOG << "Landscape::updateLocalStoch(): y=" << y << " x=" << x -// << " env.std= " << env.std << " env.ac= " << env.ac << " randpart= " << randpart -// << endl; + //DEBUGLOG << "Landscape::updateLocalStoch(): y=" << y << " x=" << x + // << " env.std= " << env.std << " env.ac= " << env.ac << " randpart= " << randpart + // << endl; #endif - cells[y][x]->updateEps((float)env.ac,randpart); + cells[y][x]->updateEps((float)env.ac, randpart); + } } } -} } void Landscape::resetCosts(void) { -for(int y = dimY-1; y >= 0; y--){ - for (int x = 0; x < dimX; x++) { - if (cells[y][x] != 0) { // not a no-data cell - cells[y][x]->resetCost(); + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (cells[y][x] != 0) { // not a no-data cell + cells[y][x]->resetCost(); + } } } } -} void Landscape::resetEffCosts(void) { -for(int y = dimY-1; y >= 0; y--){ - for (int x = 0; x < dimX; x++) { - if (cells[y][x] != 0) { // not a no-data cell - cells[y][x]->resetEffCosts(); + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (cells[y][x] != 0) { // not a no-data cell + cells[y][x]->resetEffCosts(); + } } } } -} //--------------------------------------------------------------------------- @@ -1306,61 +1307,61 @@ void Landscape::setDynamicLand(bool dyn) { dynamic = dyn; } void Landscape::addLandChange(landChange c) { #if RSDEBUG -//DebugGUI(("Landscape::addLandChange(): chgnum=" + Int2Str(c.chgnum) -// + " chgyear=" + Int2Str(c.chgyear) -// ).c_str()); + //DebugGUI(("Landscape::addLandChange(): chgnum=" + Int2Str(c.chgnum) + // + " chgyear=" + Int2Str(c.chgyear) + // ).c_str()); #endif -landchanges.push_back(c); + landchanges.push_back(c); } int Landscape::numLandChanges(void) { return (int)landchanges.size(); } landChange Landscape::getLandChange(short ix) { -landChange c; c.chgnum = c.chgyear = 0; -c.habfile = c.pchfile = c.costfile = "none"; -int nchanges = (int)landchanges.size(); -if (ix < nchanges) c = landchanges[ix]; -return c; + landChange c; c.chgnum = c.chgyear = 0; + c.habfile = c.pchfile = c.costfile = "none"; + int nchanges = (int)landchanges.size(); + if (ix < nchanges) c = landchanges[ix]; + return c; } void Landscape::deleteLandChanges(void) { -while (landchanges.size() > 0) landchanges.pop_back(); -landchanges.clear(); + while (landchanges.size() > 0) landchanges.pop_back(); + landchanges.clear(); } #if RS_RCPP && !R_CMD int Landscape::readLandChange(int filenum, bool costs, wifstream& hfile, wifstream& pfile, wifstream& cfile, int habnodata, int pchnodata, int costnodata) #else -int Landscape::readLandChange(int filenum,bool costs) +int Landscape::readLandChange(int filenum, bool costs) #endif { #if RSDEBUG -DEBUGLOG << "Landscape::readLandChange(): filenum=" << filenum << " costs=" << int(costs) - << endl; + DEBUGLOG << "Landscape::readLandChange(): filenum=" << filenum << " costs=" << int(costs) + << endl; #endif #if RS_RCPP -wstring header; + wstring header; #else -string header; -int ncols,nrows,habnodata,costnodata,pchnodata; -costnodata = 0; -pchnodata = 0; + string header; + int ncols, nrows, habnodata, costnodata, pchnodata; + costnodata = 0; + pchnodata = 0; #endif -int h = 0,p = 0,c = 0, pchseq = 0; -float hfloat,pfloat,cfloat; -simParams sim = paramsSim->getSim(); + int h = 0, p = 0, c = 0, pchseq = 0; + float hfloat, pfloat, cfloat; + simParams sim = paramsSim->getSim(); -if (filenum < 0) return 19; + if (filenum < 0) return 19; -//if (patchModel && (rasterType == 0 || rasterType == 2)) { -// if (filenum == 0) { // first change -// createPatchChgMatrix(); -// } -// pchseq = patchCount(); -//} -if (patchModel) pchseq = patchCount(); + //if (patchModel && (rasterType == 0 || rasterType == 2)) { + // if (filenum == 0) { // first change + // createPatchChgMatrix(); + // } + // pchseq = patchCount(); + //} + if (patchModel) pchseq = patchCount(); #if !RS_RCPP ifstream hfile; // habitat file input stream @@ -1369,643 +1370,649 @@ if (patchModel) pchseq = patchCount(); #endif #if !RS_RCPP || R_CMD -// open habitat file and optionally also patch and costs files -hfile.open(landchanges[filenum].habfile.c_str()); -if (!hfile.is_open()) return 30; -if (patchModel) { - pfile.open(landchanges[filenum].pchfile.c_str()); - if (!pfile.is_open()) { - hfile.close(); hfile.clear(); - return 31; + // open habitat file and optionally also patch and costs files + hfile.open(landchanges[filenum].habfile.c_str()); + if (!hfile.is_open()) return 30; + if (patchModel) { + pfile.open(landchanges[filenum].pchfile.c_str()); + if (!pfile.is_open()) { + hfile.close(); hfile.clear(); + return 31; + } } -} -if (costs) { - cfile.open(landchanges[filenum].costfile.c_str()); - if (!cfile.is_open()) { - hfile.close(); hfile.clear(); - if (pfile.is_open()) { - pfile.close(); pfile.clear(); + if (costs) { + cfile.open(landchanges[filenum].costfile.c_str()); + if (!cfile.is_open()) { + hfile.close(); hfile.clear(); + if (pfile.is_open()) { + pfile.close(); pfile.clear(); + } + return 32; } - return 32; } -} -// read header records of habitat (and patch) file(s) -// NB headers of all files have already been compared -hfile >> header >> ncols >> header >> nrows >> header >> hfloat >> header >> hfloat - >> header >> hfloat >> header >> habnodata; -if (patchModel) { - for (int i = 0; i < 5; i++) pfile >> header >> pfloat; - pfile >> header >> pchnodata; -} -if (costs) { - for (int i = 0; i < 5; i++) cfile >> header >> cfloat; - cfile >> header >> costnodata; -} + // read header records of habitat (and patch) file(s) + // NB headers of all files have already been compared + hfile >> header >> ncols >> header >> nrows >> header >> hfloat >> header >> hfloat + >> header >> hfloat >> header >> habnodata; + if (patchModel) { + for (int i = 0; i < 5; i++) pfile >> header >> pfloat; + pfile >> header >> pchnodata; + } + if (costs) { + for (int i = 0; i < 5; i++) cfile >> header >> cfloat; + cfile >> header >> costnodata; + } #endif -// set up bad float values to ensure that valid values are read -float badhfloat = -9.0; if (habnodata == -9) badhfloat = -99.0; -float badpfloat = -9.0; if (pchnodata == -9) badpfloat = -99.0; -float badcfloat = -9.0; if (costnodata == -9) badcfloat = -99.0; + // set up bad float values to ensure that valid values are read + float badhfloat = -9.0; if (habnodata == -9) badhfloat = -99.0; + float badpfloat = -9.0; if (pchnodata == -9) badpfloat = -99.0; + float badcfloat = -9.0; if (costnodata == -9) badcfloat = -99.0; -switch (rasterType) { + switch (rasterType) { -case 0: // raster with habitat codes - 100% habitat each cell - for (int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { - hfloat = badhfloat; + case 0: // raster with habitat codes - 100% habitat each cell + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + hfloat = badhfloat; #if RS_RCPP - if(hfile >> hfloat) { + if (hfile >> hfloat) { #else - hfile >> hfloat; + hfile >> hfloat; #endif - h = (int)hfloat; + h = (int)hfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR("habitatchgfile"); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 171; - } + } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - if (patchModel) { - pfloat = badpfloat; + StreamErrorR("habitatchgfile"); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 171; + } +#endif + if (patchModel) { + pfloat = badpfloat; #if RS_RCPP - if(pfile >> pfloat) { + if (pfile >> pfloat) { #else - pfile >> pfloat; + pfile >> pfloat; #endif - p = (int)pfloat; + p = (int)pfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR("patchchgfile"); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 172; - } + } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - } - if (costs) { - cfloat = badcfloat; + StreamErrorR("patchchgfile"); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 172; + } +#endif + } + if (costs) { + cfloat = badcfloat; #if RS_RCPP - if(cfile >> cfloat) { + if (cfile >> cfloat) { #else - cfile >> cfloat; + cfile >> cfloat; #endif - c = (int)cfloat; + c = (int)cfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR("costchgfile"); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 173; - } -#endif } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR("costchgfile"); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 173; + } +#endif + } #if RSDEBUG -//DebugGUI(("Landscape::readLandscape(): x=" + Int2Str(x) + " y=" + Int2Str(y) -// + " h=" + Int2Str(h) + " p=" + Int2Str(p) -//).c_str()); + //DebugGUI(("Landscape::readLandscape(): x=" + Int2Str(x) + " y=" + Int2Str(y) + // + " h=" + Int2Str(h) + " p=" + Int2Str(p) + //).c_str()); #endif - if (cells[y][x] != 0) { // not a no data cell (in initial landscape) - if (h == habnodata) { // invalid no data cell in change map - hfile.close(); hfile.clear(); - return 36; - } - else { - if (h < 0 || (sim.batchMode && (h < 1 || h > nHabMax))) { - // invalid habitat code - hfile.close(); hfile.clear(); - if (patchModel) { pfile.close(); pfile.clear(); } - return 33; - } - else { - addHabCode(h); - cells[y][x]->setHabIndex(h); - } - } - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code - #if RS_RCPP && !R_CMD - if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; - else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; - #endif - hfile.close(); hfile.clear(); - pfile.close(); pfile.clear(); - return 34; - } - else { - patchChgMatrix[y][x][2] = p; - if (p > 0 && !existsPatch(p)) { - addPatchNum(p); - newPatch(pchseq++,p); - } - } + if (cells[y][x] != 0) { // not a no data cell (in initial landscape) + if (h == habnodata) { // invalid no data cell in change map + hfile.close(); hfile.clear(); + return 36; + } + else { + if (h < 0 || (sim.batchMode && (h < 1 || h > nHabMax))) { + // invalid habitat code + hfile.close(); hfile.clear(); + if (patchModel) { pfile.close(); pfile.clear(); } + return 33; + } + else { + addHabCode(h); + cells[y][x]->setHabIndex(h); + } + } + if (patchModel) { + if (p < 0 || p == pchnodata) { // invalid patch code +#if RS_RCPP && !R_CMD + if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; +#endif + hfile.close(); hfile.clear(); + pfile.close(); pfile.clear(); + return 34; + } + else { + patchChgMatrix[y][x][2] = p; + if (p > 0 && !existsPatch(p)) { + addPatchNum(p); + newPatch(pchseq++, p); } - if (costs) { - if (c < 1) { // invalid cost - hfile.close(); hfile.clear(); - if (pfile.is_open()) { - pfile.close(); pfile.clear(); - } - return 38; - } - else { - costsChgMatrix[y][x][2] = c; - } + } + } + if (costs) { + if (c < 1) { // invalid cost + hfile.close(); hfile.clear(); + if (pfile.is_open()) { + pfile.close(); pfile.clear(); } + return 38; + } + else { + costsChgMatrix[y][x][2] = c; } } } + } + } #if RS_RCPP - hfile >> hfloat; - if (!hfile.eof()) EOFerrorR("habitatchgfile"); - if (patchModel) - { - pfile >> pfloat; - if (!pfile.eof()) EOFerrorR("patchchgfile"); - } - if (costs) - { - cfile >> cfloat; - if (!cfile.eof()) EOFerrorR("costchgfile"); - } + hfile >> hfloat; + if (!hfile.eof()) EOFerrorR("habitatchgfile"); + if (patchModel) + { + pfile >> pfloat; + if (!pfile.eof()) EOFerrorR("patchchgfile"); + } + if (costs) + { + cfile >> cfloat; + if (!cfile.eof()) EOFerrorR("costchgfile"); + } #endif - break; + break; case 2: // habitat quality - for (int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { - hfloat = badhfloat; + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + hfloat = badhfloat; #if RS_RCPP - if(hfile >> hfloat) { + if (hfile >> hfloat) { #else - hfile >> hfloat; + hfile >> hfloat; #endif - h = (int)hfloat; + h = (int)hfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR("habitatchgfile"); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 172; - } + } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - if (patchModel) { - pfloat = badpfloat; + StreamErrorR("habitatchgfile"); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 172; + } +#endif + if (patchModel) { + pfloat = badpfloat; #if RS_RCPP - if(pfile >> pfloat) { + if (pfile >> pfloat) { #else - pfile >> pfloat; + pfile >> pfloat; #endif - p = (int)pfloat; + p = (int)pfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR("patchchgfile"); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 175; - } -#endif } - if (costs) { - cfloat = badcfloat; + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR("patchchgfile"); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 175; + } +#endif + } + if (costs) { + cfloat = badcfloat; #if RS_RCPP - if(cfile >> cfloat) { + if (cfile >> cfloat) { #else - cfile >> cfloat; + cfile >> cfloat; #endif - c = (int)cfloat; + c = (int)cfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR("costchgfile"); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 173; - } -#endif } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR("costchgfile"); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 173; + } +#endif + } #if RSDEBUG -//MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) -// + " p=" + Int2Str(p)).c_str()); + //MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) + // + " p=" + Int2Str(p)).c_str()); #endif - if (cells[y][x] != 0) { // not a no data cell (in initial landscape) - if (h == habnodata) { // invalid no data cell in change map + if (cells[y][x] != 0) { // not a no data cell (in initial landscape) + if (h == habnodata) { // invalid no data cell in change map + hfile.close(); hfile.clear(); + if (patchModel) { pfile.close(); pfile.clear(); } + return 36; + } + else { + if (hfloat < 0.0 || hfloat > 100.0) { // invalid quality score hfile.close(); hfile.clear(); if (patchModel) { pfile.close(); pfile.clear(); } - return 36; + return 37; } else { - if (hfloat < 0.0 || hfloat > 100.0) { // invalid quality score - hfile.close(); hfile.clear(); - if (patchModel) { pfile.close(); pfile.clear(); } - return 37; - } - else { - cells[y][x]->setHabitat(hfloat); + cells[y][x]->setHabitat(hfloat); + } + } + if (patchModel) { + if (p < 0 || p == pchnodata) { // invalid patch code +#if RS_RCPP && !R_CMD + if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; +#endif + hfile.close(); hfile.clear(); + pfile.close(); pfile.clear(); + return 34; + } + else { + patchChgMatrix[y][x][2] = p; + if (p > 0 && !existsPatch(p)) { + addPatchNum(p); + newPatch(pchseq++, p); } } - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code - #if RS_RCPP && !R_CMD - if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; - else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; - #endif - hfile.close(); hfile.clear(); + } + if (costs) { + if (c < 1) { // invalid cost + hfile.close(); hfile.clear(); + if (pfile.is_open()) { pfile.close(); pfile.clear(); - return 34; - } - else { - patchChgMatrix[y][x][2] = p; - if (p > 0 && !existsPatch(p)) { - addPatchNum(p); - newPatch(pchseq++,p); - } } + return 38; } - if (costs) { - if (c < 1) { // invalid cost - hfile.close(); hfile.clear(); - if (pfile.is_open()) { - pfile.close(); pfile.clear(); - } - return 38; - } - else { - costsChgMatrix[y][x][2] = c; - } + else { + costsChgMatrix[y][x][2] = c; } } } - } + } + } #if RS_RCPP - hfile >> hfloat; - if (!hfile.eof()) EOFerrorR("habitatchgfile"); - if (patchModel) - { - pfile >> pfloat; - if (!pfile.eof()) EOFerrorR("patchchgfile"); - } - if (costs) - { - cfile >> cfloat; - if (!cfile.eof()) EOFerrorR("costchgfile"); - } + hfile >> hfloat; + if (!hfile.eof()) EOFerrorR("habitatchgfile"); + if (patchModel) + { + pfile >> pfloat; + if (!pfile.eof()) EOFerrorR("patchchgfile"); + } + if (costs) + { + cfile >> cfloat; + if (!cfile.eof()) EOFerrorR("costchgfile"); + } #endif - break; + break; default: break; -} + } -if (hfile.is_open()) { hfile.close(); hfile.clear(); } -if (pfile.is_open()) { pfile.close(); pfile.clear(); } -if (cfile.is_open()) { cfile.close(); cfile.clear(); } -return 0; + if (hfile.is_open()) { hfile.close(); hfile.clear(); } + if (pfile.is_open()) { pfile.close(); pfile.clear(); } + if (cfile.is_open()) { cfile.close(); cfile.clear(); } + return 0; } // Create & initialise patch change matrix void Landscape::createPatchChgMatrix(void) { -intptr patch; -Patch *pPatch; -Cell *pCell; -if (patchChgMatrix != 0) deletePatchChgMatrix(); -patchChgMatrix = new int **[dimY]; -for(int y = dimY-1; y >= 0; y--){ - patchChgMatrix[y] = new int *[dimX]; - for (int x = 0; x < dimX; x++) { - patchChgMatrix[y][x] = new int [3]; - pCell = findCell(x,y); - if (pCell == 0) { // no-data cell - patchChgMatrix[y][x][0] = patchChgMatrix[y][x][1] = 0; - } - else { - // record initial patch number - patch = pCell->getPatch(); - if (patch == 0) { // matrix cell + intptr patch; + Patch* pPatch; + Cell* pCell; + if (patchChgMatrix != 0) deletePatchChgMatrix(); + patchChgMatrix = new int** [dimY]; + for (int y = dimY - 1; y >= 0; y--) { + patchChgMatrix[y] = new int* [dimX]; + for (int x = 0; x < dimX; x++) { + patchChgMatrix[y][x] = new int[3]; + pCell = findCell(x, y); + if (pCell == 0) { // no-data cell patchChgMatrix[y][x][0] = patchChgMatrix[y][x][1] = 0; } else { - pPatch = (Patch*)patch; - patchChgMatrix[y][x][0] = patchChgMatrix[y][x][1] = pPatch->getPatchNum(); + // record initial patch number + patch = pCell->getPatch(); + if (patch == 0) { // matrix cell + patchChgMatrix[y][x][0] = patchChgMatrix[y][x][1] = 0; + } + else { + pPatch = (Patch*)patch; + patchChgMatrix[y][x][0] = patchChgMatrix[y][x][1] = pPatch->getPatchNum(); + } } - } - patchChgMatrix[y][x][2] = 0; + patchChgMatrix[y][x][2] = 0; #if RSDEBUG -//DebugGUI(("Landscape::createPatchChgMatrix(): y=" + Int2Str(y) -// + " x=" + Int2Str(x) -// + " patchChgMatrix[y][x][0]=" + Int2Str(patchChgMatrix[y][x][0]) -// + " [1]=" + Int2Str(patchChgMatrix[y][x][1]) -// + " [2]=" + Int2Str(patchChgMatrix[y][x][2]) -// ).c_str()); + //DebugGUI(("Landscape::createPatchChgMatrix(): y=" + Int2Str(y) + // + " x=" + Int2Str(x) + // + " patchChgMatrix[y][x][0]=" + Int2Str(patchChgMatrix[y][x][0]) + // + " [1]=" + Int2Str(patchChgMatrix[y][x][1]) + // + " [2]=" + Int2Str(patchChgMatrix[y][x][2]) + // ).c_str()); #endif + } } } -} void Landscape::recordPatchChanges(int landIx) { -if (patchChgMatrix == 0) return; // should not occur -patchChange chg; - -for(int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { - if (landIx == 0) { // reset to original landscape - if (patchChgMatrix[y][x][0] != patchChgMatrix[y][x][2]) { - // record change of patch for current cell - chg.chgnum = 666666; chg.x = x; chg.y = y; - chg.oldpatch = patchChgMatrix[y][x][2]; - chg.newpatch = patchChgMatrix[y][x][0]; - patchchanges.push_back(chg); -#if RSDEBUG -//DebugGUI(("Landscape::recordPatchChanges(): landIx=" + Int2Str(landIx) -// + " chg.chgnum=" + Int2Str(chg.chgnum) -// + " chg.x=" + Int2Str(chg.x) -// + " chg.y=" + Int2Str(chg.y) -// + " chg.oldpatch=" + Int2Str(chg.oldpatch) -// + " chg.newpatch=" + Int2Str(chg.newpatch) -// ).c_str()); + if (patchChgMatrix == 0) return; // should not occur + patchChange chg; + + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (landIx == 0) { // reset to original landscape + if (patchChgMatrix[y][x][0] != patchChgMatrix[y][x][2]) { + // record change of patch for current cell + chg.chgnum = 666666; chg.x = x; chg.y = y; + chg.oldpatch = patchChgMatrix[y][x][2]; + chg.newpatch = patchChgMatrix[y][x][0]; + patchchanges.push_back(chg); +#if RSDEBUG + //DebugGUI(("Landscape::recordPatchChanges(): landIx=" + Int2Str(landIx) + // + " chg.chgnum=" + Int2Str(chg.chgnum) + // + " chg.x=" + Int2Str(chg.x) + // + " chg.y=" + Int2Str(chg.y) + // + " chg.oldpatch=" + Int2Str(chg.oldpatch) + // + " chg.newpatch=" + Int2Str(chg.newpatch) + // ).c_str()); #endif + } } - } - else { // any other change - if (patchChgMatrix[y][x][2] != patchChgMatrix[y][x][1]) { - // record change of patch for current cell - chg.chgnum = landIx; chg.x = x; chg.y = y; - chg.oldpatch = patchChgMatrix[y][x][1]; - chg.newpatch = patchChgMatrix[y][x][2]; - patchchanges.push_back(chg); -#if RSDEBUG -//DebugGUI(("Landscape::recordPatchChanges(): landIx=" + Int2Str(landIx) -// + " chg.chgnum=" + Int2Str(chg.chgnum) -// + " chg.x=" + Int2Str(chg.x) -// + " chg.y=" + Int2Str(chg.y) -// + " chg.oldpatch=" + Int2Str(chg.oldpatch) -// + " chg.newpatch=" + Int2Str(chg.newpatch) -// ).c_str()); + else { // any other change + if (patchChgMatrix[y][x][2] != patchChgMatrix[y][x][1]) { + // record change of patch for current cell + chg.chgnum = landIx; chg.x = x; chg.y = y; + chg.oldpatch = patchChgMatrix[y][x][1]; + chg.newpatch = patchChgMatrix[y][x][2]; + patchchanges.push_back(chg); +#if RSDEBUG + //DebugGUI(("Landscape::recordPatchChanges(): landIx=" + Int2Str(landIx) + // + " chg.chgnum=" + Int2Str(chg.chgnum) + // + " chg.x=" + Int2Str(chg.x) + // + " chg.y=" + Int2Str(chg.y) + // + " chg.oldpatch=" + Int2Str(chg.oldpatch) + // + " chg.newpatch=" + Int2Str(chg.newpatch) + // ).c_str()); #endif + } } + // reset cell for next landscape change + patchChgMatrix[y][x][1] = patchChgMatrix[y][x][2]; } - // reset cell for next landscape change - patchChgMatrix[y][x][1] = patchChgMatrix[y][x][2]; } -} } int Landscape::numPatchChanges(void) { return (int)patchchanges.size(); } patchChange Landscape::getPatchChange(int i) { -patchChange c; c.chgnum = 99999999; c.x = c.y = c.oldpatch = c.newpatch = -1; -if (i >= 0 && i < (int)patchchanges.size()) c = patchchanges[i]; -return c; + patchChange c; c.chgnum = 99999999; c.x = c.y = c.oldpatch = c.newpatch = -1; + if (i >= 0 && i < (int)patchchanges.size()) c = patchchanges[i]; + return c; } void Landscape::deletePatchChgMatrix(void) { -if (patchChgMatrix != 0) { - for(int y = dimY-1; y >= 0; y--){ - for (int x = 0; x < dimX; x++) { - delete[] patchChgMatrix[y][x]; + if (patchChgMatrix != 0) { + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + delete[] patchChgMatrix[y][x]; + } + delete[] patchChgMatrix[y]; } - delete[] patchChgMatrix[y]; } -} -patchChgMatrix = 0; + patchChgMatrix = 0; } // Create & initialise costs change matrix void Landscape::createCostsChgMatrix(void) { -//intptr patch; -//Patch *pPatch; -Cell *pCell; -if (costsChgMatrix != 0) deleteCostsChgMatrix(); -costsChgMatrix = new int **[dimY]; -for(int y = dimY-1; y >= 0; y--){ - costsChgMatrix[y] = new int *[dimX]; - for (int x = 0; x < dimX; x++) { - costsChgMatrix[y][x] = new int [3]; - pCell = findCell(x,y); - if (pCell == 0) { // no-data cell - costsChgMatrix[y][x][0] = costsChgMatrix[y][x][1] = 0; - } - else { - // record initial cost - costsChgMatrix[y][x][0] = costsChgMatrix[y][x][1] = pCell->getCost(); - } - costsChgMatrix[y][x][2] = 0; + //intptr patch; + //Patch *pPatch; + Cell* pCell; + if (costsChgMatrix != 0) deleteCostsChgMatrix(); + costsChgMatrix = new int** [dimY]; + for (int y = dimY - 1; y >= 0; y--) { + costsChgMatrix[y] = new int* [dimX]; + for (int x = 0; x < dimX; x++) { + costsChgMatrix[y][x] = new int[3]; + pCell = findCell(x, y); + if (pCell == 0) { // no-data cell + costsChgMatrix[y][x][0] = costsChgMatrix[y][x][1] = 0; + } + else { + // record initial cost + costsChgMatrix[y][x][0] = costsChgMatrix[y][x][1] = pCell->getCost(); + } + costsChgMatrix[y][x][2] = 0; #if RSDEBUG -//DebugGUI(("Landscape::createCostsChgMatrix(): y=" + Int2Str(y) -// + " x=" + Int2Str(x) -// + " costsChgMatrix[y][x][0]=" + Int2Str(costsChgMatrix[y][x][0]) -// + " [1]=" + Int2Str(costsChgMatrix[y][x][1]) -// + " [2]=" + Int2Str(costsChgMatrix[y][x][2]) -// ).c_str()); + //DebugGUI(("Landscape::createCostsChgMatrix(): y=" + Int2Str(y) + // + " x=" + Int2Str(x) + // + " costsChgMatrix[y][x][0]=" + Int2Str(costsChgMatrix[y][x][0]) + // + " [1]=" + Int2Str(costsChgMatrix[y][x][1]) + // + " [2]=" + Int2Str(costsChgMatrix[y][x][2]) + // ).c_str()); #endif + } } } -} void Landscape::recordCostChanges(int landIx) { #if RSDEBUG -DEBUGLOG << "Landscape::recordCostChanges(): landIx=" << landIx << endl; -#endif -if (costsChgMatrix == 0) return; // should not occur -costChange chg; - -for(int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { - if (landIx == 0) { // reset to original landscape - if (costsChgMatrix[y][x][0] != costsChgMatrix[y][x][2]) { - // record change of cost for current cell - chg.chgnum = 666666; chg.x = x; chg.y = y; - chg.oldcost = costsChgMatrix[y][x][2]; - chg.newcost = costsChgMatrix[y][x][0]; - costschanges.push_back(chg); -#if RSDEBUG -//DebugGUI(("Landscape::recordCostsChanges(): landIx=" + Int2Str(landIx) -// + " chg.chgnum=" + Int2Str(chg.chgnum) -// + " chg.x=" + Int2Str(chg.x) -// + " chg.y=" + Int2Str(chg.y) -// + " chg.oldcost=" + Int2Str(chg.oldcost) -// + " chg.newcost=" + Int2Str(chg.newcost) -// ).c_str()); + DEBUGLOG << "Landscape::recordCostChanges(): landIx=" << landIx << endl; #endif - } - } - else { // any other change -#if RSDEBUG -//if (x < 20 && y == 0) { -// DEBUGLOG << "Landscape::recordCostChanges(): x=" << x << " y=" << y -// << " costsChgMatrix[y][x][0]=" << costsChgMatrix[y][x][0] -// << " costsChgMatrix[y][x][1]=" << costsChgMatrix[y][x][1] -// << " costsChgMatrix[y][x][2]=" << costsChgMatrix[y][x][2] -// << endl; -//} + if (costsChgMatrix == 0) return; // should not occur + costChange chg; + + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (landIx == 0) { // reset to original landscape + if (costsChgMatrix[y][x][0] != costsChgMatrix[y][x][2]) { + // record change of cost for current cell + chg.chgnum = 666666; chg.x = x; chg.y = y; + chg.oldcost = costsChgMatrix[y][x][2]; + chg.newcost = costsChgMatrix[y][x][0]; + costschanges.push_back(chg); +#if RSDEBUG + //DebugGUI(("Landscape::recordCostsChanges(): landIx=" + Int2Str(landIx) + // + " chg.chgnum=" + Int2Str(chg.chgnum) + // + " chg.x=" + Int2Str(chg.x) + // + " chg.y=" + Int2Str(chg.y) + // + " chg.oldcost=" + Int2Str(chg.oldcost) + // + " chg.newcost=" + Int2Str(chg.newcost) + // ).c_str()); #endif - if (costsChgMatrix[y][x][2] != costsChgMatrix[y][x][1]) { - // record change of cost for current cell - chg.chgnum = landIx; chg.x = x; chg.y = y; - chg.oldcost = costsChgMatrix[y][x][1]; - chg.newcost = costsChgMatrix[y][x][2]; - costschanges.push_back(chg); -#if RSDEBUG -//DebugGUI(("Landscape::recordCostsChanges(): landIx=" + Int2Str(landIx) -// + " chg.chgnum=" + Int2Str(chg.chgnum) -// + " chg.x=" + Int2Str(chg.x) -// + " chg.y=" + Int2Str(chg.y) -// + " chg.oldcost=" + Int2Str(chg.oldcost) -// + " chg.newcost=" + Int2Str(chg.newcost) -// ).c_str()); + } + } + else { // any other change +#if RSDEBUG + //if (x < 20 && y == 0) { + // DEBUGLOG << "Landscape::recordCostChanges(): x=" << x << " y=" << y + // << " costsChgMatrix[y][x][0]=" << costsChgMatrix[y][x][0] + // << " costsChgMatrix[y][x][1]=" << costsChgMatrix[y][x][1] + // << " costsChgMatrix[y][x][2]=" << costsChgMatrix[y][x][2] + // << endl; + //} +#endif + if (costsChgMatrix[y][x][2] != costsChgMatrix[y][x][1]) { + // record change of cost for current cell + chg.chgnum = landIx; chg.x = x; chg.y = y; + chg.oldcost = costsChgMatrix[y][x][1]; + chg.newcost = costsChgMatrix[y][x][2]; + costschanges.push_back(chg); +#if RSDEBUG + //DebugGUI(("Landscape::recordCostsChanges(): landIx=" + Int2Str(landIx) + // + " chg.chgnum=" + Int2Str(chg.chgnum) + // + " chg.x=" + Int2Str(chg.x) + // + " chg.y=" + Int2Str(chg.y) + // + " chg.oldcost=" + Int2Str(chg.oldcost) + // + " chg.newcost=" + Int2Str(chg.newcost) + // ).c_str()); #endif + } } + // reset cell for next landscape change + costsChgMatrix[y][x][1] = costsChgMatrix[y][x][2]; } - // reset cell for next landscape change - costsChgMatrix[y][x][1] = costsChgMatrix[y][x][2]; } -} } int Landscape::numCostChanges(void) { return (int)costschanges.size(); } costChange Landscape::getCostChange(int i) { -costChange c; c.chgnum = 99999999; c.x = c.y = c.oldcost = c.newcost = -1; -if (i >= 0 && i < (int)costschanges.size()) c = costschanges[i]; -return c; + costChange c; c.chgnum = 99999999; c.x = c.y = c.oldcost = c.newcost = -1; + if (i >= 0 && i < (int)costschanges.size()) c = costschanges[i]; + return c; } void Landscape::deleteCostsChgMatrix(void) { -if (costsChgMatrix != 0) { - for(int y = dimY-1; y >= 0; y--){ - for (int x = 0; x < dimX; x++) { - delete[] costsChgMatrix[y][x]; + if (costsChgMatrix != 0) { + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + delete[] costsChgMatrix[y][x]; + } + delete[] costsChgMatrix[y]; } - delete[] costsChgMatrix[y]; } -} -costsChgMatrix = 0; + costsChgMatrix = 0; } //--------------------------------------------------------------------------- // Species distribution functions -int Landscape::newDistribution(Species *pSpecies, string distname) { -int readcode; -int ndistns = (int)distns.size(); -distns.push_back(new InitDist(pSpecies)); -readcode = distns[ndistns]->readDistribution(distname); -if (readcode != 0) { // error encountered - // delete the distribution created above - delete distns[ndistns]; - distns.pop_back(); -} -return readcode; +int Landscape::newDistribution(Species* pSpecies, string distname) { + int readcode; + int ndistns = (int)distns.size(); + distns.push_back(new InitDist(pSpecies)); + readcode = distns[ndistns]->readDistribution(distname); + if (readcode != 0) { // error encountered + // delete the distribution created above + delete distns[ndistns]; + distns.pop_back(); + } + return readcode; } -void Landscape::setDistribution(Species *pSpecies,int nInit) { -// WILL NEED TO SELECT DISTRIBUTION FOR CORRECT SPECIES ... -// ... CURRENTLY IT IS THE ONLY ONE -distns[0]->setDistribution(nInit); +void Landscape::setDistribution(Species* pSpecies, int nInit) { + // WILL NEED TO SELECT DISTRIBUTION FOR CORRECT SPECIES ... + // ... CURRENTLY IT IS THE ONLY ONE + distns[0]->setDistribution(nInit); } // Specified cell match one of the distribution cells to be initialised? -bool Landscape::inInitialDist(Species *pSpecies,locn loc) { -// convert landscape co-ordinates to distribution co-ordinates -locn initloc; -initloc.x = loc.x * resol / spResol; -initloc.y = loc.y * resol / spResol; -// WILL HAVE TO GET CORRECT SPECIES WHEN THERE ARE MULTIPLE SPECIES ... -bool initialise = distns[0]->inInitialDist(initloc); -return initialise; +bool Landscape::inInitialDist(Species* pSpecies, locn loc) { + // convert landscape co-ordinates to distribution co-ordinates + locn initloc; + initloc.x = loc.x * resol / spResol; + initloc.y = loc.y * resol / spResol; + // WILL HAVE TO GET CORRECT SPECIES WHEN THERE ARE MULTIPLE SPECIES ... + bool initialise = distns[0]->inInitialDist(initloc); + return initialise; } -void Landscape::deleteDistribution(Species *pSpecies) { -// WILL NEED TO SELECT DISTRIBUTION FOR CORRECT SPECIES ... -// ... CURRENTLY IT IS THE ONLY ONE ... -// ... FOR MULTIPLE SPECIES IT MAY BE BETTER TO USE A DYNAMIC ARRAY FOR -// SPECIES DISTRIBUTIONS INDEXED BY SPECIES NUMBER, RATHER THAN A VECTOR -if (distns[0] != 0) delete distns[0]; distns.clear(); +void Landscape::deleteDistribution(Species* pSpecies) { + // WILL NEED TO SELECT DISTRIBUTION FOR CORRECT SPECIES ... + // ... CURRENTLY IT IS THE ONLY ONE ... + // ... FOR MULTIPLE SPECIES IT MAY BE BETTER TO USE A DYNAMIC ARRAY FOR + // SPECIES DISTRIBUTIONS INDEXED BY SPECIES NUMBER, RATHER THAN A VECTOR + if (distns[0] != 0) delete distns[0]; distns.clear(); } // Return no. of initial distributions int Landscape::distnCount(void) { -return (int)distns.size(); + return (int)distns.size(); } int Landscape::distCellCount(int dist) { -return distns[dist]->cellCount(); + return distns[dist]->cellCount(); } // Set a cell in a specified initial distribution (by position in cells vector) -void Landscape::setDistnCell(int dist,int ix,bool init) { -distns[dist]->setDistCell(ix,init); +void Landscape::setDistnCell(int dist, int ix, bool init) { + distns[dist]->setDistCell(ix, init); } // Set a cell in a specified initial distribution (by given co-ordinates) -void Landscape::setDistnCell(int dist,locn loc,bool init) { -distns[dist]->setDistCell(loc,init); +void Landscape::setDistnCell(int dist, locn loc, bool init) { + distns[dist]->setDistCell(loc, init); } // Get the co-ordinates of a specified cell in a specified initial distribution -locn Landscape::getDistnCell(int dist,int ix) { -return distns[dist]->getCell(ix); +locn Landscape::getDistnCell(int dist, int ix) { + return distns[dist]->getCell(ix); } // Get the co-ordinates of a specified cell in a specified initial distribution // Returns negative co-ordinates if the cell is not selected -locn Landscape::getSelectedDistnCell(int dist,int ix) { -return distns[dist]->getSelectedCell(ix); +locn Landscape::getSelectedDistnCell(int dist, int ix) { + return distns[dist]->getSelectedCell(ix); } // Get the dimensions of a specified initial distribution locn Landscape::getDistnDimensions(int dist) { -return distns[dist]->getDimensions(); + return distns[dist]->getDimensions(); } // Reset the distribution for a given species so that all cells are deselected -void Landscape::resetDistribution(Species *pSp) { -// CURRENTLY WORKS FOR FIRST SPECIES ONLY ... -distns[0]->resetDistribution(); +void Landscape::resetDistribution(Species* pSp) { + // CURRENTLY WORKS FOR FIRST SPECIES ONLY ... + distns[0]->resetDistribution(); } //--------------------------------------------------------------------------- @@ -2013,23 +2020,23 @@ distns[0]->resetDistribution(); // Initialisation cell functions int Landscape::initCellCount(void) { -return (int)initcells.size(); + return (int)initcells.size(); } -void Landscape::addInitCell(int x,int y) { -initcells.push_back(new DistCell(x,y)); +void Landscape::addInitCell(int x, int y) { + initcells.push_back(new DistCell(x, y)); } locn Landscape::getInitCell(int ix) { -return initcells[ix]->getLocn(); + return initcells[ix]->getLocn(); } void Landscape::clearInitCells(void) { -int ncells = (int)initcells.size(); -for (int i = 0; i < ncells; i++) { - delete initcells[i]; -} -initcells.clear(); + int ncells = (int)initcells.size(); + for (int i = 0; i < ncells; i++) { + delete initcells[i]; + } + initcells.clear(); } //--------------------------------------------------------------------------- @@ -2037,24 +2044,24 @@ initcells.clear(); // Read landscape file(s) // Returns error code or zero if read correctly -int Landscape::readLandscape(int fileNum,string habfile,string pchfile,string costfile) +int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string costfile) { -// fileNum == 0 for (first) habitat file and optional patch file -// fileNum > 0 for subsequent habitat files under the %cover option + // fileNum == 0 for (first) habitat file and optional patch file + // fileNum > 0 for subsequent habitat files under the %cover option #if RS_RCPP -wstring header; + wstring header; #else -string header; + string header; #endif -int h,seq,p,habnodata; -int pchnodata = 0; -int ncols,nrows; -float hfloat,pfloat; -Patch *pPatch; -simParams sim = paramsSim->getSim(); + int h, seq, p, habnodata; + int pchnodata = 0; + int ncols, nrows; + float hfloat, pfloat; + Patch* pPatch; + simParams sim = paramsSim->getSim(); -if (fileNum < 0) return 19; + if (fileNum < 0) return 19; #if RS_RCPP wifstream hfile; // habitat file input stream @@ -2063,43 +2070,43 @@ if (fileNum < 0) return 19; ifstream hfile; // habitat file input stream ifstream pfile; // patch file input stream #endif -initParams init = paramsInit->getInit(); + initParams init = paramsInit->getInit(); -// open habitat file and optionally also patch file + // open habitat file and optionally also patch file #if !RS_RCPP || RSWIN64 -hfile.open(habfile.c_str()); + hfile.open(habfile.c_str()); #else -hfile.open(habfile, std::ios::binary); -if(landraster.utf) { - // apply BOM-sensitive UTF-16 facet - hfile.imbue(std::locale(hfile.getloc(), new std::codecvt_utf16)); -} + hfile.open(habfile, std::ios::binary); + if (landraster.utf) { + // apply BOM-sensitive UTF-16 facet + hfile.imbue(std::locale(hfile.getloc(), new std::codecvt_utf16)); + } #endif -if (!hfile.is_open()) return 11; -if (fileNum == 0) { - if (patchModel) { + if (!hfile.is_open()) return 11; + if (fileNum == 0) { + if (patchModel) { #if !RS_RCPP || RSWIN64 - pfile.open(pchfile.c_str()); + pfile.open(pchfile.c_str()); #else - pfile.open(pchfile, std::ios::binary); - if(patchraster.utf) { - // apply BOM-sensitive UTF-16 facet - pfile.imbue(std::locale(pfile.getloc(), new std::codecvt_utf16)); - } + pfile.open(pchfile, std::ios::binary); + if (patchraster.utf) { + // apply BOM-sensitive UTF-16 facet + pfile.imbue(std::locale(pfile.getloc(), new std::codecvt_utf16)); + } #endif - if (!pfile.is_open()) { - hfile.close(); hfile.clear(); - return 12; + if (!pfile.is_open()) { + hfile.close(); hfile.clear(); + return 12; + } } } -} -// read landscape data from header records of habitat file -// NB headers of all files have already been compared -double tmpresol; -hfile >> header >> ncols >> header >> nrows >> header >> minEast >> header >> minNorth - >> header >> tmpresol >> header >> habnodata; -resol = (int) tmpresol; + // read landscape data from header records of habitat file + // NB headers of all files have already been compared + double tmpresol; + hfile >> header >> ncols >> header >> nrows >> header >> minEast >> header >> minNorth + >> header >> tmpresol >> header >> habnodata; + resol = (int)tmpresol; #if RS_RCPP if (!hfile.good()) { @@ -2115,70 +2122,71 @@ resol = (int) tmpresol; } #endif -dimX = ncols; dimY = nrows; minX = maxY = 0; maxX = dimX-1; maxY = dimY-1; -if (fileNum == 0) { - // set initialisation limits to landscape limits - init.minSeedX = init.minSeedY = 0; - init.maxSeedX = maxX; init.maxSeedY = maxY; - paramsInit->setInit(init); -} - -if (fileNum == 0) { - if (patchModel) { - for (int i = 0; i < 5; i++) pfile >> header >> pfloat; - pfile >> header >> pchnodata; + dimX = ncols; dimY = nrows; minX = maxY = 0; maxX = dimX - 1; maxY = dimY - 1; + if (fileNum == 0) { + // set initialisation limits to landscape limits + init.minSeedX = init.minSeedY = 0; + init.maxSeedX = maxX; init.maxSeedY = maxY; + paramsInit->setInit(init); } + + if (fileNum == 0) { + if (patchModel) { + for (int i = 0; i < 5; i++) pfile >> header >> pfloat; + pfile >> header >> pchnodata; + } #if RS_RCPP - if (!pfile.good()) { - // corrupt file stream - StreamErrorR(pchfile); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 135; - } + if (!pfile.good()) { + // corrupt file stream + StreamErrorR(pchfile); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 135; + } #endif - setCellArray(); -} + setCellArray(); + } -// set up bad float values to ensure that valid values are read -float badhfloat = -9.0; if (habnodata == -9) badhfloat = -99.0; -float badpfloat = -9.0; if (pchnodata == -9) badpfloat = -99.0; + // set up bad float values to ensure that valid values are read + float badhfloat = -9.0; if (habnodata == -9) badhfloat = -99.0; + float badpfloat = -9.0; if (pchnodata == -9) badpfloat = -99.0; -seq = 0; // initial sequential patch landscape -p = 0; // initial patch number for cell-based landscape -// create patch 0 - the matrix patch (even if there is no matrix) -if (fileNum == 0) newPatch(seq++,p++); + seq = 0; // initial sequential patch landscape + p = 0; // initial patch number for cell-based landscape + // create patch 0 - the matrix patch (even if there is no matrix) + if (fileNum == 0) newPatch(seq++, p++); -switch (rasterType) { + switch (rasterType) { -case 0: // raster with habitat codes - 100% habitat each cell - if (fileNum > 0) return 19; // error condition - should not occur - for (int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { - hfloat = badhfloat; + case 0: // raster with habitat codes - 100% habitat each cell + if (fileNum > 0) return 19; // error condition - should not occur + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + hfloat = badhfloat; #if RS_RCPP - if(hfile >> hfloat) { + if (hfile >> hfloat) { #else - hfile >> hfloat; + hfile >> hfloat; #endif - h = (int)hfloat; - if (patchModel) { - pfloat = badpfloat; + h = (int)hfloat; + if (patchModel) { + pfloat = badpfloat; #if RS_RCPP - if(pfile >> pfloat) { + if (pfile >> pfloat) { #else - pfile >> pfloat; + pfile >> pfloat; #endif p = (int)pfloat; #if RS_RCPP - } else { + } + else { // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif StreamErrorR(pchfile); hfile.close(); hfile.clear(); @@ -2187,100 +2195,101 @@ case 0: // raster with habitat codes - 100% habitat each cell return 132; } #endif - } + } #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR(habfile); - hfile.close(); - hfile.clear(); - if (patchModel) { - pfile.close(); - pfile.clear(); } - return 135; + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR(habfile); + hfile.close(); + hfile.clear(); + if (patchModel) { + pfile.close(); + pfile.clear(); } + return 135; + } #endif #if RSDEBUG -//DebugGUI(("Landscape::readLandscape(): x=" + Int2Str(x) + " y=" + Int2Str(y) -// + " h=" + Int2Str(h) + " p=" + Int2Str(p) -//).c_str()); + //DebugGUI(("Landscape::readLandscape(): x=" + Int2Str(x) + " y=" + Int2Str(y) + // + " h=" + Int2Str(h) + " p=" + Int2Str(p) + //).c_str()); #endif - if (h == habnodata) - addNewCellToLand(x,y,-1); // add cell only to landscape - else { + if (h == habnodata) + addNewCellToLand(x, y, -1); // add cell only to landscape + else { - // THERE IS AN ANOMALY HERE - CURRENTLY HABITAT 0 IS OK FOR GUI VERSION BUT - // NOT ALLOWED FOR BATCH VERSION (HABITATS MUST BE 1...n) - // SHOULD WE MAKE THE TWO VERSIONS AGREE? ... + // THERE IS AN ANOMALY HERE - CURRENTLY HABITAT 0 IS OK FOR GUI VERSION BUT + // NOT ALLOWED FOR BATCH VERSION (HABITATS MUST BE 1...n) + // SHOULD WE MAKE THE TWO VERSIONS AGREE? ... - if (h < 0 || (sim.batchMode && (h < 1 || h > nHabMax))) { - // invalid habitat code - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "Found invalid habitat code." << std::endl; - #endif - hfile.close(); hfile.clear(); - if (patchModel) { - pfile.close(); pfile.clear(); - } - return 13; + if (h < 0 || (sim.batchMode && (h < 1 || h > nHabMax))) { + // invalid habitat code +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found invalid habitat code." << std::endl; +#endif + hfile.close(); hfile.clear(); + if (patchModel) { + pfile.close(); pfile.clear(); } - else { - addHabCode(h); - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code - #if RS_RCPP && !R_CMD - if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; - else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; - #endif - hfile.close(); hfile.clear(); - pfile.close(); pfile.clear(); - return 14; - } - if (p == 0) { // cell is in the matrix - addNewCellToPatch(0,x,y,h); + return 13; + } + else { + addHabCode(h); + if (patchModel) { + if (p < 0 || p == pchnodata) { // invalid patch code +#if RS_RCPP && !R_CMD + if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; +#endif + hfile.close(); hfile.clear(); + pfile.close(); pfile.clear(); + return 14; + } + if (p == 0) { // cell is in the matrix + addNewCellToPatch(0, x, y, h); + } + else { + if (existsPatch(p)) { + pPatch = findPatch(p); + addNewCellToPatch(pPatch, x, y, h); + // addNewCellToPatch(findPatch(p),x,y,h); } else { - if (existsPatch(p)) { - pPatch = findPatch(p); - addNewCellToPatch(pPatch,x,y,h); -// addNewCellToPatch(findPatch(p),x,y,h); - } - else { - pPatch = newPatch(seq++,p); - addNewCellToPatch(pPatch,x,y,h); - } + pPatch = newPatch(seq++, p); + addNewCellToPatch(pPatch, x, y, h); } } - else { // cell-based model - // add cell to landscape (patches created later) - addNewCellToLand(x,y,h); - } + } + else { // cell-based model + // add cell to landscape (patches created later) + addNewCellToLand(x, y, h); } } } - } + } + } #if RS_RCPP - hfile >> hfloat; - if (!hfile.eof()) EOFerrorR(habfile); - if (patchModel) - { - pfile >> pfloat; - if (!pfile.eof()) EOFerrorR(pchfile); - } +hfile >> hfloat; +if (!hfile.eof()) EOFerrorR(habfile); +if (patchModel) +{ + pfile >> pfloat; + if (!pfile.eof()) EOFerrorR(pchfile); +} #endif - break; +break; case 1: // multiple % cover - for (int y = dimY-1; y >= 0; y--) { + for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { hfloat = badhfloat; #if RS_RCPP - if(hfile >> hfloat) { + if (hfile >> hfloat) { #else hfile >> hfloat; #endif @@ -2289,24 +2298,25 @@ case 1: // multiple % cover if (patchModel) { pfloat = badpfloat; #if RS_RCPP - if(pfile >> pfloat) { + if (pfile >> pfloat) { #else pfile >> pfloat; #endif p = (int)pfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR(pchfile); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 135; } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR(pchfile); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 135; + } #endif } //end if patchmodel @@ -2314,85 +2324,86 @@ case 1: // multiple % cover //MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) // + " p=" + Int2Str(p)).c_str()); #endif - if (h == habnodata) { - addNewCellToLand(x,y,-1); // add cell only to landscape + if (h == habnodata) { + addNewCellToLand(x, y, -1); // add cell only to landscape + } + else { + if (hfloat < 0.0 || hfloat > 100.0) { // invalid cover score +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found invalid habitat cover score." << std::endl; +#endif + hfile.close(); hfile.clear(); + if (patchModel) { + pfile.close(); pfile.clear(); + } + return 17; } else { - if (hfloat < 0.0 || hfloat > 100.0) { // invalid cover score - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "Found invalid habitat cover score." << std::endl; - #endif - hfile.close(); hfile.clear(); - if (patchModel) { + if (patchModel) { + if (p < 0 || p == pchnodata) { // invalid patch code +#if RS_RCPP && !R_CMD + if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; +#endif + hfile.close(); hfile.clear(); pfile.close(); pfile.clear(); + return 14; } - return 17; - } - else { - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code - #if RS_RCPP && !R_CMD - if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; - else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; - #endif - hfile.close(); hfile.clear(); - pfile.close(); pfile.clear(); - return 14; - } - if (p == 0) { // cell is in the matrix - addNewCellToPatch(0,x,y,hfloat); + if (p == 0) { // cell is in the matrix + addNewCellToPatch(0, x, y, hfloat); + } + else { + if (existsPatch(p)) { + pPatch = findPatch(p); + addNewCellToPatch(pPatch, x, y, hfloat); + // addNewCellToPatch(findPatch(p),x,y,hfloat); } else { - if (existsPatch(p)) { - pPatch = findPatch(p); - addNewCellToPatch(pPatch,x,y,hfloat); -// addNewCellToPatch(findPatch(p),x,y,hfloat); - } - else { - pPatch = newPatch(seq++,p); - addNewCellToPatch(pPatch,x,y,hfloat); - } + pPatch = newPatch(seq++, p); + addNewCellToPatch(pPatch, x, y, hfloat); } } - else { // cell-based model - // add cell to landscape (patches created later) - addNewCellToLand(x,y,hfloat); - } + } + else { // cell-based model + // add cell to landscape (patches created later) + addNewCellToLand(x, y, hfloat); } } } - else { // additional habitat cover layers - if (h != habnodata) { - if (hfloat < 0.0 || hfloat > 100.0) { // invalid cover score - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "Found invalid habitat cover score." << std::endl; - #endif - hfile.close(); hfile.clear(); - if (patchModel) { - pfile.close(); pfile.clear(); - } - return 17; - } - else { - cells[y][x]->setHabitat(hfloat); - } - } // end of h != habnodata } -#if RS_RCPP - } else { // couldn't read from hfile - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR(habfile); - hfile.close(); - hfile.clear(); +else { // additional habitat cover layers + if (h != habnodata) { + if (hfloat < 0.0 || hfloat > 100.0) { // invalid cover score +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found invalid habitat cover score." << std::endl; +#endif + hfile.close(); hfile.clear(); if (patchModel) { - pfile.close(); - pfile.clear(); + pfile.close(); pfile.clear(); } - return 133; + return 17; + } + else { + cells[y][x]->setHabitat(hfloat); } + } // end of h != habnodata +} +#if RS_RCPP + } +else { // couldn't read from hfile + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR(habfile); + hfile.close(); + hfile.clear(); + if (patchModel) { + pfile.close(); + pfile.clear(); + } + return 133; +} #endif } @@ -2411,105 +2422,107 @@ case 1: // multiple % cover case 2: // habitat quality if (fileNum > 0) return 19; // error condition - should not occur - for (int y = dimY-1; y >= 0; y--) { + for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { hfloat = badhfloat; #if RS_RCPP - if(hfile >> hfloat) { + if (hfile >> hfloat) { #else hfile >> hfloat; #endif h = (int)hfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR(habfile); - hfile.close(); - hfile.clear(); - if (patchModel) { - pfile.close(); - pfile.clear(); - } - return 134; } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - if (patchModel) { - pfloat = badpfloat; + StreamErrorR(habfile); + hfile.close(); + hfile.clear(); + if (patchModel) { + pfile.close(); + pfile.clear(); + } + return 134; + } +#endif + if (patchModel) { + pfloat = badpfloat; #if RS_RCPP - if(pfile >> pfloat) { + if (pfile >> pfloat) { #else - pfile >> pfloat; + pfile >> pfloat; #endif - p = (int)pfloat; + p = (int)pfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR(pchfile); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 135; - } + } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - } + StreamErrorR(pchfile); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 135; + } +#endif + } #if RSDEBUG -//MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) -// + " p=" + Int2Str(p)).c_str()); + //MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) + // + " p=" + Int2Str(p)).c_str()); #endif - if (h == habnodata) { - addNewCellToLand(x,y,-1); // add cell only to landscape + if (h == habnodata) { + addNewCellToLand(x, y, -1); // add cell only to landscape + } + else { + if (hfloat < 0.0 || hfloat > 100.0) { // invalid quality score +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found invalid habitat quality score." << std::endl; +#endif + hfile.close(); hfile.clear(); + if (patchModel) { + pfile.close(); pfile.clear(); } - else { - if (hfloat < 0.0 || hfloat > 100.0) { // invalid quality score - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "Found invalid habitat quality score." << std::endl; - #endif + return 17; + } + else { + if (patchModel) { + if (p < 0 || p == pchnodata) { // invalid patch code +#if RS_RCPP && !R_CMD + if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; +#endif hfile.close(); hfile.clear(); - if (patchModel) { - pfile.close(); pfile.clear(); - } - return 17; + pfile.close(); pfile.clear(); + return 14; + } + if (p == 0) { // cell is in the matrix + addNewCellToPatch(0, x, y, hfloat); } else { - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code - #if RS_RCPP && !R_CMD - if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; - else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; - #endif - hfile.close(); hfile.clear(); - pfile.close(); pfile.clear(); - return 14; - } - if (p == 0) { // cell is in the matrix - addNewCellToPatch(0,x,y,hfloat); - } - else { - if (existsPatch(p)) { - pPatch = findPatch(p); - addNewCellToPatch(pPatch,x,y,hfloat); -// addNewCellToPatch(findPatch(p),x,y,hfloat); - } - else { - addPatchNum(p); - pPatch = newPatch(seq++,p); - addNewCellToPatch(pPatch,x,y,hfloat); - } - } + if (existsPatch(p)) { + pPatch = findPatch(p); + addNewCellToPatch(pPatch, x, y, hfloat); + // addNewCellToPatch(findPatch(p),x,y,hfloat); } - else { // cell-based model - // add cell to landscape (patches created later) - addNewCellToLand(x,y,hfloat); + else { + addPatchNum(p); + pPatch = newPatch(seq++, p); + addNewCellToPatch(pPatch, x, y, hfloat); } } } + else { // cell-based model + // add cell to landscape (patches created later) + addNewCellToLand(x, y, hfloat); + } + } + } } } #if RS_RCPP @@ -2525,19 +2538,19 @@ case 2: // habitat quality default: break; -} // end switch(rasterType) + } // end switch(rasterType) -if (hfile.is_open()) { hfile.close(); hfile.clear(); } -if (pfile.is_open()) { pfile.close(); pfile.clear(); } + if (hfile.is_open()) { hfile.close(); hfile.clear(); } + if (pfile.is_open()) { pfile.close(); pfile.clear(); } -if (sim.batchMode) { - if (costfile != "NULL") { - int retcode = readCosts(costfile); - if (retcode < 0) return 54; + if (sim.batchMode) { + if (costfile != "NULL") { + int retcode = readCosts(costfile); + if (retcode < 0) return 54; + } } -} -return 0; + return 0; } @@ -2556,25 +2569,25 @@ int Landscape::readCosts(string fname) ifstream costs; // cost map file input stream #endif -//int hc,maxYcost,maxXcost,NODATACost,hab; -int hc,maxYcost,maxXcost,NODATACost; -float minLongCost, minLatCost; int resolCost; -float fcost; + //int hc,maxYcost,maxXcost,NODATACost,hab; + int hc, maxYcost, maxXcost, NODATACost; + float minLongCost, minLatCost; int resolCost; + float fcost; #if RS_RCPP -wstring header; + wstring header; #else -string header; + string header; #endif -Cell *pCell; + Cell* pCell; #if !RS_RCPP -simView v = paramsSim->getViews(); + simView v = paramsSim->getViews(); #endif -int maxcost = 0; + int maxcost = 0; #if RSDEBUG #if BATCH -//DEBUGLOG << "Landscape::readCosts(): fname=" << fname << endl; + //DEBUGLOG << "Landscape::readCosts(): fname=" << fname << endl; #endif #endif // open cost file @@ -2582,21 +2595,21 @@ int maxcost = 0; costs.open(fname.c_str()); #else costs.open(fname, std::ios::binary); - if(costsraster.utf) { + if (costsraster.utf) { // apply BOM-sensitive UTF-16 facet costs.imbue(std::locale(costs.getloc(), new std::codecvt_utf16)); } #endif -//if (!costs.is_open()) { -// MessageDlg("COSTS IS NOT OPEN!!!!!", -// mtError, TMsgDlgButtons() << mbRetry,0); -//} -//else { -// MessageDlg("Costs is open!", -// mtError, TMsgDlgButtons() << mbRetry,0); -//} -// read headers and check that they correspond to the landscape ones -costs >> header; + //if (!costs.is_open()) { + // MessageDlg("COSTS IS NOT OPEN!!!!!", + // mtError, TMsgDlgButtons() << mbRetry,0); + //} + //else { + // MessageDlg("Costs is open!", + // mtError, TMsgDlgButtons() << mbRetry,0); + //} + // read headers and check that they correspond to the landscape ones + costs >> header; #if RS_RCPP if (!costs.good()) { // corrupt file stream @@ -2609,75 +2622,76 @@ costs >> header; #else if (header != "ncols" && header != "NCOLS") { #endif -// MessageDlg("The selected file is not a raster.", -// MessageDlg("Header problem in import_CostsLand()", -// mtError, TMsgDlgButtons() << mbRetry,0); - costs.close(); costs.clear(); - return -1; -} -double tmpresolCost; -costs >> maxXcost >> header >> maxYcost >> header >> minLongCost; -costs >> header >> minLatCost >> header >> tmpresolCost >> header >> NODATACost; -resolCost = (int) tmpresolCost; + // MessageDlg("The selected file is not a raster.", + // MessageDlg("Header problem in import_CostsLand()", + // mtError, TMsgDlgButtons() << mbRetry,0); + costs.close(); costs.clear(); + return -1; + } + double tmpresolCost; + costs >> maxXcost >> header >> maxYcost >> header >> minLongCost; + costs >> header >> minLatCost >> header >> tmpresolCost >> header >> NODATACost; + resolCost = (int)tmpresolCost; #if !RS_RCPP -MemoLine("Loading costs map. Please wait..."); + MemoLine("Loading costs map. Please wait..."); #endif -for (int y = maxYcost - 1; y > -1; y--){ - for (int x = 0; x < maxXcost; x++){ + for (int y = maxYcost - 1; y > -1; y--) { + for (int x = 0; x < maxXcost; x++) { #if RS_RCPP - if(costs >> fcost) { + if (costs >> fcost) { #else - costs >> fcost; + costs >> fcost; #endif - hc = (int)fcost; // read as float and convert to int + hc = (int)fcost; // read as float and convert to int #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR(fname); - costs.close(); - costs.clear(); - return -181; - } + } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR(fname); + costs.close(); + costs.clear(); + return -181; + } #endif - if ( hc < 1 && hc != NODATACost ) { + if (hc < 1 && hc != NODATACost) { #if RSDEBUG #if BATCH -// DEBUGLOG << "Landscape::readCosts(): x=" << x << " y=" << y -// << " fcost=" << fcost << " hc=" << hc -// << endl; + // DEBUGLOG << "Landscape::readCosts(): x=" << x << " y=" << y + // << " fcost=" << fcost << " hc=" << hc + // << endl; #endif #endif #if RS_RCPP && !R_CMD - Rcpp::Rcout << "Cost map my only contain values of 1 or higher, but found " << fcost << "." << endl; + Rcpp::Rcout << "Cost map my only contain values of 1 or higher, but found " << fcost << "." << endl; #endif - // error - zero / negative cost not allowed + // error - zero / negative cost not allowed // MessageDlg("Error in the costs map file : zero or negative cost detected." // , mtError, TMsgDlgButtons() << mbOK,0); - costs.close(); costs.clear(); - return -999; - } - pCell = findCell(x,y); - if (pCell != 0) { // not no-data cell - pCell->setCost(hc); - if (hc > maxcost) maxcost = hc; + costs.close(); costs.clear(); + return -999; + } + pCell = findCell(x, y); + if (pCell != 0) { // not no-data cell + pCell->setCost(hc); + if (hc > maxcost) maxcost = hc; + } } } -} #if RS_RCPP - costs >> fcost; - if (costs.eof()) { - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "Costs map loaded." << endl; - #endif - } - else EOFerrorR(fname); +costs >> fcost; +if (costs.eof()) { +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "Costs map loaded." << endl; +#endif +} +else EOFerrorR(fname); #else - MemoLine("Costs map loaded."); +MemoLine("Costs map loaded."); #endif costs.close(); costs.clear(); @@ -2690,63 +2704,63 @@ return maxcost; rasterdata CheckRasterFile(string fname) { -rasterdata r; -string header; -int inint; -ifstream infile; + rasterdata r; + string header; + int inint; + ifstream infile; -r.ok = true; -r.errors = r.ncols = r.nrows = r.cellsize = 0; -r.xllcorner = r.yllcorner = 0.0; + r.ok = true; + r.errors = r.ncols = r.nrows = r.cellsize = 0; + r.xllcorner = r.yllcorner = 0.0; -infile.open(fname.c_str()); -if (infile.is_open()) { - infile >> header >> r.ncols; + infile.open(fname.c_str()); + if (infile.is_open()) { + infile >> header >> r.ncols; #if RSDEBUG -DebugGUI(("CheckRasterFile(): header=" + header + " r.ncols=" + Int2Str(r.ncols) - ).c_str()); + DebugGUI(("CheckRasterFile(): header=" + header + " r.ncols=" + Int2Str(r.ncols) + ).c_str()); #endif - if (header != "ncols" && header != "NCOLS") r.errors++; - infile >> header >> r.nrows; + if (header != "ncols" && header != "NCOLS") r.errors++; + infile >> header >> r.nrows; #if RSDEBUG -DebugGUI(("CheckRasterFile(): header=" + header + " r.nrows=" + Int2Str(r.nrows) - ).c_str()); + DebugGUI(("CheckRasterFile(): header=" + header + " r.nrows=" + Int2Str(r.nrows) + ).c_str()); #endif - if (header != "nrows" && header != "NROWS") r.errors++; - infile >> header >> r.xllcorner; + if (header != "nrows" && header != "NROWS") r.errors++; + infile >> header >> r.xllcorner; #if RSDEBUG -DebugGUI(("CheckRasterFile(): header=" + header + " r.xllcorner=" + Float2Str(r.xllcorner) - ).c_str()); + DebugGUI(("CheckRasterFile(): header=" + header + " r.xllcorner=" + Float2Str(r.xllcorner) + ).c_str()); #endif - if (header != "xllcorner" && header != "XLLCORNER") r.errors++; - infile >> header >> r.yllcorner; + if (header != "xllcorner" && header != "XLLCORNER") r.errors++; + infile >> header >> r.yllcorner; #if RSDEBUG -DebugGUI(("CheckRasterFile(): header=" + header + " r.yllcorner=" + Float2Str(r.yllcorner) - ).c_str()); + DebugGUI(("CheckRasterFile(): header=" + header + " r.yllcorner=" + Float2Str(r.yllcorner) + ).c_str()); #endif - if (header != "yllcorner" && header != "YLLCORNER") r.errors++; - infile >> header >> r.cellsize; + if (header != "yllcorner" && header != "YLLCORNER") r.errors++; + infile >> header >> r.cellsize; #if RSDEBUG -DebugGUI(("CheckRasterFile(): header=" + header + " r.cellsize=" + Int2Str(r.cellsize) - ).c_str()); + DebugGUI(("CheckRasterFile(): header=" + header + " r.cellsize=" + Int2Str(r.cellsize) + ).c_str()); #endif - if (header != "cellsize" && header != "CELLSIZE") r.errors++; - infile >> header >> inint; + if (header != "cellsize" && header != "CELLSIZE") r.errors++; + infile >> header >> inint; #if RSDEBUG -DebugGUI(("CheckRasterFile(): header=" + header + " inint=" + Int2Str(inint) - ).c_str()); + DebugGUI(("CheckRasterFile(): header=" + header + " inint=" + Int2Str(inint) + ).c_str()); #endif - if (header != "NODATA_value" && header != "NODATA_VALUE") r.errors++; - infile.close(); + if (header != "NODATA_value" && header != "NODATA_VALUE") r.errors++; + infile.close(); + infile.clear(); + if (r.errors > 0) r.ok = false; + } + else { + r.ok = false; r.errors = -111; + } infile.clear(); - if (r.errors > 0) r.ok = false; -} -else { - r.ok = false; r.errors = -111; -} -infile.clear(); -return r; + return r; } //--------------------------------------------------------------------------- @@ -2756,74 +2770,74 @@ return r; // Create & initialise connectivity matrix void Landscape::createConnectMatrix(void) { -if (connectMatrix != 0) deleteConnectMatrix(); -int npatches = (int)patches.size(); + if (connectMatrix != 0) deleteConnectMatrix(); + int npatches = (int)patches.size(); #if RSDEBUG -//DEBUGLOG << "Landscape::createConnectMatrix(): npatches=" << npatches << endl; + //DEBUGLOG << "Landscape::createConnectMatrix(): npatches=" << npatches << endl; #endif -connectMatrix = new int *[npatches]; -for (int i = 0; i < npatches; i++) { - connectMatrix[i] = new int[npatches]; - for (int j = 0; j < npatches; j++) connectMatrix[i][j] = 0; -} + connectMatrix = new int* [npatches]; + for (int i = 0; i < npatches; i++) { + connectMatrix[i] = new int[npatches]; + for (int j = 0; j < npatches; j++) connectMatrix[i][j] = 0; + } } // Re-initialise connectivity matrix void Landscape::resetConnectMatrix(void) { -if (connectMatrix != 0) { - int npatches = (int)patches.size(); - for (int i = 0; i < npatches; i++) { - for (int j = 0; j < npatches; j++) connectMatrix[i][j] = 0; + if (connectMatrix != 0) { + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) { + for (int j = 0; j < npatches; j++) connectMatrix[i][j] = 0; + } } } -} // Increment connectivity count between two specified patches -void Landscape::incrConnectMatrix(int p0,int p1) { -int npatches = (int)patches.size(); -if (connectMatrix == 0 || p0 < 0 || p0 >= npatches || p1 < 0 || p1 >= npatches) return; -connectMatrix[p0][p1]++; +void Landscape::incrConnectMatrix(int p0, int p1) { + int npatches = (int)patches.size(); + if (connectMatrix == 0 || p0 < 0 || p0 >= npatches || p1 < 0 || p1 >= npatches) return; + connectMatrix[p0][p1]++; } // Delete connectivity matrix void Landscape::deleteConnectMatrix(void) { -if (connectMatrix != 0) { - int npatches = (int)patches.size(); - for (int j = 0; j < npatches; j++) { - if (connectMatrix[j] != 0) - delete connectMatrix[j]; + if (connectMatrix != 0) { + int npatches = (int)patches.size(); + for (int j = 0; j < npatches; j++) { + if (connectMatrix[j] != 0) + delete connectMatrix[j]; + } + delete[] connectMatrix; + connectMatrix = 0; } - delete[] connectMatrix; - connectMatrix = 0; -} } // Write connectivity file headers bool Landscape::outConnectHeaders(int option) { -if (option == -999) { // close the file - if (outConnMat.is_open()) outConnMat.close(); - outConnMat.clear(); - return true; -} + if (option == -999) { // close the file + if (outConnMat.is_open()) outConnMat.close(); + outConnMat.clear(); + return true; + } -simParams sim = paramsSim->getSim(); + simParams sim = paramsSim->getSim(); -string name = paramsSim->getDir(2); -if (sim.batchMode) { - name += "Batch" + Int2Str(sim.batchNum) + "_"; - name += "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNum); -} -else - name += "Sim" + Int2Str(sim.simulation); -name += "_Connect.txt"; -outConnMat.open(name.c_str()); + string name = paramsSim->getDir(2); + if (sim.batchMode) { + name += "Batch" + Int2Str(sim.batchNum) + "_"; + name += "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNum); + } + else + name += "Sim" + Int2Str(sim.simulation); + name += "_Connect.txt"; + outConnMat.open(name.c_str()); -outConnMat << "Rep\tYear\tStartPatch\tEndPatch\tNinds" << endl; + outConnMat << "Rep\tYear\tStartPatch\tEndPatch\tNinds" << endl; -return outConnMat.is_open(); + return outConnMat.is_open(); } #if RS_RCPP @@ -2840,140 +2854,142 @@ void Landscape::outPathsHeaders(int rep, int option) string name = paramsSim->getDir(2); if (sim.batchMode) { name += "Batch" + Int2Str(sim.batchNum) - + "_Sim" + Int2Str(sim.simulation) - + "_Land" + Int2Str(landNum) - + "_Rep" + Int2Str(rep); - } else { + + "_Sim" + Int2Str(sim.simulation) + + "_Land" + Int2Str(landNum) + + "_Rep" + Int2Str(rep); + } + else { name += "Sim" + Int2Str(sim.simulation) - + "_Rep" + Int2Str(rep); + + "_Rep" + Int2Str(rep); } name += "_MovePaths.txt"; outMovePaths.open(name.c_str()); - if( outMovePaths.is_open() ){ + if (outMovePaths.is_open()) { outMovePaths << "Year\tIndID\tStep\tx\ty\tStatus" << endl; - }else{ - #if RSDEBUG + } + else { +#if RSDEBUG DEBUGLOG << "RunModel(): UNABLE TO OPEN MOVEMENT PATHS FILE" << endl; - #endif +#endif outMovePaths.clear(); } } } #endif -void Landscape::outConnect(int rep,int yr) +void Landscape::outConnect(int rep, int yr) { -int patchnum0,patchnum1; -int npatches = (int)patches.size(); -int *emigrants = new int[npatches]; // 1D array to hold emigrants from each patch -int *immigrants = new int[npatches]; // 1D array to hold immigrants to each patch + int patchnum0, patchnum1; + int npatches = (int)patches.size(); + int* emigrants = new int[npatches]; // 1D array to hold emigrants from each patch + int* immigrants = new int[npatches]; // 1D array to hold immigrants to each patch -for (int i = 0; i < npatches; i++) { - emigrants[i] = immigrants[i] = 0; -} + for (int i = 0; i < npatches; i++) { + emigrants[i] = immigrants[i] = 0; + } -for (int i = 0; i < npatches; i++) { - patchnum0 = patches[i]->getPatchNum(); - if (patchnum0 != 0) { - for (int j = 0; j < npatches; j++) { - patchnum1 = patches[j]->getPatchNum(); - if (patchnum1 != 0) { - emigrants[i] += connectMatrix[i][j]; - immigrants[j] += connectMatrix[i][j]; - if (connectMatrix[i][j] > 0) { - outConnMat << rep << "\t" << yr - << "\t" << patchnum0 << "\t" << patchnum1 - << "\t" << connectMatrix[i][j] << endl; + for (int i = 0; i < npatches; i++) { + patchnum0 = patches[i]->getPatchNum(); + if (patchnum0 != 0) { + for (int j = 0; j < npatches; j++) { + patchnum1 = patches[j]->getPatchNum(); + if (patchnum1 != 0) { + emigrants[i] += connectMatrix[i][j]; + immigrants[j] += connectMatrix[i][j]; + if (connectMatrix[i][j] > 0) { + outConnMat << rep << "\t" << yr + << "\t" << patchnum0 << "\t" << patchnum1 + << "\t" << connectMatrix[i][j] << endl; + } } } } } -} -for (int i = 0; i < npatches; i++) { - patchnum0 = patches[i]->getPatchNum(); - if (patchnum0 != 0) { - if (patches[i]->getK() > 0.0) - { // suitable patch - outConnMat << rep << "\t" << yr - << "\t" << patchnum0 << "\t-999\t" << emigrants[i] << endl; - outConnMat << rep << "\t" << yr - << "\t-999\t" << patchnum0 << "\t" << immigrants[i] << endl; + for (int i = 0; i < npatches; i++) { + patchnum0 = patches[i]->getPatchNum(); + if (patchnum0 != 0) { + if (patches[i]->getK() > 0.0) + { // suitable patch + outConnMat << rep << "\t" << yr + << "\t" << patchnum0 << "\t-999\t" << emigrants[i] << endl; + outConnMat << rep << "\t" << yr + << "\t-999\t" << patchnum0 << "\t" << immigrants[i] << endl; + } } } -} -delete[] emigrants; -delete[] immigrants; + delete[] emigrants; + delete[] immigrants; } //--------------------------------------------------------------------------- void Landscape::resetVisits(void) { -for(int y = dimY-1; y >= 0; y--){ - for (int x = 0; x < dimX; x++) { - if (cells[y][x] != 0) { // not a no-data cell - cells[y][x]->resetVisits(); + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (cells[y][x] != 0) { // not a no-data cell + cells[y][x]->resetVisits(); + } } } } -} // Save SMS path visits map to raster text file void Landscape::outVisits(int rep, int landNr) { -string name; -simParams sim = paramsSim->getSim(); + string name; + simParams sim = paramsSim->getSim(); -if (sim.batchMode) { - name = paramsSim->getDir(3) + if (sim.batchMode) { + name = paramsSim->getDir(3) #if RS_RCPP - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) - + "_Land" + Int2Str(landNr) + "_Rep" + Int2Str(rep) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + + "_Land" + Int2Str(landNr) + "_Rep" + Int2Str(rep) #else - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) - + "_land" + Int2Str(landNr) + "_rep" + Int2Str(rep) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + + "_land" + Int2Str(landNr) + "_rep" + Int2Str(rep) #endif -// + "_yr" + Int2Str(yr) - + "_Visits.txt"; -} -else { - name = paramsSim->getDir(3) - + "Sim" + Int2Str(sim.simulation) - + "_land" + Int2Str(landNr) + "_rep" + Int2Str(rep) -// + "_yr" + Int2Str(yr) - + "_Visits.txt"; -} -outvisits.open(name.c_str()); + // + "_yr" + Int2Str(yr) + + "_Visits.txt"; + } + else { + name = paramsSim->getDir(3) + + "Sim" + Int2Str(sim.simulation) + + "_land" + Int2Str(landNr) + "_rep" + Int2Str(rep) + // + "_yr" + Int2Str(yr) + + "_Visits.txt"; + } + outvisits.open(name.c_str()); -outvisits << "ncols " << dimX << endl; -outvisits << "nrows " << dimY << endl; -outvisits << "xllcorner " << minEast << endl; -outvisits << "yllcorner " << minNorth << endl; -outvisits << "cellsize " << resol << endl; -outvisits << "NODATA_value -9" << endl; + outvisits << "ncols " << dimX << endl; + outvisits << "nrows " << dimY << endl; + outvisits << "xllcorner " << minEast << endl; + outvisits << "yllcorner " << minNorth << endl; + outvisits << "cellsize " << resol << endl; + outvisits << "NODATA_value -9" << endl; -for (int y = dimY-1; y >= 0; y--) { + for (int y = dimY - 1; y >= 0; y--) { #if RSDEBUG -//DebugGUI(("Landscape::drawLandscape(): y=" + Int2Str(y) -// + " cells[y]=" + Int2Str((int)cells[y])).c_str()); + //DebugGUI(("Landscape::drawLandscape(): y=" + Int2Str(y) + // + " cells[y]=" + Int2Str((int)cells[y])).c_str()); #endif - for (int x = 0; x < dimX; x++) { - if (cells[y][x] == 0) { // no-data cell - outvisits << "-9 "; - } - else { - outvisits << cells[y][x]->getVisits() << " "; + for (int x = 0; x < dimX; x++) { + if (cells[y][x] == 0) { // no-data cell + outvisits << "-9 "; + } + else { + outvisits << cells[y][x]->getVisits() << " "; + } } + outvisits << endl; } - outvisits << endl; -} -outvisits.close(); outvisits.clear(); + outvisits.close(); outvisits.clear(); } //--------------------------------------------------------------------------- diff --git a/Landscape.h b/Landscape.h index a3d974d..c82dc7a 100644 --- a/Landscape.h +++ b/Landscape.h @@ -1,78 +1,78 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ -RangeShifter v2.0 Landscape -Implements the following classes: + /*------------------------------------------------------------------------------ -InitDist - Initial species distribution + RangeShifter v2.0 Landscape -Landscape - Landscape grid + Implements the following classes: -The Landscape is a rectangular array of Cells which are grouped together in -Patches. As far as the user is aware, the Landscape is either patch-based or -cell-based (having no Patches), but internally Patches are always present (they -each comprise only one Cell for a cell-based model). The grain of the Landscape -may be any positive integer, and is nominally in metres. + InitDist - Initial species distribution -The Landscape is either input from one or more text files in ArcGIS raster export -format, or it is generated artificially as a random or fractal binary array (in -which case, it must be cell-based). An input 'real' Landscape may hold within each -Cell either discrete habitat classes, or percent cover of habitat classes, or a -continuous quality index (1 to 100%). + Landscape - Landscape grid -The Landscape may be dynamic, in which case the user specifies a set of changes -to be applied at certain years during each simulation. The changes may be to -habitat only, patches only (if a patch-based model) or habitats and patches. -Although the changes must be supplied as entire habitat / patch files (which -must match the original Landscape in terms of cell size and extent), internally -they are recorded as lists of dynamic habitat and patch changes. + The Landscape is a rectangular array of Cells which are grouped together in + Patches. As far as the user is aware, the Landscape is either patch-based or + cell-based (having no Patches), but internally Patches are always present (they + each comprise only one Cell for a cell-based model). The grain of the Landscape + may be any positive integer, and is nominally in metres. -The initial species distribution is a rectangular array if distribution cells -(DistCell) covering the same spatial extent at the Landscape. Its grain may be -either that of the Landscape or an integer multiple of it. + The Landscape is either input from one or more text files in ArcGIS raster export + format, or it is generated artificially as a random or fractal binary array (in + which case, it must be cell-based). An input 'real' Landscape may hold within each + Cell either discrete habitat classes, or percent cover of habitat classes, or a + continuous quality index (1 to 100%). -The Landscape can record a list (in the vector initcells) of Cells or Patches -to be intialised, which are specified by the user in FormSeeding. This option is -available in the GUI version only. + The Landscape may be dynamic, in which case the user specifies a set of changes + to be applied at certain years during each simulation. The changes may be to + habitat only, patches only (if a patch-based model) or habitats and patches. + Although the changes must be supplied as entire habitat / patch files (which + must match the original Landscape in terms of cell size and extent), internally + they are recorded as lists of dynamic habitat and patch changes. -For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. -and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. -Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 + The initial species distribution is a rectangular array if distribution cells + (DistCell) covering the same spatial extent at the Landscape. Its grain may be + either that of the Landscape or an integer multiple of it. -Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + The Landscape can record a list (in the vector initcells) of Cells or Patches + to be intialised, which are specified by the user in FormSeeding. This option is + available in the GUI version only. -Last updated: 2 December 2021 by Steve Palmer -------------------------------------------------------------------------------*/ + For full details of RangeShifter, please see: + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. + and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial + eco-evolutionary dynamics and species’ responses to environmental changes. + Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 + + Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + + Last updated: 2 December 2021 by Steve Palmer + ------------------------------------------------------------------------------*/ #ifndef LandscapeH #define LandscapeH -//#include -//#include + //#include + //#include #include #include //#include @@ -98,7 +98,7 @@ using namespace std; // Initial species distribution -class InitDist{ +class InitDist { public: InitDist(Species*); ~InitDist(); @@ -124,15 +124,15 @@ class InitDist{ int // index no. of DistCell in cells vector ); locn getSelectedCell( // Return the co-ordinates of a specified initial distribution - // cell if it has been selected - // otherwise return negative co-ordinates + // cell if it has been selected + // otherwise return negative co-ordinates int // index no. of DistCell in cells vector ); locn getDimensions(void); void resetDistribution(void); private: - Species *pSpecies; // pointer to species + Species* pSpecies; // pointer to species int resol; // species distribution cell size (m) int maxX, maxY; // dimensions double minEast; // ) real world min co-ordinates @@ -147,19 +147,19 @@ class InitDist{ //--------------------------------------------------------------------------- -struct landParams { +struct landParams { bool patchModel; bool spDist; bool generated; bool dynamic; int landNum; int resol; int spResol; int nHab; int nHabMax; - int dimX,dimY,minX,minY,maxX,maxY; + int dimX, dimY, minX, minY, maxX, maxY; short rasterType; }; struct landData { - int resol; int dimX,dimY,minX,minY,maxX,maxY; + int resol; int dimX, dimY, minX, minY, maxX, maxY; }; struct genLandParams { bool fractal; bool continuous; - float minPct,maxPct; float propSuit; float hurst; int maxCells; + float minPct, maxPct; float propSuit; float hurst; int maxCells; }; struct landPix { int pix; float gpix; @@ -169,31 +169,31 @@ struct landOrigin { }; struct rasterHdr { bool ok; - int errors,ncols,nrows,cellsize; - double xllcorner,yllcorner; + int errors, ncols, nrows, cellsize; + double xllcorner, yllcorner; }; struct rasterdata { bool ok; - int errors,ncols,nrows,cellsize; - double xllcorner,yllcorner; + int errors, ncols, nrows, cellsize; + double xllcorner, yllcorner; #if RS_RCPP bool utf; #endif }; struct patchData { - Patch *pPatch; int patchNum,nCells; int x,y; + Patch* pPatch; int patchNum, nCells; int x, y; }; struct landChange { - int chgnum,chgyear; string habfile,pchfile,costfile; + int chgnum, chgyear; string habfile, pchfile, costfile; }; struct patchChange { int chgnum, x, y, oldpatch, newpatch; }; struct costChange { - int chgnum,x,y,oldcost,newcost; + int chgnum, x, y, oldcost, newcost; }; -class Landscape{ +class Landscape { public: Landscape(); ~Landscape(); @@ -231,7 +231,7 @@ class Landscape{ int getHabCode(int); void clearHabitats(void); void addColour(rgb); - void changeColour(int,rgb); + void changeColour(int, rgb); rgb getColour(int); int colourCount(void); @@ -334,7 +334,7 @@ class Landscape{ void deleteLandChanges(void); #if RS_RCPP && !R_CMD int readLandChange( - int, // change file number + int, // change file number bool, // change SMS costs? wifstream&, // habitat file stream wifstream&, // patch file stream @@ -390,7 +390,7 @@ class Landscape{ int // index no. of DistCell in cells vector ); locn getSelectedDistnCell( // Get co-ordinates of a specified cell in a specified initial distn - // Returns negative co-ordinates if the cell is not selected + // Returns negative co-ordinates if the cell is not selected int, // index no. of InitDist in distns vector int // index no. of DistCell in cells vector ); @@ -447,7 +447,7 @@ class Landscape{ int readLandscape( int, // fileNum == 0 for (first) habitat file and optional patch file - // fileNum > 0 for subsequent habitat files under the %cover option + // fileNum > 0 for subsequent habitat files under the %cover option string, // habitat file name string, // patch file name string // cost file name (may be NULL) @@ -470,7 +470,7 @@ class Landscape{ ); void resetVisits(void); - void outVisits(int,int); // save SMS path visits map to raster text file + void outVisits(int, int); // save SMS path visits map to raster text file private: bool generated; // artificially generated? @@ -486,10 +486,10 @@ class Landscape{ int spResol; // species distribution cell size (m) int nHab; // no. of habitats int nHabMax; // max. no. of habitats (used for batch input only) - int dimX,dimY; // dimensions - int minX,minY; // minimum available X and Y co-ordinates - int maxX,maxY; // maximum available X and Y co-ordinates - float minPct,maxPct; // min and max percentage of habitat in a cell + int dimX, dimY; // dimensions + int minX, minY; // minimum available X and Y co-ordinates + int maxX, maxY; // maximum available X and Y co-ordinates + float minPct, maxPct; // min and max percentage of habitat in a cell float propSuit; // proportion of suitable cells float hurst; // Hurst exponent int maxCells; // max. cells per patch (artificial landscapes) @@ -500,7 +500,7 @@ class Landscape{ // list of cells in the landscape // cells MUST be loaded in the sequence ascending x within descending y - Cell ***cells; + Cell*** cells; // list of patches in the landscape - can be in any sequence std::vector patches; @@ -527,16 +527,16 @@ class Landscape{ // patch connectivity matrix // indexed by [start patch seq num][end patch seq num] - int **connectMatrix; + int** connectMatrix; // global environmental stochasticity (epsilon) - float *epsGlobal; // pointer to time-series + float* epsGlobal; // pointer to time-series // patch and costs change matrices (temporary - used when reading dynamic landscape) // indexed by [descending y][x][period] // where there are three periods, 0=original 1=previous 2=current - int ***patchChgMatrix; - int ***costsChgMatrix; + int*** patchChgMatrix; + int*** costsChgMatrix; }; @@ -544,11 +544,11 @@ class Landscape{ // batch routine to check raster files before any Landscape has been initiated rasterdata CheckRasterFile(string); -extern paramGrad *paramsGrad; -extern paramStoch *paramsStoch; -extern paramInit *paramsInit; -extern paramSim *paramsSim; -extern RSrandom *pRandom; +extern paramGrad* paramsGrad; +extern paramStoch* paramsStoch; +extern paramInit* paramsInit; +extern paramSim* paramsSim; +extern RSrandom* pRandom; #if RSDEBUG extern ofstream DEBUGLOG; @@ -558,7 +558,7 @@ extern void DebugGUI(string); extern void MemoLine(string); #if RS_RCPP -extern rasterdata landraster,patchraster,spdistraster,costsraster; +extern rasterdata landraster, patchraster, spdistraster, costsraster; extern void EOFerrorR(string); extern void StreamErrorR(string); #endif diff --git a/Model.cpp b/Model.cpp index 9f26886..c14c7ce 100644 --- a/Model.cpp +++ b/Model.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Model.h" @@ -29,89 +29,89 @@ ofstream outPar; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #if RS_RCPP && !R_CMD -Rcpp::List RunModel(Landscape *pLandscape,int seqsim) +Rcpp::List RunModel(Landscape* pLandscape, int seqsim) #else -int RunModel(Landscape *pLandscape,int seqsim) +int RunModel(Landscape* pLandscape, int seqsim) #endif { -//int Nsuit,yr,totalInds; -int yr,totalInds; -//float gradval,gradmin,gradmax; -bool filesOK; -//int t0,t1; - -landParams ppLand = pLandscape->getLandParams(); -envGradParams grad = paramsGrad->getGradient(); -envStochParams env = paramsStoch->getStoch(); -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -//emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -initParams init = paramsInit->getInit(); -simParams sim = paramsSim->getSim(); -simView v = paramsSim->getViews(); - -//t0 = time(0); + //int Nsuit,yr,totalInds; + int yr, totalInds; + //float gradval,gradmin,gradmax; + bool filesOK; + //int t0,t1; + + landParams ppLand = pLandscape->getLandParams(); + envGradParams grad = paramsGrad->getGradient(); + envStochParams env = paramsStoch->getStoch(); + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + //emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + initParams init = paramsInit->getInit(); + simParams sim = paramsSim->getSim(); + simView v = paramsSim->getViews(); + + //t0 = time(0); #if RSDEBUG -landPix p = pLandscape->getLandPix(); -DEBUGLOG << "RunModel(): reps=" << sim.reps - << " ppLand.nHab=" << ppLand.nHab - << " p.pix=" << p.pix - << endl; -//DEBUGLOG << "RunModel(): random integers:"; -//for (int i = 0; i < 5; i++) { -// int rrrr = pRandom->IRandom(1000,2000); DEBUGLOG << " " << rrrr; -//} -DEBUGLOG << endl; -#endif - -if (!ppLand.generated) { - if (!ppLand.patchModel) { // cell-based landscape - // create patches for suitable cells, adding unsuitable cells to the matrix - // NB this is an overhead here, but is necessary in case the identity of - // suitable habitats has been changed from one simulation to another (GUI or batch) - // substantial time savings may result during simulation in certain landscapes - pLandscape->allocatePatches(pSpecies); - } - pComm = new Community(pLandscape); // set up community - // set up a sub-community associated with each patch (incl. the matrix) - pLandscape->updateCarryingCapacity(pSpecies,0,0); -// if (ppLand.rasterType <= 2 && ppLand.dmgLoaded) -// pLandscape->updateDamageIndices(); - patchData ppp; - int npatches = pLandscape->patchCount(); - for (int i = 0; i < npatches; i++) { - ppp = pLandscape->getPatchData(i); + landPix p = pLandscape->getLandPix(); + DEBUGLOG << "RunModel(): reps=" << sim.reps + << " ppLand.nHab=" << ppLand.nHab + << " p.pix=" << p.pix + << endl; + //DEBUGLOG << "RunModel(): random integers:"; + //for (int i = 0; i < 5; i++) { + // int rrrr = pRandom->IRandom(1000,2000); DEBUGLOG << " " << rrrr; + //} + DEBUGLOG << endl; +#endif + + if (!ppLand.generated) { + if (!ppLand.patchModel) { // cell-based landscape + // create patches for suitable cells, adding unsuitable cells to the matrix + // NB this is an overhead here, but is necessary in case the identity of + // suitable habitats has been changed from one simulation to another (GUI or batch) + // substantial time savings may result during simulation in certain landscapes + pLandscape->allocatePatches(pSpecies); + } + pComm = new Community(pLandscape); // set up community + // set up a sub-community associated with each patch (incl. the matrix) + pLandscape->updateCarryingCapacity(pSpecies, 0, 0); + // if (ppLand.rasterType <= 2 && ppLand.dmgLoaded) + // pLandscape->updateDamageIndices(); + patchData ppp; + int npatches = pLandscape->patchCount(); + for (int i = 0; i < npatches; i++) { + ppp = pLandscape->getPatchData(i); #if RSDEBUG -//DEBUGLOG << "RunModel(): i = " << i -// << " ppp.pPatch = " << ppp.pPatch << " ppp.patchNum = " << ppp.patchNum -// << endl; -#endif - pComm->addSubComm(ppp.pPatch,ppp.patchNum); // SET UP ALL SUB-COMMUNITIES -// if (i == 0 || ppp.pPatch->getK() > 0.0) { -// // SET UP SUB-COMMUNITY FOR MATRIX PATCH AND ANY PATCH HAVING NON-ZERO CARRYING CAPACITY -// pComm->addSubComm(ppp.pPatch,ppp.patchNum); -// } - } - if (init.seedType == 0 && init.freeType < 2 && init.initFrzYr > 0) { - // restrict available landscape to initialised region - pLandscape->setLandLimits(init.minSeedX,init.minSeedY, - init.maxSeedX,init.maxSeedY); - } - else { - pLandscape->resetLandLimits(); + //DEBUGLOG << "RunModel(): i = " << i + // << " ppp.pPatch = " << ppp.pPatch << " ppp.patchNum = " << ppp.patchNum + // << endl; +#endif + pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES + // if (i == 0 || ppp.pPatch->getK() > 0.0) { + // // SET UP SUB-COMMUNITY FOR MATRIX PATCH AND ANY PATCH HAVING NON-ZERO CARRYING CAPACITY + // pComm->addSubComm(ppp.pPatch,ppp.patchNum); + // } + } + if (init.seedType == 0 && init.freeType < 2 && init.initFrzYr > 0) { + // restrict available landscape to initialised region + pLandscape->setLandLimits(init.minSeedX, init.minSeedY, + init.maxSeedX, init.maxSeedY); + } + else { + pLandscape->resetLandLimits(); + } } -} #if RS_RCPP && !R_CMD -Rcpp::List list_outPop; + Rcpp::List list_outPop; #endif -// Loop through replicates -for (int rep = 0; rep < sim.reps; rep++) { + // Loop through replicates + for (int rep = 0; rep < sim.reps; rep++) { #if RSDEBUG -DEBUGLOG << endl << "RunModel(): starting simulation=" << sim.simulation << " rep=" << rep << endl; + DEBUGLOG << endl << "RunModel(): starting simulation=" << sim.simulation << " rep=" << rep << endl; #endif #if RS_RCPP && !R_CMD Rcpp::Rcout << endl << "starting replicate " << rep << endl; @@ -121,768 +121,768 @@ DEBUGLOG << endl << "RunModel(): starting simulation=" << sim.simulation << " re #endif #endif - MemoLine(("Running replicate " + Int2Str(rep) + "...").c_str()); + MemoLine(("Running replicate " + Int2Str(rep) + "...").c_str()); - if (sim.saveVisits && !ppLand.generated) { - pLandscape->resetVisits(); - } + if (sim.saveVisits && !ppLand.generated) { + pLandscape->resetVisits(); + } - patchChange patchchange; - costChange costchange; - int npatchchanges = pLandscape->numPatchChanges(); - int ncostchanges = pLandscape->numCostChanges(); - int ixpchchg = 0; - int ixcostchg = 0; + patchChange patchchange; + costChange costchange; + int npatchchanges = pLandscape->numPatchChanges(); + int ncostchanges = pLandscape->numCostChanges(); + int ixpchchg = 0; + int ixcostchg = 0; #if RSDEBUG -DEBUGLOG << "RunModel(): npatchchanges=" << npatchchanges << " ncostchanges=" << ncostchanges << endl; + DEBUGLOG << "RunModel(): npatchchanges=" << npatchchanges << " ncostchanges=" << ncostchanges << endl; #endif - if (ppLand.generated) { + if (ppLand.generated) { #if RSDEBUG -DEBUGLOG << endl << "RunModel(): generating new landscape ..." << endl; -#endif - // delete previous community (if any) - // Note: this must be BEFORE the landscape is reset (as a sub-community accesses - // its corresponding patch upon deletion) - if (pComm != 0) delete pComm; - // generate new cell-based landscape - MemoLine("...generating new landscape..."); - pLandscape->resetLand(); + DEBUGLOG << endl << "RunModel(): generating new landscape ..." << endl; +#endif + // delete previous community (if any) + // Note: this must be BEFORE the landscape is reset (as a sub-community accesses + // its corresponding patch upon deletion) + if (pComm != 0) delete pComm; + // generate new cell-based landscape + MemoLine("...generating new landscape..."); + pLandscape->resetLand(); #if RSDEBUG -DEBUGLOG << "RunModel(): finished resetting landscape" << endl << endl; -#endif - pLandscape->generatePatches(); -//#if VCL - if (v.viewLand || sim.saveMaps) { - pLandscape->setLandMap(); - pLandscape->drawLandscape(rep,0,ppLand.landNum); - } -//#endif -//#if BATCH -// if (sim.saveMaps) { -// pLandscape->drawLandscape(rep,0,ppLand.landNum); -// } -//#endif + DEBUGLOG << "RunModel(): finished resetting landscape" << endl << endl; +#endif + pLandscape->generatePatches(); + //#if VCL + if (v.viewLand || sim.saveMaps) { + pLandscape->setLandMap(); + pLandscape->drawLandscape(rep, 0, ppLand.landNum); + } + //#endif + //#if BATCH + // if (sim.saveMaps) { + // pLandscape->drawLandscape(rep,0,ppLand.landNum); + // } + //#endif #if RSDEBUG -DEBUGLOG << endl << "RunModel(): finished generating patches" << endl; -#endif - pComm = new Community(pLandscape); // set up community - // set up a sub-community associated with each patch (incl. the matrix) -// pLandscape->updateCarryingCapacity(pSpecies,0); - pLandscape->updateCarryingCapacity(pSpecies,0,0); - patchData ppp; - int npatches = pLandscape->patchCount(); + DEBUGLOG << endl << "RunModel(): finished generating patches" << endl; +#endif + pComm = new Community(pLandscape); // set up community + // set up a sub-community associated with each patch (incl. the matrix) + // pLandscape->updateCarryingCapacity(pSpecies,0); + pLandscape->updateCarryingCapacity(pSpecies, 0, 0); + patchData ppp; + int npatches = pLandscape->patchCount(); #if RSDEBUG -DEBUGLOG << "RunModel(): patch count is " << npatches << endl; + DEBUGLOG << "RunModel(): patch count is " << npatches << endl; #endif - for (int i = 0; i < npatches; i++) { - ppp = pLandscape->getPatchData(i); + for (int i = 0; i < npatches; i++) { + ppp = pLandscape->getPatchData(i); #if RSDEBUG -//DEBUGLOG << "RunModel(): i = " << i -// << " ppp.pPatch = " << ppp.pPatch << " ppp.patchNum = " << ppp.patchNum -// << endl; + //DEBUGLOG << "RunModel(): i = " << i + // << " ppp.pPatch = " << ppp.pPatch << " ppp.patchNum = " << ppp.patchNum + // << endl; #endif #if RSWIN64 #if LINUX_CLUSTER - pComm->addSubComm(ppp.pPatch,ppp.patchNum); // SET UP ALL SUB-COMMUNITIES + pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES #else - SubCommunity *pSubComm = pComm->addSubComm(ppp.pPatch,ppp.patchNum); // SET UP ALL SUB-COMMUNITIES + SubCommunity* pSubComm = pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES #endif -// if (ppp.y >= 9995) { -// DEBUGLOG << "RunModel(): i=" << i << " pSubComm=" << pSubComm -// << endl; -// } + // if (ppp.y >= 9995) { + // DEBUGLOG << "RunModel(): i=" << i << " pSubComm=" << pSubComm + // << endl; + // } #else - pComm->addSubComm(ppp.pPatch,ppp.patchNum); // SET UP ALL SUB-COMMUNITIES + pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES #endif -// if (i == 0 || ppp.pPatch->getK() > 0.0) { -// // SET UP SUB-COMMUNITY FOR MATRIX PATCH AND ANY PATCH HAVING NON-ZERO CARRYING CAPACITY -// pComm->addSubComm(ppp.pPatch,ppp.patchNum); -// } - } - MemoLine("...completed..."); + // if (i == 0 || ppp.pPatch->getK() > 0.0) { + // // SET UP SUB-COMMUNITY FOR MATRIX PATCH AND ANY PATCH HAVING NON-ZERO CARRYING CAPACITY + // pComm->addSubComm(ppp.pPatch,ppp.patchNum); + // } + } + MemoLine("...completed..."); #if RSDEBUG -DEBUGLOG << endl << "RunModel(): finished generating populations" << endl; + DEBUGLOG << endl << "RunModel(): finished generating populations" << endl; #endif - } - if (init.seedType == 0 && init.freeType < 2 && init.initFrzYr > 0) { - // restrict available landscape to initialised region - pLandscape->setLandLimits(init.minSeedX,init.minSeedY, - init.maxSeedX,init.maxSeedY); - } - else { - pLandscape->resetLandLimits(); - } - - filesOK = true; - if (rep == 0) { - // open output files - if (sim.outRange) { // open Range file - if (!pComm->outRangeHeaders(pSpecies,ppLand.landNum)) { - MemoLine("UNABLE TO OPEN RANGE FILE"); - filesOK = false; - } } - if (sim.outOccup && sim.reps > 1) - if (!pComm->outOccupancyHeaders(0)) { - MemoLine("UNABLE TO OPEN OCCUPANCY FILE(S)"); - filesOK = false; - } - if (sim.outPop) { - // open Population file - if (!pComm->outPopHeaders(pSpecies,ppLand.landNum)) { - MemoLine("UNABLE TO OPEN POPULATION FILE"); - filesOK = false; - } + if (init.seedType == 0 && init.freeType < 2 && init.initFrzYr > 0) { + // restrict available landscape to initialised region + pLandscape->setLandLimits(init.minSeedX, init.minSeedY, + init.maxSeedX, init.maxSeedY); } - if (sim.outTraitsCells) - if (!pComm->outTraitsHeaders(pSpecies,ppLand.landNum)) { - MemoLine("UNABLE TO OPEN TRAITS FILE"); - filesOK = false; - } - if (sim.outTraitsRows) - if (!pComm->outTraitsRowsHeaders(pSpecies,ppLand.landNum)) { - MemoLine("UNABLE TO OPEN TRAITS ROWS FILE"); - filesOK = false; + else { + pLandscape->resetLandLimits(); + } + + filesOK = true; + if (rep == 0) { + // open output files + if (sim.outRange) { // open Range file + if (!pComm->outRangeHeaders(pSpecies, ppLand.landNum)) { + MemoLine("UNABLE TO OPEN RANGE FILE"); + filesOK = false; + } } - if (sim.outConnect && ppLand.patchModel) // open Connectivity file - if (!pLandscape->outConnectHeaders(0)) { - MemoLine("UNABLE TO OPEN CONNECTIVITY FILE"); - filesOK = false; + if (sim.outOccup && sim.reps > 1) + if (!pComm->outOccupancyHeaders(0)) { + MemoLine("UNABLE TO OPEN OCCUPANCY FILE(S)"); + filesOK = false; + } + if (sim.outPop) { + // open Population file + if (!pComm->outPopHeaders(pSpecies, ppLand.landNum)) { + MemoLine("UNABLE TO OPEN POPULATION FILE"); + filesOK = false; + } } - } + if (sim.outTraitsCells) + if (!pComm->outTraitsHeaders(pSpecies, ppLand.landNum)) { + MemoLine("UNABLE TO OPEN TRAITS FILE"); + filesOK = false; + } + if (sim.outTraitsRows) + if (!pComm->outTraitsRowsHeaders(pSpecies, ppLand.landNum)) { + MemoLine("UNABLE TO OPEN TRAITS ROWS FILE"); + filesOK = false; + } + if (sim.outConnect && ppLand.patchModel) // open Connectivity file + if (!pLandscape->outConnectHeaders(0)) { + MemoLine("UNABLE TO OPEN CONNECTIVITY FILE"); + filesOK = false; + } + } #if RSDEBUG -DEBUGLOG << "RunModel(): completed opening output files" << endl; + DEBUGLOG << "RunModel(): completed opening output files" << endl; #endif - if (!filesOK) { + if (!filesOK) { #if RSDEBUG -DEBUGLOG << "RunModel(): PROBLEM - closing output files" << endl; -#endif - // close any files which may be open - if (sim.outRange) { - pComm->outRangeHeaders(pSpecies,-999); - } - if (sim.outOccup && sim.reps > 1) - pComm->outOccupancyHeaders(-999); - if (sim.outPop) { - pComm->outPopHeaders(pSpecies,-999); - } - if (sim.outTraitsCells) - pComm->outTraitsHeaders(pSpecies,-999); - if (sim.outTraitsRows) - pComm->outTraitsRowsHeaders(pSpecies,-999); - if (sim.outConnect && ppLand.patchModel) - pLandscape->outConnectHeaders(-999); + DEBUGLOG << "RunModel(): PROBLEM - closing output files" << endl; +#endif + // close any files which may be open + if (sim.outRange) { + pComm->outRangeHeaders(pSpecies, -999); + } + if (sim.outOccup && sim.reps > 1) + pComm->outOccupancyHeaders(-999); + if (sim.outPop) { + pComm->outPopHeaders(pSpecies, -999); + } + if (sim.outTraitsCells) + pComm->outTraitsHeaders(pSpecies, -999); + if (sim.outTraitsRows) + pComm->outTraitsRowsHeaders(pSpecies, -999); + if (sim.outConnect && ppLand.patchModel) + pLandscape->outConnectHeaders(-999); #if RS_RCPP && !R_CMD - return Rcpp::List::create(Rcpp::Named("Errors") = 666); + return Rcpp::List::create(Rcpp::Named("Errors") = 666); #else - return 666; + return 666; #endif - } + } - if (env.stoch && !env.local) { - // create time series in case of global environmental stochasticity - pLandscape->setGlobalStoch(sim.years+1); - } + if (env.stoch && !env.local) { + // create time series in case of global environmental stochasticity + pLandscape->setGlobalStoch(sim.years + 1); + } - if (grad.gradient) { // set up environmental gradient - pLandscape->setEnvGradient(pSpecies,true); - } + if (grad.gradient) { // set up environmental gradient + pLandscape->setEnvGradient(pSpecies, true); + } - if (sim.outConnect && ppLand.patchModel) - pLandscape->createConnectMatrix(); + if (sim.outConnect && ppLand.patchModel) + pLandscape->createConnectMatrix(); - // variables to control dynamic landscape - landChange landChg; landChg.chgnum = 0; landChg.chgyear = 999999; - if (!ppLand.generated && ppLand.dynamic) { - landChg = pLandscape->getLandChange(0); // get first change year - } + // variables to control dynamic landscape + landChange landChg; landChg.chgnum = 0; landChg.chgyear = 999999; + if (!ppLand.generated && ppLand.dynamic) { + landChg = pLandscape->getLandChange(0); // get first change year + } - // set up populations in the community - pLandscape->updateCarryingCapacity(pSpecies,0,0); + // set up populations in the community + pLandscape->updateCarryingCapacity(pSpecies, 0, 0); #if RSDEBUG -DEBUGLOG << "RunModel(): completed updating carrying capacity" << endl; + DEBUGLOG << "RunModel(): completed updating carrying capacity" << endl; #endif -// if (init.seedType != 2) { - pComm->initialise(pSpecies,-1); -// } - bool updateland = false; - int landIx = 0; // landscape change index + // if (init.seedType != 2) { + pComm->initialise(pSpecies, -1); + // } + bool updateland = false; + int landIx = 0; // landscape change index #if RSDEBUG -DEBUGLOG << "RunModel(): completed initialisation, rep=" << rep - << " pSpecies=" << pSpecies << endl; + DEBUGLOG << "RunModel(): completed initialisation, rep=" << rep + << " pSpecies=" << pSpecies << endl; #endif #if BATCH #if RS_RCPP && !R_CMD - Rcpp::Rcout << "RunModel(): completed initialisation " << endl; + Rcpp::Rcout << "RunModel(): completed initialisation " << endl; #else - cout << "RunModel(): completed initialisation " << endl; + cout << "RunModel(): completed initialisation " << endl; #endif #endif - // open a new individuals file for each replicate - if (sim.outInds) - pComm->outInds(rep,0,0,ppLand.landNum); - // open a new genetics file for each replicate - if (sim.outGenetics) { - pComm->outGenetics(rep,0,0,ppLand.landNum); - if (!dem.stageStruct && sim.outStartGenetic == 0) { - // write genetic data for initialised individuals of non-strucutred population - pComm->outGenetics(rep,0,0,-1); + // open a new individuals file for each replicate + if (sim.outInds) + pComm->outInds(rep, 0, 0, ppLand.landNum); + // open a new genetics file for each replicate + if (sim.outGenetics) { + pComm->outGenetics(rep, 0, 0, ppLand.landNum); + if (!dem.stageStruct && sim.outStartGenetic == 0) { + // write genetic data for initialised individuals of non-strucutred population + pComm->outGenetics(rep, 0, 0, -1); + } } - } #if RSDEBUG - // output initialised Individuals - if (sim.outInds) - pComm->outInds(rep,-1,-1,-1); + // output initialised Individuals + if (sim.outInds) + pComm->outInds(rep, -1, -1, -1); #endif #if RS_RCPP // open a new movement paths file for each replicate if (sim.outPaths) - pLandscape->outPathsHeaders(rep,0); + pLandscape->outPathsHeaders(rep, 0); #endif - // years loop - MemoLine("...running..."); - for (yr = 0; yr < sim.years; yr++) { + // years loop + MemoLine("...running..."); + for (yr = 0; yr < sim.years; yr++) { #if RSDEBUG -DEBUGLOG << endl << "RunModel(): starting simulation=" << sim.simulation - << " rep=" << rep << " yr=" << yr << endl; + DEBUGLOG << endl << "RunModel(): starting simulation=" << sim.simulation + << " rep=" << rep << " yr=" << yr << endl; #endif #if RS_RCPP && !R_CMD - Rcpp::checkUserInterrupt(); -#endif - bool updateCC = false; - if (yr < 4 - || (yr < 31 && yr%10 == 0) - || (yr < 301 && yr%100 == 0) - || (yr < 3001 && yr%1000 == 0) - || (yr < 30001 && yr%10000 == 0) - || (yr < 300001 && yr%100000 == 0) - || (yr < 3000001 && yr%1000000 == 0) - ) { + Rcpp::checkUserInterrupt(); +#endif + bool updateCC = false; + if (yr < 4 + || (yr < 31 && yr % 10 == 0) + || (yr < 301 && yr % 100 == 0) + || (yr < 3001 && yr % 1000 == 0) + || (yr < 30001 && yr % 10000 == 0) + || (yr < 300001 && yr % 100000 == 0) + || (yr < 3000001 && yr % 1000000 == 0) + ) { #if RS_RCPP && !R_CMD - Rcpp::Rcout << "starting year " << yr << "..." << endl; + Rcpp::Rcout << "starting year " << yr << "..." << endl; #else - cout << "starting year " << yr << endl; + cout << "starting year " << yr << endl; #endif - } - if (init.seedType == 0 && init.freeType < 2) { - // apply any range restrictions - if (yr == init.initFrzYr) { - // release initial frozen range - reset landscape to its full extent - pLandscape->resetLandLimits(); - updateCC = true; } - if (init.restrictRange) { - if (yr > init.initFrzYr && yr < init.finalFrzYr) { - if ((yr-init.initFrzYr)%init.restrictFreq == 0) { - // apply dynamic range restriction - commStats s = pComm->getStats(); - int minY = s.maxY-init.restrictRows; - if (minY < 0) minY = 0; + if (init.seedType == 0 && init.freeType < 2) { + // apply any range restrictions + if (yr == init.initFrzYr) { + // release initial frozen range - reset landscape to its full extent + pLandscape->resetLandLimits(); + updateCC = true; + } + if (init.restrictRange) { + if (yr > init.initFrzYr && yr < init.finalFrzYr) { + if ((yr - init.initFrzYr) % init.restrictFreq == 0) { + // apply dynamic range restriction + commStats s = pComm->getStats(); + int minY = s.maxY - init.restrictRows; + if (minY < 0) minY = 0; #if RSDEBUG -DEBUGLOG << "RunModel(): restriction yr=" << yr - << " s.minY=" << s.minY << " s.maxY=" << s.maxY - << " init.restrictRows=" << init.restrictRows - << " minY=" << minY - << endl; -#endif - pLandscape->setLandLimits(ppLand.minX,minY,ppLand.maxX,ppLand.maxY); - updateCC = true; + DEBUGLOG << "RunModel(): restriction yr=" << yr + << " s.minY=" << s.minY << " s.maxY=" << s.maxY + << " init.restrictRows=" << init.restrictRows + << " minY=" << minY + << endl; +#endif + pLandscape->setLandLimits(ppLand.minX, minY, ppLand.maxX, ppLand.maxY); + updateCC = true; #if RSDEBUG -//landData d = pLandscape->getLandData(); -//DEBUGLOG << "RunModel(): landscape yr=" << yr -// << " minX=" << d.minX << " minY=" << d.minY << " maxX=" << d.maxX << " maxY=" << d.maxY -// << endl; + //landData d = pLandscape->getLandData(); + //DEBUGLOG << "RunModel(): landscape yr=" << yr + // << " minX=" << d.minX << " minY=" << d.minY << " maxX=" << d.maxX << " maxY=" << d.maxY + // << endl; #endif + } } - } - if (yr == init.finalFrzYr) { - // apply final range restriction - commStats s = pComm->getStats(); + if (yr == init.finalFrzYr) { + // apply final range restriction + commStats s = pComm->getStats(); #if RSDEBUG -DEBUGLOG << "RunModel(): final restriction yr=" << yr - << " s.minY=" << s.minY << " s.maxY=" << s.maxY - << endl; + DEBUGLOG << "RunModel(): final restriction yr=" << yr + << " s.minY=" << s.minY << " s.maxY=" << s.maxY + << endl; #endif - pLandscape->setLandLimits(ppLand.minX,s.minY,ppLand.maxX,s.maxY); - updateCC = true; + pLandscape->setLandLimits(ppLand.minX, s.minY, ppLand.maxX, s.maxY); + updateCC = true; #if RSDEBUG -//landData d = pLandscape->getLandData(); -//DEBUGLOG << "RunModel(): landscape yr=" << yr -// << " minX=" << d.minX << " minY=" << d.minY << " maxX=" << d.maxX << " maxY=" << d.maxY -// << endl; + //landData d = pLandscape->getLandData(); + //DEBUGLOG << "RunModel(): landscape yr=" << yr + // << " minX=" << d.minX << " minY=" << d.minY << " maxX=" << d.maxX << " maxY=" << d.maxY + // << endl; #endif + } } } - } - // environmental gradient, stochasticity & local extinction - // or dynamic landscape - updateland = false; - if (env.stoch || grad.gradient || ppLand.dynamic) { - if (grad.shifting && yr > grad.shift_begin && yr < grad.shift_stop) { - paramsGrad->incrOptY(); - pLandscape->setEnvGradient(pSpecies,false); - updateCC = true; - } + // environmental gradient, stochasticity & local extinction + // or dynamic landscape + updateland = false; + if (env.stoch || grad.gradient || ppLand.dynamic) { + if (grad.shifting && yr > grad.shift_begin && yr < grad.shift_stop) { + paramsGrad->incrOptY(); + pLandscape->setEnvGradient(pSpecies, false); + updateCC = true; + } #if RSDEBUG -//DEBUGLOG << "RunModel(): yr=" << yr << " shift_begin=" << grad.shift_begin -// << " shift_stop=" << grad.shift_stop << " opt_y=" << grad.opt_y << endl; + //DEBUGLOG << "RunModel(): yr=" << yr << " shift_begin=" << grad.shift_begin + // << " shift_stop=" << grad.shift_stop << " opt_y=" << grad.opt_y << endl; #endif - if (env.stoch) { - if (env.local) pLandscape->updateLocalStoch(); - updateCC = true; - } - if (ppLand.dynamic) { + if (env.stoch) { + if (env.local) pLandscape->updateLocalStoch(); + updateCC = true; + } + if (ppLand.dynamic) { #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " landChg.chgnum=" << landChg.chgnum - << " landChg.chgyear=" << landChg.chgyear - << " npatchchanges=" << npatchchanges << " ncostchanges=" << ncostchanges - << " ixpchchg=" << ixpchchg << " ixcostchg=" << ixcostchg - << endl; -#endif - if (yr == landChg.chgyear) { // apply landscape change - landIx = landChg.chgnum; - updateland = updateCC = true; - if (ppLand.patchModel) { // apply any patch changes - Patch *pPatch; - Cell *pCell; - patchchange = pLandscape->getPatchChange(ixpchchg++); - while (patchchange.chgnum <= landIx && ixpchchg <= npatchchanges) { + DEBUGLOG << "RunModel(): yr=" << yr << " landChg.chgnum=" << landChg.chgnum + << " landChg.chgyear=" << landChg.chgyear + << " npatchchanges=" << npatchchanges << " ncostchanges=" << ncostchanges + << " ixpchchg=" << ixpchchg << " ixcostchg=" << ixcostchg + << endl; +#endif + if (yr == landChg.chgyear) { // apply landscape change + landIx = landChg.chgnum; + updateland = updateCC = true; + if (ppLand.patchModel) { // apply any patch changes + Patch* pPatch; + Cell* pCell; + patchchange = pLandscape->getPatchChange(ixpchchg++); + while (patchchange.chgnum <= landIx && ixpchchg <= npatchchanges) { #if RSDEBUG -//DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << landIx -// << " npatchchanges=" << npatchchanges << " ixpchchg=" << ixpchchg -// << " patchchange.chgnum=" << patchchange.chgnum -// << " .oldpatch=" << patchchange.oldpatch -// << " .newpatch=" << patchchange.newpatch -// << " .x=" << patchchange.x << " .y=" << patchchange.y -// << endl; + //DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << landIx + // << " npatchchanges=" << npatchchanges << " ixpchchg=" << ixpchchg + // << " patchchange.chgnum=" << patchchange.chgnum + // << " .oldpatch=" << patchchange.oldpatch + // << " .newpatch=" << patchchange.newpatch + // << " .x=" << patchchange.x << " .y=" << patchchange.y + // << endl; #endif // move cell from original patch to new patch - pCell = pLandscape->findCell(patchchange.x,patchchange.y); - if (patchchange.oldpatch != 0) { // not matrix - pPatch = pLandscape->findPatch(patchchange.oldpatch); - pPatch->removeCell(pCell); - } - if (patchchange.newpatch == 0) { // matrix - pPatch = 0; + pCell = pLandscape->findCell(patchchange.x, patchchange.y); + if (patchchange.oldpatch != 0) { // not matrix + pPatch = pLandscape->findPatch(patchchange.oldpatch); + pPatch->removeCell(pCell); + } + if (patchchange.newpatch == 0) { // matrix + pPatch = 0; + } + else { + pPatch = pLandscape->findPatch(patchchange.newpatch); + pPatch->addCell(pCell, patchchange.x, patchchange.y); + } + pCell->setPatch((intptr)pPatch); + // get next patch change + patchchange = pLandscape->getPatchChange(ixpchchg++); } - else { - pPatch = pLandscape->findPatch(patchchange.newpatch); - pPatch->addCell(pCell,patchchange.x,patchchange.y); - } - pCell->setPatch((intptr)pPatch); - // get next patch change - patchchange = pLandscape->getPatchChange(ixpchchg++); + ixpchchg--; + pLandscape->resetPatches(); // reset patch limits } - ixpchchg--; - pLandscape->resetPatches(); // reset patch limits - } - if (landChg.costfile != "NULL") { // apply any SMS cost changes + if (landChg.costfile != "NULL") { // apply any SMS cost changes #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " landChg.costfile=" << landChg.costfile << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " landChg.costfile=" << landChg.costfile << endl; #endif - Cell *pCell; - costchange = pLandscape->getCostChange(ixcostchg++); - while (costchange.chgnum <= landIx && ixcostchg <= ncostchanges) { + Cell* pCell; + costchange = pLandscape->getCostChange(ixcostchg++); + while (costchange.chgnum <= landIx && ixcostchg <= ncostchanges) { #if RSDEBUG -//DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << landIx -// << " ncostchanges=" << ncostchanges << " ixcostchg=" << ixcostchg -// << " costchange.chgnum=" << costchange.chgnum -// << " .x=" << costchange.x << " .y=" << costchange.y -// << " .oldcost=" << costchange.oldcost -// << " .newcost=" << costchange.newcost -// << endl; -#endif - pCell = pLandscape->findCell(costchange.x,costchange.y); - if (pCell != 0) { - pCell->setCost(costchange.newcost); + //DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << landIx + // << " ncostchanges=" << ncostchanges << " ixcostchg=" << ixcostchg + // << " costchange.chgnum=" << costchange.chgnum + // << " .x=" << costchange.x << " .y=" << costchange.y + // << " .oldcost=" << costchange.oldcost + // << " .newcost=" << costchange.newcost + // << endl; +#endif + pCell = pLandscape->findCell(costchange.x, costchange.y); + if (pCell != 0) { + pCell->setCost(costchange.newcost); + } + costchange = pLandscape->getCostChange(ixcostchg++); } - costchange = pLandscape->getCostChange(ixcostchg++); + ixcostchg--; + pLandscape->resetEffCosts(); + } + if (landIx < pLandscape->numLandChanges()) { // get next change + landChg = pLandscape->getLandChange(landIx); + } + else { + landChg.chgyear = 9999999; } - ixcostchg--; - pLandscape->resetEffCosts(); - } - if (landIx < pLandscape->numLandChanges()) { // get next change - landChg = pLandscape->getLandChange(landIx); - } - else { - landChg.chgyear = 9999999; } } + } // end of environmental gradient, etc. + + if (updateCC) { + pLandscape->updateCarryingCapacity(pSpecies, yr, landIx); } - } // end of environmental gradient, etc. - if (updateCC) { - pLandscape->updateCarryingCapacity(pSpecies,yr,landIx); - } - - if (sim.outConnect && ppLand.patchModel) - pLandscape->resetConnectMatrix(); + if (sim.outConnect && ppLand.patchModel) + pLandscape->resetConnectMatrix(); - if (ppLand.dynamic && updateland) { -// trfrRules trfr = pSpecies->getTrfr(); - if (trfr.moveModel && trfr.moveType == 1) { // SMS - if (!trfr.costMap) pLandscape->resetCosts(); // in case habitats have changed - } - // apply effects of landscape change to species present in changed patches - pComm->patchChanges(); + if (ppLand.dynamic && updateland) { + // trfrRules trfr = pSpecies->getTrfr(); + if (trfr.moveModel && trfr.moveType == 1) { // SMS + if (!trfr.costMap) pLandscape->resetCosts(); // in case habitats have changed + } + // apply effects of landscape change to species present in changed patches + pComm->patchChanges(); #if RS_RCPP - pComm->dispersal(landIx,yr); + pComm->dispersal(landIx, yr); #else - pComm->dispersal(landIx); + pComm->dispersal(landIx); #endif // RS_RCPP - } - if (init.restrictRange) { - // remove any population from region removed from restricted range - if (yr > init.initFrzYr && yr < init.finalFrzYr) { - if ((yr-init.initFrzYr)%init.restrictFreq == 0) { - pComm->patchChanges(); + } + if (init.restrictRange) { + // remove any population from region removed from restricted range + if (yr > init.initFrzYr && yr < init.finalFrzYr) { + if ((yr - init.initFrzYr) % init.restrictFreq == 0) { + pComm->patchChanges(); + } } } - } - if (init.seedType == 2) { - // add any new initial individuals for the current year - pComm->initialise(pSpecies,yr); - } + if (init.seedType == 2) { + // add any new initial individuals for the current year + pComm->initialise(pSpecies, yr); + } - for(int gen = 0; gen < dem.repSeasons; gen++) // generation loop - { + for (int gen = 0; gen < dem.repSeasons; gen++) // generation loop + { #if RSDEBUG -// TEMPORARY RANDOM STREAM CHECK -//if (yr%1 == 0 && gen == 0) -if (yr%1 == 0) -{ -DEBUGLOG << endl << "RunModel(): start of gen " << gen << " in year " << yr - << " for rep " << rep << " ("; -for (int i = 0; i < 5; i++) { - int rrrr = pRandom->IRandom(1000,2000); - DEBUGLOG << " " << rrrr; -} -DEBUGLOG << " )" << endl; -} + // TEMPORARY RANDOM STREAM CHECK + //if (yr%1 == 0 && gen == 0) + if (yr % 1 == 0) + { + DEBUGLOG << endl << "RunModel(): start of gen " << gen << " in year " << yr + << " for rep " << rep << " ("; + for (int i = 0; i < 5; i++) { + int rrrr = pRandom->IRandom(1000, 2000); + DEBUGLOG << " " << rrrr; + } + DEBUGLOG << " )" << endl; + } #endif - if (v.viewPop || (sim.saveMaps && yr%sim.mapInt == 0)) { - if (updateland && gen == 0) { - pLandscape->drawLandscape(rep,landIx,ppLand.landNum); + if (v.viewPop || (sim.saveMaps && yr % sim.mapInt == 0)) { + if (updateland && gen == 0) { + pLandscape->drawLandscape(rep, landIx, ppLand.landNum); + } + pComm->draw(rep, yr, gen, ppLand.landNum); } - pComm->draw(rep,yr,gen,ppLand.landNum); - } - // Output and pop. visualisation before reproduction - if (v.viewPop || v.viewTraits || sim.outOccup - || sim.outTraitsCells || sim.outTraitsRows || sim.saveMaps) - PreReproductionOutput(pLandscape,pComm,rep,yr,gen); - // for non-structured population, also produce range and population output now - if (!dem.stageStruct && (sim.outRange || sim.outPop)) - RangePopOutput(pComm,rep,yr,gen); + // Output and pop. visualisation before reproduction + if (v.viewPop || v.viewTraits || sim.outOccup + || sim.outTraitsCells || sim.outTraitsRows || sim.saveMaps) + PreReproductionOutput(pLandscape, pComm, rep, yr, gen); + // for non-structured population, also produce range and population output now + if (!dem.stageStruct && (sim.outRange || sim.outPop)) + RangePopOutput(pComm, rep, yr, gen); #if RS_RCPP && !R_CMD - if ( sim.ReturnPopRaster && sim.outPop && yr >= sim.outStartPop && yr%sim.outIntPop == 0) { - list_outPop.push_back(pComm->addYearToPopList(rep,yr), "rep" + std::to_string(rep) + "_year" + std::to_string(yr)); - } + if (sim.ReturnPopRaster && sim.outPop && yr >= sim.outStartPop && yr % sim.outIntPop == 0) { + list_outPop.push_back(pComm->addYearToPopList(rep, yr), "rep" + std::to_string(rep) + "_year" + std::to_string(yr)); + } #endif #if RSDEBUG -//DEBUGLOG << "RunModel(): completed RangePopOutput()" -// << " Total_Size = " << Total_Size << endl; + //DEBUGLOG << "RunModel(): completed RangePopOutput()" + // << " Total_Size = " << Total_Size << endl; #endif // apply local extinction for generation 0 only // CHANGED TO *BEFORE* RANGE & POPN OUTPUT PRODUCTION IN v1.1, // SO THAT NOS. OF JUVENILES BORN CAN BE REPORTED - if (!ppLand.patchModel && gen == 0) { - if (env.localExt) pComm->localExtinction(0); - if (grad.gradient && grad.gradType == 3) pComm->localExtinction(1); - } + if (!ppLand.patchModel && gen == 0) { + if (env.localExt) pComm->localExtinction(0); + if (grad.gradient && grad.gradType == 3) pComm->localExtinction(1); + } - // reproduction - pComm->reproduction(yr); + // reproduction + pComm->reproduction(yr); - if (dem.stageStruct) { - if (sstruct.survival == 0) { // at reproduction - pComm->survival(0,2,1); // survival of all non-juvenile stages + if (dem.stageStruct) { + if (sstruct.survival == 0) { // at reproduction + pComm->survival(0, 2, 1); // survival of all non-juvenile stages + } } - } - // Output and pop. visualisation AFTER reproduction - if (dem.stageStruct && (sim.outRange || sim.outPop)) - RangePopOutput(pComm,rep,yr,gen); + // Output and pop. visualisation AFTER reproduction + if (dem.stageStruct && (sim.outRange || sim.outPop)) + RangePopOutput(pComm, rep, yr, gen); #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed reproduction" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed reproduction" << endl; #endif - // Dispersal + // Dispersal - pComm->emigration(); + pComm->emigration(); #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed emigration" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed emigration" << endl; #endif #if RS_RCPP - pComm->dispersal(landIx,yr); + pComm->dispersal(landIx, yr); #else - pComm->dispersal(landIx); + pComm->dispersal(landIx); #endif // RS_RCPP #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed dispersal" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed dispersal" << endl; #endif - // survival part 0 - if (dem.stageStruct) { - if (sstruct.survival == 0) { // at reproduction - pComm->survival(0,0,1); // survival of juveniles only - } - if (sstruct.survival == 1) { // between reproduction events - pComm->survival(0,1,1); // survival of all stages + // survival part 0 + if (dem.stageStruct) { + if (sstruct.survival == 0) { // at reproduction + pComm->survival(0, 0, 1); // survival of juveniles only + } + if (sstruct.survival == 1) { // between reproduction events + pComm->survival(0, 1, 1); // survival of all stages + } + if (sstruct.survival == 2) { // annually + pComm->survival(0, 1, 0); // development only of all stages + // pComm->survival(0,1,0); // development only of all stages + } } - if (sstruct.survival == 2) { // annually - pComm->survival(0,1,0); // development only of all stages -// pComm->survival(0,1,0); // development only of all stages + else { // non-structured population + pComm->survival(0, 1, 1); } - } - else { // non-structured population - pComm->survival(0,1,1); - } #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed survival part 0" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed survival part 0" << endl; #endif // output Individuals - if (sim.outInds && yr >= sim.outStartInd && yr%sim.outIntInd == 0) - pComm->outInds(rep,yr,gen,-1); + if (sim.outInds && yr >= sim.outStartInd && yr % sim.outIntInd == 0) + pComm->outInds(rep, yr, gen, -1); // output Genetics - if (sim.outGenetics && yr >= sim.outStartGenetic && yr%sim.outIntGenetic == 0) - pComm->outGenetics(rep,yr,gen,-1); + if (sim.outGenetics && yr >= sim.outStartGenetic && yr % sim.outIntGenetic == 0) + pComm->outGenetics(rep, yr, gen, -1); - // survival part 1 - if (dem.stageStruct) { -// if (sstruct.survival != 2) { // at reproduction or between reproduction events - pComm->survival(1,0,1); -// } - } - else { // non-structured population - pComm->survival(1,0,1); - } + // survival part 1 + if (dem.stageStruct) { + // if (sstruct.survival != 2) { // at reproduction or between reproduction events + pComm->survival(1, 0, 1); + // } + } + else { // non-structured population + pComm->survival(1, 0, 1); + } #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed survival part 1" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed survival part 1" << endl; #endif - } // end of the generation loop + } // end of the generation loop #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " completed generation loop" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " completed generation loop" << endl; #endif - totalInds = pComm->totalInds(); - if (totalInds <= 0) { yr++; break; } + totalInds = pComm->totalInds(); + if (totalInds <= 0) { yr++; break; } - // Connectivity Matrix - if (sim.outConnect && ppLand.patchModel - && yr >= sim.outStartConn && yr%sim.outIntConn == 0) - pLandscape->outConnect(rep,yr); + // Connectivity Matrix + if (sim.outConnect && ppLand.patchModel + && yr >= sim.outStartConn && yr % sim.outIntConn == 0) + pLandscape->outConnect(rep, yr); - if (dem.stageStruct && sstruct.survival == 2) { // annual survival - all stages - pComm->survival(0,1,2); - pComm->survival(1,0,1); + if (dem.stageStruct && sstruct.survival == 2) { // annual survival - all stages + pComm->survival(0, 1, 2); + pComm->survival(1, 0, 1); #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " completed annual survival" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " completed annual survival" << endl; #endif - } + } - if (dem.stageStruct) { - pComm->ageIncrement(); // increment age of all individuals - if (sim.outInds && yr >= sim.outStartInd && yr%sim.outIntInd == 0) - pComm->outInds(rep,yr,-1,-1); // list any individuals dying having reached maximum age - pComm->survival(1,0,1); // delete any such individuals + if (dem.stageStruct) { + pComm->ageIncrement(); // increment age of all individuals + if (sim.outInds && yr >= sim.outStartInd && yr % sim.outIntInd == 0) + pComm->outInds(rep, yr, -1, -1); // list any individuals dying having reached maximum age + pComm->survival(1, 0, 1); // delete any such individuals #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " completed Age_increment and final survival" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " completed Age_increment and final survival" << endl; #endif - totalInds = pComm->totalInds(); - if (totalInds <= 0) { yr++; break; } - } + totalInds = pComm->totalInds(); + if (totalInds <= 0) { yr++; break; } + } - } // end of the years loop + } // end of the years loop - // Final output and popn. visualisation + // Final output and popn. visualisation #if BATCH - if (sim.saveMaps && yr%sim.mapInt == 0) { - if (updateland) { - pLandscape->drawLandscape(rep,landIx,ppLand.landNum); + if (sim.saveMaps && yr % sim.mapInt == 0) { + if (updateland) { + pLandscape->drawLandscape(rep, landIx, ppLand.landNum); + } + pComm->draw(rep, yr, 0, ppLand.landNum); } - pComm->draw(rep,yr,0,ppLand.landNum); - } #endif // produce final summary output if (v.viewPop || v.viewTraits || sim.outOccup - || sim.outTraitsCells || sim.outTraitsRows || sim.saveMaps) - PreReproductionOutput(pLandscape,pComm,rep,yr,0); + || sim.outTraitsCells || sim.outTraitsRows || sim.saveMaps) + PreReproductionOutput(pLandscape, pComm, rep, yr, 0); if (sim.outRange || sim.outPop) - RangePopOutput(pComm,rep,yr,0); + RangePopOutput(pComm, rep, yr, 0); #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " completed final summary output" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " completed final summary output" << endl; #endif - pComm->resetPopns(); + pComm->resetPopns(); -// if (batchMode) { -// // delete the community of species using the landscape -// pComm->resetPopns(); -// } + // if (batchMode) { + // // delete the community of species using the landscape + // pComm->resetPopns(); + // } - //Reset the gradient optimum - if (grad.gradient) paramsGrad->resetOptY(); + //Reset the gradient optimum + if (grad.gradient) paramsGrad->resetOptY(); - pLandscape->resetLandLimits(); + pLandscape->resetLandLimits(); #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << "reset" - << " npatchchanges=" << npatchchanges << " ncostchanges=" << ncostchanges - << " ixpchchg=" << ixpchchg << " ixcostchg=" << ixcostchg - << endl; -#endif - if (ppLand.patchModel && ppLand.dynamic && ixpchchg > 0) { - // apply any patch changes to reset landscape to original configuration - // (provided that at least one has already occurred) - patchChange patchchange; - Patch *pPatch; - Cell *pCell; - patchchange = pLandscape->getPatchChange(ixpchchg++); - while (patchchange.chgnum <= 666666 && ixpchchg <= npatchchanges) { + DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << "reset" + << " npatchchanges=" << npatchchanges << " ncostchanges=" << ncostchanges + << " ixpchchg=" << ixpchchg << " ixcostchg=" << ixcostchg + << endl; +#endif + if (ppLand.patchModel && ppLand.dynamic && ixpchchg > 0) { + // apply any patch changes to reset landscape to original configuration + // (provided that at least one has already occurred) + patchChange patchchange; + Patch* pPatch; + Cell* pCell; + patchchange = pLandscape->getPatchChange(ixpchchg++); + while (patchchange.chgnum <= 666666 && ixpchchg <= npatchchanges) { #if RSDEBUG -//DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << "reset" -// << " npatchchanges=" << npatchchanges << " ixpchchg=" << ixpchchg -// << " patchchange.chgnum=" << patchchange.chgnum -// << " .oldpatch=" << patchchange.oldpatch -// << " .newpatch=" << patchchange.newpatch -// << " .x=" << patchchange.x << " .y=" << patchchange.y -// << endl; + //DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << "reset" + // << " npatchchanges=" << npatchchanges << " ixpchchg=" << ixpchchg + // << " patchchange.chgnum=" << patchchange.chgnum + // << " .oldpatch=" << patchchange.oldpatch + // << " .newpatch=" << patchchange.newpatch + // << " .x=" << patchchange.x << " .y=" << patchchange.y + // << endl; #endif // move cell from original patch to new patch - pCell = pLandscape->findCell(patchchange.x,patchchange.y); - if (patchchange.oldpatch != 0) { // not matrix - pPatch = pLandscape->findPatch(patchchange.oldpatch); - pPatch->removeCell(pCell); - } - if (patchchange.newpatch == 0) { // matrix - pPatch = 0; - } - else { - pPatch = pLandscape->findPatch(patchchange.newpatch); - pPatch->addCell(pCell,patchchange.x,patchchange.y); + pCell = pLandscape->findCell(patchchange.x, patchchange.y); + if (patchchange.oldpatch != 0) { // not matrix + pPatch = pLandscape->findPatch(patchchange.oldpatch); + pPatch->removeCell(pCell); + } + if (patchchange.newpatch == 0) { // matrix + pPatch = 0; + } + else { + pPatch = pLandscape->findPatch(patchchange.newpatch); + pPatch->addCell(pCell, patchchange.x, patchchange.y); + } + pCell->setPatch((intptr)pPatch); + // get next patch change + patchchange = pLandscape->getPatchChange(ixpchchg++); } - pCell->setPatch((intptr)pPatch); - // get next patch change - patchchange = pLandscape->getPatchChange(ixpchchg++); + ixpchchg--; + pLandscape->resetPatches(); } - ixpchchg--; - pLandscape->resetPatches(); - } - if (ppLand.dynamic) { - trfrRules trfr = pSpecies->getTrfr(); - if (trfr.moveModel && trfr.moveType == 1) { // SMS - if (ixcostchg > 0) { - // apply any cost changes to reset landscape to original configuration - // (provided that at least one has already occurred) - Cell *pCell; - costchange = pLandscape->getCostChange(ixcostchg++); - while (costchange.chgnum <= 666666 && ixcostchg <= ncostchanges) { + if (ppLand.dynamic) { + trfrRules trfr = pSpecies->getTrfr(); + if (trfr.moveModel && trfr.moveType == 1) { // SMS + if (ixcostchg > 0) { + // apply any cost changes to reset landscape to original configuration + // (provided that at least one has already occurred) + Cell* pCell; + costchange = pLandscape->getCostChange(ixcostchg++); + while (costchange.chgnum <= 666666 && ixcostchg <= ncostchanges) { #if RSDEBUG -//DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << landIx -// << " ncostchanges=" << ncostchanges << " ixcostchg=" << ixcostchg -// << " costchange.chgnum=" << costchange.chgnum -// << " .x=" << costchange.x << " .y=" << costchange.y -// << " .oldcost=" << costchange.oldcost -// << " .newcost=" << costchange.newcost -// << endl; -#endif - pCell = pLandscape->findCell(costchange.x,costchange.y); - if (pCell != 0) { - pCell->setCost(costchange.newcost); - } - costchange = pLandscape->getCostChange(ixcostchg++); + //DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << landIx + // << " ncostchanges=" << ncostchanges << " ixcostchg=" << ixcostchg + // << " costchange.chgnum=" << costchange.chgnum + // << " .x=" << costchange.x << " .y=" << costchange.y + // << " .oldcost=" << costchange.oldcost + // << " .newcost=" << costchange.newcost + // << endl; +#endif + pCell = pLandscape->findCell(costchange.x, costchange.y); + if (pCell != 0) { + pCell->setCost(costchange.newcost); } - ixcostchg--; - pLandscape->resetEffCosts(); + costchange = pLandscape->getCostChange(ixcostchg++); + } + ixcostchg--; + pLandscape->resetEffCosts(); + } + if (!trfr.costMap) pLandscape->resetCosts(); // in case habitats have changed } - if (!trfr.costMap) pLandscape->resetCosts(); // in case habitats have changed } - } -// if (landIx < pLandscape->numLandChanges()) { // get next change -// landChg = pLandscape->getLandChange(landIx); -// } -// else { -// landChg.chgyear = 9999999; -// } + // if (landIx < pLandscape->numLandChanges()) { // get next change + // landChg = pLandscape->getLandChange(landIx); + // } + // else { + // landChg.chgyear = 9999999; + // } #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " completed reset" - << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " completed reset" + << endl; #endif - if (sim.outConnect && ppLand.patchModel) - pLandscape->resetConnectMatrix(); // set connectivity matrix to zeroes + if (sim.outConnect && ppLand.patchModel) + pLandscape->resetConnectMatrix(); // set connectivity matrix to zeroes - if (sim.outInds) // close Individuals output file - pComm->outInds(rep,0,0,-999); - if (sim.outGenetics) // close Genetics output file - pComm->outGenetics(rep,0,0,-999); + if (sim.outInds) // close Individuals output file + pComm->outInds(rep, 0, 0, -999); + if (sim.outGenetics) // close Genetics output file + pComm->outGenetics(rep, 0, 0, -999); - if (sim.saveVisits) { - pLandscape->outVisits(rep,ppLand.landNum); - pLandscape->resetVisits(); - } + if (sim.saveVisits) { + pLandscape->outVisits(rep, ppLand.landNum); + pLandscape->resetVisits(); + } #if RS_RCPP - if (sim.outPaths) - pLandscape->outPathsHeaders(rep,-999); + if (sim.outPaths) + pLandscape->outPathsHeaders(rep, -999); #endif #if RSDEBUG -DEBUGLOG << endl << "RunModel(): finished rep=" << rep << endl; + DEBUGLOG << endl << "RunModel(): finished rep=" << rep << endl; #endif -} // end of the replicates loop + } // end of the replicates loop -if (sim.outConnect && ppLand.patchModel) { - pLandscape->deleteConnectMatrix(); - pLandscape->outConnectHeaders(-999); // close Connectivity Matrix file -} + if (sim.outConnect && ppLand.patchModel) { + pLandscape->deleteConnectMatrix(); + pLandscape->outConnectHeaders(-999); // close Connectivity Matrix file + } + + // Occupancy outputs + if (sim.outOccup && sim.reps > 1) { + MemoLine("Writing final occupancy output..."); + pComm->outOccupancy(); + pComm->outOccSuit(v.viewGraph); + // pComm->deleteOccupancy((sim.years/sim.outInt)+1); + pComm->deleteOccupancy((sim.years / sim.outIntOcc) + 1); + pComm->outOccupancyHeaders(-999); + MemoLine("...finished"); + } + + if (sim.outRange) { + pComm->outRangeHeaders(pSpecies, -999); // close Range file + } + if (sim.outPop) { + pComm->outPopHeaders(pSpecies, -999); // close Population file + } + if (sim.outTraitsCells) + pComm->outTraitsHeaders(pSpecies, -999); // close Traits file + if (sim.outTraitsRows) + pComm->outTraitsRowsHeaders(pSpecies, -999); // close Traits rows file + // close Individuals & Genetics output files if open + // they can still be open if the simulation was stopped by the user + if (sim.outInds) pComm->outInds(0, 0, 0, -999); + if (sim.outGenetics) pComm->outGenetics(0, 0, 0, -999); -// Occupancy outputs -if (sim.outOccup && sim.reps > 1) { - MemoLine("Writing final occupancy output..."); - pComm->outOccupancy(); - pComm->outOccSuit(v.viewGraph); -// pComm->deleteOccupancy((sim.years/sim.outInt)+1); - pComm->deleteOccupancy((sim.years/sim.outIntOcc)+1); - pComm->outOccupancyHeaders(-999); + MemoLine("Deleting community..."); + delete pComm; pComm = 0; MemoLine("...finished"); -} -if (sim.outRange) { - pComm->outRangeHeaders(pSpecies,-999); // close Range file -} -if (sim.outPop) { - pComm->outPopHeaders(pSpecies,-999); // close Population file -} -if (sim.outTraitsCells) - pComm->outTraitsHeaders(pSpecies,-999); // close Traits file -if (sim.outTraitsRows) - pComm->outTraitsRowsHeaders(pSpecies,-999); // close Traits rows file -// close Individuals & Genetics output files if open -// they can still be open if the simulation was stopped by the user -if (sim.outInds) pComm->outInds(0,0,0,-999); -if (sim.outGenetics) pComm->outGenetics(0,0,0,-999); - -MemoLine("Deleting community..."); -delete pComm; pComm = 0; -MemoLine("...finished"); - -// Write performance data -//t1 = time(0); -//RSlog << "Simulation," << sim.simulation << "," << sim.reps << "," << sim.years -// << "," << t1-t0 << endl; + // Write performance data + //t1 = time(0); + //RSlog << "Simulation," << sim.simulation << "," << sim.reps << "," << sim.years + // << "," << t1-t0 << endl; #if RS_RCPP && !R_CMD return list_outPop; @@ -894,94 +894,94 @@ MemoLine("...finished"); #if RS_EMBARCADERO || LINUX_CLUSTER || RS_RCPP // Check whether a specified directory path exists -bool is_directory(const char *pathname) { -struct stat info; -if (stat(pathname, &info) != 0) return false; // path does not exist -if (S_ISDIR(info.st_mode)) return true; -return false; +bool is_directory(const char* pathname) { + struct stat info; + if (stat(pathname, &info) != 0) return false; // path does not exist + if (S_ISDIR(info.st_mode)) return true; + return false; } #endif //--------------------------------------------------------------------------- bool CheckDirectory(void) { -bool errorfolder = false; + bool errorfolder = false; -string subfolder; + string subfolder; -subfolder = paramsSim->getDir(0) + "Inputs"; -const char *inputs = subfolder.c_str(); -if (!is_directory(inputs)) errorfolder = true; -subfolder = paramsSim->getDir(0) + "Outputs"; -const char *outputs = subfolder.c_str(); -if (!is_directory(outputs)) errorfolder = true; -subfolder = paramsSim->getDir(0) + "Output_Maps"; -const char *outputmaps = subfolder.c_str(); -if (!is_directory(outputmaps)) errorfolder = true; + subfolder = paramsSim->getDir(0) + "Inputs"; + const char* inputs = subfolder.c_str(); + if (!is_directory(inputs)) errorfolder = true; + subfolder = paramsSim->getDir(0) + "Outputs"; + const char* outputs = subfolder.c_str(); + if (!is_directory(outputs)) errorfolder = true; + subfolder = paramsSim->getDir(0) + "Output_Maps"; + const char* outputmaps = subfolder.c_str(); + if (!is_directory(outputmaps)) errorfolder = true; -return errorfolder; + return errorfolder; } //--------------------------------------------------------------------------- //For outputs and population visualisations pre-reproduction -void PreReproductionOutput(Landscape *pLand,Community *pComm,int rep,int yr,int gen) +void PreReproductionOutput(Landscape* pLand, Community* pComm, int rep, int yr, int gen) { #if RSDEBUG || VCL -landParams ppLand = pLand->getLandParams(); + landParams ppLand = pLand->getLandParams(); #endif -simParams sim = paramsSim->getSim(); -simView v = paramsSim->getViews(); + simParams sim = paramsSim->getSim(); + simView v = paramsSim->getViews(); #if RSDEBUG -DEBUGLOG << "PreReproductionOutput(): 11111 rep=" << rep << " yr=" << yr << " gen=" << gen - << " landNum=" << ppLand.landNum << " maxX=" << ppLand.maxX << " maxY=" << ppLand.maxY - << endl; -DEBUGLOG << "PreReproductionOutput(): 11112 outRange=" << sim.outRange - << " outIntRange=" << sim.outIntRange - << " outPop=" << sim.outPop << " outIntPop=" << sim.outIntPop - << endl; + DEBUGLOG << "PreReproductionOutput(): 11111 rep=" << rep << " yr=" << yr << " gen=" << gen + << " landNum=" << ppLand.landNum << " maxX=" << ppLand.maxX << " maxY=" << ppLand.maxY + << endl; + DEBUGLOG << "PreReproductionOutput(): 11112 outRange=" << sim.outRange + << " outIntRange=" << sim.outIntRange + << " outPop=" << sim.outPop << " outIntPop=" << sim.outIntPop + << endl; #endif #if RSDEBUG -//DEBUGLOG << "PreReproductionOutput(): 22222 " << endl; + //DEBUGLOG << "PreReproductionOutput(): 22222 " << endl; #endif //emigCanvas ecanv; //trfrCanvas tcanv; -traitCanvas tcanv; -//for (int i = 0; i < 6; i++) { -// ecanv.pcanvas[i] = 0; tcanv.pcanvas[i] = 0; -//} -for (int i = 0; i < NTRAITS; i++) { + traitCanvas tcanv; + //for (int i = 0; i < 6; i++) { + // ecanv.pcanvas[i] = 0; tcanv.pcanvas[i] = 0; + //} + for (int i = 0; i < NTRAITS; i++) { tcanv.pcanvas[i] = 0; -} + } -// trait outputs and visualisation + // trait outputs and visualisation -if (v.viewTraits) { -// ecanv = SetupEmigCanvas(); -// tcanv = SetupTrfrCanvas(); -// tcanv = SetupTraitCanvas(v.viewGrad); - tcanv = SetupTraitCanvas(); -} + if (v.viewTraits) { + // ecanv = SetupEmigCanvas(); + // tcanv = SetupTrfrCanvas(); + // tcanv = SetupTraitCanvas(v.viewGrad); + tcanv = SetupTraitCanvas(); + } -if (v.viewTraits -|| ((sim.outTraitsCells && yr >= sim.outStartTraitCell && yr%sim.outIntTraitCell == 0) || - (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr%sim.outIntTraitRow == 0))) -{ -// pComm->outTraits(ecanv,tcanv,pSpecies,rep,yr,gen); - pComm->outTraits(tcanv,pSpecies,rep,yr,gen); -} + if (v.viewTraits + || ((sim.outTraitsCells && yr >= sim.outStartTraitCell && yr % sim.outIntTraitCell == 0) || + (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0))) + { + // pComm->outTraits(ecanv,tcanv,pSpecies,rep,yr,gen); + pComm->outTraits(tcanv, pSpecies, rep, yr, gen); + } #if RSDEBUG -//DEBUGLOG << "PreReproductionOutput(): 33333 " << endl; + //DEBUGLOG << "PreReproductionOutput(): 33333 " << endl; #endif -if (sim.outOccup && yr%sim.outIntOcc == 0 && gen == 0) - pComm->updateOccupancy(yr/sim.outIntOcc,rep); + if (sim.outOccup && yr % sim.outIntOcc == 0 && gen == 0) + pComm->updateOccupancy(yr / sim.outIntOcc, rep); #if RSDEBUG -//DEBUGLOG << "PreReproductionOutput(): 88888 " << endl; + //DEBUGLOG << "PreReproductionOutput(): 88888 " << endl; #endif // Remaining graphical output actions are performed for GUI only @@ -992,99 +992,99 @@ if (sim.outOccup && yr%sim.outIntOcc == 0 && gen == 0) } //For outputs and population visualisations pre-reproduction -void RangePopOutput(Community *pComm,int rep,int yr,int gen) +void RangePopOutput(Community* pComm, int rep, int yr, int gen) { -simParams sim = paramsSim->getSim(); + simParams sim = paramsSim->getSim(); -if (sim.outRange && (yr%sim.outIntRange == 0 || pComm->totalInds() <= 0)) - pComm->outRange(pSpecies,rep,yr,gen); + if (sim.outRange && (yr % sim.outIntRange == 0 || pComm->totalInds() <= 0)) + pComm->outRange(pSpecies, rep, yr, gen); -if (sim.outPop && yr >= sim.outStartPop && yr%sim.outIntPop == 0) - pComm->outPop(rep,yr,gen); + if (sim.outPop && yr >= sim.outStartPop && yr % sim.outIntPop == 0) + pComm->outPop(rep, yr, gen); } //--------------------------------------------------------------------------- -void OutParameters(Landscape *pLandscape) +void OutParameters(Landscape* pLandscape) { -double k; -//int nrows,ncols,nsexes,nstages; -int nsexes,nstages; - -landParams ppLand = pLandscape->getLandParams(); -genLandParams ppGenLand = pLandscape->getGenLandParams(); -envGradParams grad = paramsGrad->getGradient(); -envStochParams env = paramsStoch->getStoch(); -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -settleRules srules; -settleSteps ssteps; -settleTraits settleDD; -simParams sim = paramsSim->getSim(); - -string name; -if (sim.batchMode) - name = paramsSim->getDir(2) + double k; + //int nrows,ncols,nsexes,nstages; + int nsexes, nstages; + + landParams ppLand = pLandscape->getLandParams(); + genLandParams ppGenLand = pLandscape->getGenLandParams(); + envGradParams grad = paramsGrad->getGradient(); + envStochParams env = paramsStoch->getStoch(); + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + settleRules srules; + settleSteps ssteps; + settleTraits settleDD; + simParams sim = paramsSim->getSim(); + + string name; + if (sim.batchMode) + name = paramsSim->getDir(2) + "Batch" + Int2Str(sim.batchNum) + "_" + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(ppLand.landNum) + "_Parameters.txt"; -else - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Parameters.txt"; -outPar.open(name.c_str()); + else + name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Parameters.txt"; + outPar.open(name.c_str()); -outPar << "RangeShifter 2.0 "; + outPar << "RangeShifter 2.0 "; #if !RS_RCPP #if RSWIN64 -outPar << " - 64 bit implementation"; + outPar << " - 64 bit implementation"; #else -outPar << " - 32 bit implementation"; + outPar << " - 32 bit implementation"; #endif #endif -outPar << endl; + outPar << endl; -outPar << "================ "; + outPar << "================ "; -outPar << " ====================="; -outPar << endl << endl; + outPar << " ====================="; + outPar << endl << endl; -outPar << "BATCH MODE \t"; -if (sim.batchMode) outPar << "yes" << endl; else outPar << "no" << endl; + outPar << "BATCH MODE \t"; + if (sim.batchMode) outPar << "yes" << endl; else outPar << "no" << endl; #if RS_RCPP -outPar << "SEED \t" << RS_random_seed << endl; -#endif -outPar << "REPLICATES \t" << sim.reps << endl; -outPar << "YEARS \t" << sim.years << endl; -outPar << "REPRODUCTIVE SEASONS / YEAR\t" << dem.repSeasons << endl; -if (ppLand.patchModel){ - outPar << "PATCH-BASED MODEL" << endl; - outPar << "No. PATCHES \t" << pLandscape->patchCount()-1 << endl; -} -else - outPar << "CELL-BASED MODEL" << endl; -outPar << "BOUNDARIES \t"; -if (sim.absorbing) outPar << "absorbing" << endl; -else outPar << "reflective" << endl; -outPar << endl; - -outPar << "LANDSCAPE:\t"; -if (ppLand.generated) { - outPar << "artificially generated map" << endl; - outPar << "TYPE: \t"; - if (ppGenLand.continuous) outPar << "continuous \t"; - else outPar << "discrete \t"; - if (ppGenLand.fractal) outPar << "fractal"; - else outPar << "random"; - outPar << endl << "PROPORTION OF SUITABLE HABITAT (p)\t" << ppGenLand.propSuit <patchCount() - 1 << endl; + } + else + outPar << "CELL-BASED MODEL" << endl; + outPar << "BOUNDARIES \t"; + if (sim.absorbing) outPar << "absorbing" << endl; + else outPar << "reflective" << endl; + outPar << endl; + + outPar << "LANDSCAPE:\t"; + if (ppLand.generated) { + outPar << "artificially generated map" << endl; + outPar << "TYPE: \t"; + if (ppGenLand.continuous) outPar << "continuous \t"; + else outPar << "discrete \t"; + if (ppGenLand.fractal) outPar << "fractal"; + else outPar << "random"; + outPar << endl << "PROPORTION OF SUITABLE HABITAT (p)\t" << ppGenLand.propSuit << endl; + if (ppGenLand.fractal) outPar << "HURST EXPONENT\t" << ppGenLand.hurst << endl; + } + else { + outPar << "imported map" << endl; + outPar << "TYPE: \t"; + switch (ppLand.rasterType) { case 0: outPar << "habitat codes" << endl; break; @@ -1094,165 +1094,165 @@ else { case 2: outPar << "habitat quality" << endl; break; - } - outPar << "FILE NAME: "; + } + outPar << "FILE NAME: "; #if RS_RCPP - if (ppLand.dynamic) { - outPar << name_landscape << endl; - } - else{ - outPar << name_landscape << endl; - } - if (ppLand.patchModel) { - outPar << "PATCH FILE: " << name_patch << endl; - } - if (trfr.costMap) { - outPar << "COSTS FILE: " << name_costfile << endl; - } -#else - if (sim.batchMode) outPar << " (see batch file) " << landFile << endl; - else { - outPar << habmapname << endl; - if (ppLand.rasterType == 1) { // habitat % cover - list additional layers - for (int i = 0; i < ppLand.nHab-1; i++) { - outPar << " "<< hfnames[i] << endl; - } + if (ppLand.dynamic) { + outPar << name_landscape << endl; } - if (ppLand.patchModel) { - outPar << "PATCH FILE: " << patchmapname << endl; + else { + outPar << name_landscape << endl; } - } -#endif - outPar << "No. HABITATS:\t" << ppLand.nHab << endl; -} -outPar << "RESOLUTION (m): \t" << ppLand.resol << endl; -outPar << "DIMENSIONS: X " << ppLand.dimX << " Y " << ppLand.dimY << endl; -outPar << "AVAILABLE: min.X " << ppLand.minX << " min.Y " << ppLand.minY - << " max.X " << ppLand.maxX << " max.Y " << ppLand.maxY << endl; -if (!ppLand.generated && ppLand.dynamic) { - landChange chg; - outPar << "DYNAMIC LANDSCAPE: " << endl; - int nchanges = pLandscape->numLandChanges(); - for (int i = 0; i < nchanges; i++) { - chg = pLandscape->getLandChange(i); - outPar << "Change no. " << chg.chgnum << " in year " << chg.chgyear << endl; - outPar << "Landscape: " << chg.habfile << endl; if (ppLand.patchModel) { - outPar << "Patches : " << chg.pchfile << endl; + outPar << "PATCH FILE: " << name_patch << endl; + } + if (trfr.costMap) { + outPar << "COSTS FILE: " << name_costfile << endl; } - if (chg.costfile != "none" && chg.costfile != "NULL") { - outPar << "Costs : " << chg.costfile << endl; +#else + if (sim.batchMode) outPar << " (see batch file) " << landFile << endl; + else { + outPar << habmapname << endl; + if (ppLand.rasterType == 1) { // habitat % cover - list additional layers + for (int i = 0; i < ppLand.nHab - 1; i++) { + outPar << " " << hfnames[i] << endl; + } + } + if (ppLand.patchModel) { + outPar << "PATCH FILE: " << patchmapname << endl; + } + } +#endif + outPar << "No. HABITATS:\t" << ppLand.nHab << endl; + } + outPar << "RESOLUTION (m): \t" << ppLand.resol << endl; + outPar << "DIMENSIONS: X " << ppLand.dimX << " Y " << ppLand.dimY << endl; + outPar << "AVAILABLE: min.X " << ppLand.minX << " min.Y " << ppLand.minY + << " max.X " << ppLand.maxX << " max.Y " << ppLand.maxY << endl; + if (!ppLand.generated && ppLand.dynamic) { + landChange chg; + outPar << "DYNAMIC LANDSCAPE: " << endl; + int nchanges = pLandscape->numLandChanges(); + for (int i = 0; i < nchanges; i++) { + chg = pLandscape->getLandChange(i); + outPar << "Change no. " << chg.chgnum << " in year " << chg.chgyear << endl; + outPar << "Landscape: " << chg.habfile << endl; + if (ppLand.patchModel) { + outPar << "Patches : " << chg.pchfile << endl; + } + if (chg.costfile != "none" && chg.costfile != "NULL") { + outPar << "Costs : " << chg.costfile << endl; + } + // outPar << "Change no. " << chg.chgnum << " in year " << chg.chgyear + // << " habitat map: " << chg.habfile << endl; } -// outPar << "Change no. " << chg.chgnum << " in year " << chg.chgyear -// << " habitat map: " << chg.habfile << endl; } -} -outPar << endl << "SPECIES DISTRIBUTION LOADED: \t"; -//if (sim.initDistLoaded) -if (ppLand.spDist) -{ - outPar << "yes" << endl; - outPar << "RESOLUTION (m)\t" << ppLand.spResol << endl; - outPar << "FILE NAME: "; + outPar << endl << "SPECIES DISTRIBUTION LOADED: \t"; + //if (sim.initDistLoaded) + if (ppLand.spDist) + { + outPar << "yes" << endl; + outPar << "RESOLUTION (m)\t" << ppLand.spResol << endl; + outPar << "FILE NAME: "; #if !RS_RCPP - if (sim.batchMode) outPar << " (see batch file) " << landFile << endl; - else { - outPar << distnmapname << endl; - } + if (sim.batchMode) outPar << " (see batch file) " << landFile << endl; + else { + outPar << distnmapname << endl; + } #else - outPar << name_sp_dist << endl; + outPar << name_sp_dist << endl; #endif -} -else outPar << "no" << endl; + } + else outPar << "no" << endl; -outPar << endl << "ENVIRONMENTAL GRADIENT:\t "; -if (grad.gradient) -{ - switch (grad.gradType) { - case 1: - if (dem.stageStruct) outPar << "Density dependence strength (1/b)" << endl; - else outPar << "Carrying capacity (K)" << endl; - break; - case 2: - if (dem.stageStruct) outPar << "Fecundity" << endl; - else outPar << "Intrinsic growth rate (r)" << endl; - break; - case 3: - outPar << "Local extinction probability" << endl; - break; - default: - outPar << "ERROR ERROR ERROR" << endl; - ; - } - outPar << "G:\t\t " << grad.grad_inc << endl; - outPar << "optimum Y:\t " << grad.opt_y << endl; - outPar << "f:\t\t " << grad.factor << endl; - if (grad.gradType == 3) outPar << "Local extinction prob. at optimum:\t " - << grad.extProbOpt << endl; - outPar << "GRADIENT SHIFTING:\t "; - if (grad.shifting) + outPar << endl << "ENVIRONMENTAL GRADIENT:\t "; + if (grad.gradient) { - outPar << "yes" << endl; - outPar << "SHIFTING RATE (rows/year):\t " << grad.shift_rate << endl; - outPar << "SHIFTING START (year):\t\t " << grad.shift_begin << endl; - outPar << "SHIFTING STOP (year):\t\t " << grad.shift_stop << endl; - } - else outPar << "no" << endl; -} -else outPar << "no"; -outPar << endl; -outPar << "ENVIRONMENTAL STOCHASTICITY:\t"; -if (env.stoch) { - outPar << "yes" << endl; - outPar << "TYPE\t in "; - if (dem.stageStruct) { - if (env.inK) outPar << "1/b" << endl; - else outPar << "fecundity" << endl; - } - else{ - if (env.inK) outPar << "K" << endl; - else outPar << "R" << endl; + switch (grad.gradType) { + case 1: + if (dem.stageStruct) outPar << "Density dependence strength (1/b)" << endl; + else outPar << "Carrying capacity (K)" << endl; + break; + case 2: + if (dem.stageStruct) outPar << "Fecundity" << endl; + else outPar << "Intrinsic growth rate (r)" << endl; + break; + case 3: + outPar << "Local extinction probability" << endl; + break; + default: + outPar << "ERROR ERROR ERROR" << endl; + ; + } + outPar << "G:\t\t " << grad.grad_inc << endl; + outPar << "optimum Y:\t " << grad.opt_y << endl; + outPar << "f:\t\t " << grad.factor << endl; + if (grad.gradType == 3) outPar << "Local extinction prob. at optimum:\t " + << grad.extProbOpt << endl; + outPar << "GRADIENT SHIFTING:\t "; + if (grad.shifting) + { + outPar << "yes" << endl; + outPar << "SHIFTING RATE (rows/year):\t " << grad.shift_rate << endl; + outPar << "SHIFTING START (year):\t\t " << grad.shift_begin << endl; + outPar << "SHIFTING STOP (year):\t\t " << grad.shift_stop << endl; + } + else outPar << "no" << endl; } - outPar << "SPATIAL AUTOCORRELATION\t "; - if (env.local) outPar << "local" << endl; - else outPar << "global" << endl; - outPar << "TEMPORAL AUTOCORRELATION (ac)\t" << env.ac << endl; - outPar << "AMPLITUDE (std)\t" << env.std << endl; - if (dem.stageStruct) { - if (env.inK) { - outPar << "MIN. 1/b\t" << pSpecies->getMinMax(0) - * (10000.0/(float)(ppLand.resol*ppLand.resol)) << endl; - outPar << "MAX. 1/b\t" << pSpecies->getMinMax(1) - * (10000.0/(float)(ppLand.resol*ppLand.resol)) << endl; + else outPar << "no"; + outPar << endl; + outPar << "ENVIRONMENTAL STOCHASTICITY:\t"; + if (env.stoch) { + outPar << "yes" << endl; + outPar << "TYPE\t in "; + if (dem.stageStruct) { + if (env.inK) outPar << "1/b" << endl; + else outPar << "fecundity" << endl; } else { - outPar << "MIN. fecundity\t" << pSpecies->getMinMax(0) << endl; - outPar << "MAX. fecundity\t" << pSpecies->getMinMax(1) << endl; - } - } - else { - if (env.inK) { - outPar << "MIN. K\t" << pSpecies->getMinMax(0) - * (10000.0/(float)(ppLand.resol*ppLand.resol)) << endl; - outPar << "MAX. K\t" << pSpecies->getMinMax(1) - * (10000.0/(float)(ppLand.resol*ppLand.resol)) << endl; + if (env.inK) outPar << "K" << endl; + else outPar << "R" << endl; + } + outPar << "SPATIAL AUTOCORRELATION\t "; + if (env.local) outPar << "local" << endl; + else outPar << "global" << endl; + outPar << "TEMPORAL AUTOCORRELATION (ac)\t" << env.ac << endl; + outPar << "AMPLITUDE (std)\t" << env.std << endl; + if (dem.stageStruct) { + if (env.inK) { + outPar << "MIN. 1/b\t" << pSpecies->getMinMax(0) + * (10000.0 / (float)(ppLand.resol * ppLand.resol)) << endl; + outPar << "MAX. 1/b\t" << pSpecies->getMinMax(1) + * (10000.0 / (float)(ppLand.resol * ppLand.resol)) << endl; + } + else { + outPar << "MIN. fecundity\t" << pSpecies->getMinMax(0) << endl; + outPar << "MAX. fecundity\t" << pSpecies->getMinMax(1) << endl; + } } else { - outPar << "MIN. r\t" << pSpecies->getMinMax(0) << endl; - outPar << "MAX. r\t" << pSpecies->getMinMax(1) << endl; + if (env.inK) { + outPar << "MIN. K\t" << pSpecies->getMinMax(0) + * (10000.0 / (float)(ppLand.resol * ppLand.resol)) << endl; + outPar << "MAX. K\t" << pSpecies->getMinMax(1) + * (10000.0 / (float)(ppLand.resol * ppLand.resol)) << endl; + } + else { + outPar << "MIN. r\t" << pSpecies->getMinMax(0) << endl; + outPar << "MAX. r\t" << pSpecies->getMinMax(1) << endl; + } } } -} -else outPar << "no" << endl; -outPar << "LOCAL EXTINCTION PROBABILITY:\t"; -if (env.localExt) outPar << env.locExtProb << endl; -else outPar << "0.0" << endl; - -outPar << endl << "SPECIES' PARAMETERS." << endl; -outPar << "REPRODUCTION:" << endl; -outPar << "TYPE: "; -switch (dem.repType) { + else outPar << "no" << endl; + outPar << "LOCAL EXTINCTION PROBABILITY:\t"; + if (env.localExt) outPar << env.locExtProb << endl; + else outPar << "0.0" << endl; + + outPar << endl << "SPECIES' PARAMETERS." << endl; + outPar << "REPRODUCTION:" << endl; + outPar << "TYPE: "; + switch (dem.repType) { case 0: outPar << "Asexual / Only female model" << endl; break; @@ -1265,854 +1265,854 @@ switch (dem.repType) { outPar << "Sexual model (explicit mating system)" << endl; outPar << "PROP. of MALES\t" << dem.propMales << endl; outPar << "MAX. HAREM SIZE (h)\t" << dem.harem << endl; - break; -} -outPar << "STAGE STRUCTURE:\t"; -if (dem.stageStruct){ - outPar << "yes" << endl; - outPar << "PROBABILITY OF REPRODUCING IN SUBSEQUENT SEASONS\t" << sstruct.probRep << endl; - outPar << "No. OF REP. SEASONS BEFORE SUBSEQUENT REPRODUCTIONS\t" << sstruct.repInterval << endl; - if (!ppLand.generated && ppLand.dynamic) { - outPar << "ACTION AFTER POPULATION DESTRUCTION: all individuals "; - if (sstruct.disperseOnLoss) outPar << "disperse" << endl; - else outPar << "die" << endl; - } - outPar << "No. STAGES\t" << sstruct.nStages << endl; - outPar << "MAX. AGE\t" << sstruct.maxAge << endl; - // no sex-specific demographic parameters - if (dem.repType != 2) { - outPar << "MIN. AGES:" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "stage\t" << i << ":\t" << pSpecies->getMinAge(i,0) << "\tyears"<< endl; - } - outPar << "FECUNDITIES:" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "stage\t" << i << ":\t" << pSpecies->getFec(i,0) << endl; - } - outPar << "DEVELOPMENT PROB.:" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "stage\t" << i << ":\t" << pSpecies->getDev(i,0) << endl; - } - outPar << "SURVIVAL PROB.:" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "stage\t" << i << ":\t" << pSpecies->getSurv(i,0) << endl; - } - } - // sex-specific demographic parameters - else { - outPar << "MIN. AGES:" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "males " << i << ":\t" << pSpecies->getMinAge(i,1) << " years;\t"; - outPar << "females " << i << ":\t" << pSpecies->getMinAge(i,0) << " years" << endl; - } - outPar << "FECUNDITIES:" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "males " << i << ":\t" << pSpecies->getFec(i,1) << endl; - outPar << "females " << i << ":\t" << pSpecies->getFec(i,0) << endl; - } - outPar << "DEVELOPMENT PROB.:" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "males " << i << ":\t" << pSpecies->getDev(i,1) << endl; - outPar << "females " << i << ":\t" << pSpecies->getDev(i,0) << endl; - } - outPar << "SURVIVAL PROB.:" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "males " << i << ":\t" << pSpecies->getSurv(i,1) << endl; - outPar << "females " << i << ":\t" << pSpecies->getSurv(i,0) << endl; - } + break; } -/* -#if RSDEBUG - outPar << endl << "TRANSITION MATRIX AS ENTERED:" << endl; - if (batchMode) { - DEBUGLOG << "outParameters(): matrix = " << matrix - << " matrix[1][1] = " << matrix[1][1] - << endl; - if (dem.repType == 2) { - nrows = sstruct.nStages*2-1; ncols = sstruct.nStages*2; + outPar << "STAGE STRUCTURE:\t"; + if (dem.stageStruct) { + outPar << "yes" << endl; + outPar << "PROBABILITY OF REPRODUCING IN SUBSEQUENT SEASONS\t" << sstruct.probRep << endl; + outPar << "No. OF REP. SEASONS BEFORE SUBSEQUENT REPRODUCTIONS\t" << sstruct.repInterval << endl; + if (!ppLand.generated && ppLand.dynamic) { + outPar << "ACTION AFTER POPULATION DESTRUCTION: all individuals "; + if (sstruct.disperseOnLoss) outPar << "disperse" << endl; + else outPar << "die" << endl; + } + outPar << "No. STAGES\t" << sstruct.nStages << endl; + outPar << "MAX. AGE\t" << sstruct.maxAge << endl; + // no sex-specific demographic parameters + if (dem.repType != 2) { + outPar << "MIN. AGES:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "stage\t" << i << ":\t" << pSpecies->getMinAge(i, 0) << "\tyears" << endl; + } + outPar << "FECUNDITIES:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "stage\t" << i << ":\t" << pSpecies->getFec(i, 0) << endl; + } + outPar << "DEVELOPMENT PROB.:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "stage\t" << i << ":\t" << pSpecies->getDev(i, 0) << endl; + } + outPar << "SURVIVAL PROB.:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "stage\t" << i << ":\t" << pSpecies->getSurv(i, 0) << endl; + } } + // sex-specific demographic parameters else { - nrows = sstruct.nStages; ncols = sstruct.nStages; - } - for (int i = 0; i < nrows; i++) { - for (int j = 0; j < ncols; j++) { - outPar << matrix[j][i] << "\t"; + outPar << "MIN. AGES:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "males " << i << ":\t" << pSpecies->getMinAge(i, 1) << " years;\t"; + outPar << "females " << i << ":\t" << pSpecies->getMinAge(i, 0) << " years" << endl; + } + outPar << "FECUNDITIES:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "males " << i << ":\t" << pSpecies->getFec(i, 1) << endl; + outPar << "females " << i << ":\t" << pSpecies->getFec(i, 0) << endl; + } + outPar << "DEVELOPMENT PROB.:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "males " << i << ":\t" << pSpecies->getDev(i, 1) << endl; + outPar << "females " << i << ":\t" << pSpecies->getDev(i, 0) << endl; + } + outPar << "SURVIVAL PROB.:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "males " << i << ":\t" << pSpecies->getSurv(i, 1) << endl; + outPar << "females " << i << ":\t" << pSpecies->getSurv(i, 0) << endl; } - outPar << endl; } - } -#if VCL - else { + /* + #if RSDEBUG + outPar << endl << "TRANSITION MATRIX AS ENTERED:" << endl; + if (batchMode) { + DEBUGLOG << "outParameters(): matrix = " << matrix + << " matrix[1][1] = " << matrix[1][1] + << endl; + if (dem.repType == 2) { + nrows = sstruct.nStages*2-1; ncols = sstruct.nStages*2; + } + else { + nrows = sstruct.nStages; ncols = sstruct.nStages; + } + for (int i = 0; i < nrows; i++) { + for (int j = 0; j < ncols; j++) { + outPar << matrix[j][i] << "\t"; + } + outPar << endl; + } + } + #if VCL + else { - // NOTE: TO PREVENT COMPILING FOR BATCH MODE, THIS CODE NEEDS TO BE INCLUDED IN COMPILER - // CONDITIONAL BLOCK AS SHOWN + // NOTE: TO PREVENT COMPILING FOR BATCH MODE, THIS CODE NEEDS TO BE INCLUDED IN COMPILER + // CONDITIONAL BLOCK AS SHOWN -// outPar << "Row count: " << frmSpecies->transMatrix->RowCount << endl; -// outPar << "Col count: " << frmSpecies->transMatrix->ColCount << endl; - for (int i = 1; i < frmSpecies->transMatrix->RowCount; i++) { - for (int j = 1; j < frmSpecies->transMatrix->ColCount; j++) { - outPar << frmSpecies->transMatrix->Cells[j][i].ToDouble() << "\t"; + // outPar << "Row count: " << frmSpecies->transMatrix->RowCount << endl; + // outPar << "Col count: " << frmSpecies->transMatrix->ColCount << endl; + for (int i = 1; i < frmSpecies->transMatrix->RowCount; i++) { + for (int j = 1; j < frmSpecies->transMatrix->ColCount; j++) { + outPar << frmSpecies->transMatrix->Cells[j][i].ToDouble() << "\t"; + } + outPar << endl; + } } + #endif outPar << endl; - } - } -#endif - outPar << endl; -#endif -*/ - - outPar << "SCHEDULING OF SURVIVAL: "; - switch (sstruct.survival) { - case 0: - outPar << "At reproduction" << endl; - break; - case 1: - outPar << "Between reproductive events" << endl; - break; - case 2: - outPar << "Annually" << endl; - break; - } + #endif + */ - int mSize; // index for weights matrices - if (dem.repType == 2) mSize = sstruct.nStages * NSEXES; - else mSize = sstruct.nStages; + outPar << "SCHEDULING OF SURVIVAL: "; + switch (sstruct.survival) { + case 0: + outPar << "At reproduction" << endl; + break; + case 1: + outPar << "Between reproductive events" << endl; + break; + case 2: + outPar << "Annually" << endl; + break; + } - outPar << "DENSITY-DEPENDENCE IN FECUNDITY:\t"; - if (sstruct.fecDens) { - outPar << "yes" << endl; - if (sstruct.fecStageDens) { - outPar << "STAGE'S WEIGHTS:" << endl; - for (int i = 0; i < mSize; i++) { - if (dem.repType == 2) { - outPar << "stage " << i/NSEXES << " "; - if (i%NSEXES == 0) outPar << "males : \t"; - else outPar << "females: \t"; + int mSize; // index for weights matrices + if (dem.repType == 2) mSize = sstruct.nStages * NSEXES; + else mSize = sstruct.nStages; + + outPar << "DENSITY-DEPENDENCE IN FECUNDITY:\t"; + if (sstruct.fecDens) { + outPar << "yes" << endl; + if (sstruct.fecStageDens) { + outPar << "STAGE'S WEIGHTS:" << endl; + for (int i = 0; i < mSize; i++) { + if (dem.repType == 2) { + outPar << "stage " << i / NSEXES << " "; + if (i % NSEXES == 0) outPar << "males : \t"; + else outPar << "females: \t"; + } + else outPar << "stage " << i << ": \t"; + for (int j = 0; j < mSize; j++) outPar << pSpecies->getDDwtFec(j, i) << "\t"; + outPar << endl; } - else outPar << "stage " << i << ": \t"; - for (int j = 0; j < mSize; j++) outPar << pSpecies->getDDwtFec(j,i) << "\t"; - outPar << endl; } + else outPar << "not stage-dependent" << endl; } - else outPar << "not stage-dependent" << endl; - } - else outPar << "no" << endl; + else outPar << "no" << endl; - densDepParams ddparams = pSpecies->getDensDep(); + densDepParams ddparams = pSpecies->getDensDep(); - outPar << "DENSITY-DEPENDENCE IN DEVELOPMENT:\t"; - if (sstruct.devDens) { - outPar << "yes - coefficient: " << ddparams.devCoeff << endl; - if (sstruct.devStageDens) { - outPar << "STAGE'S WEIGHTS:" << endl; - for (int i = 0; i < mSize; i++) { - if (dem.repType == 2) { - outPar << "stage " << i/NSEXES << " "; - if (i%NSEXES == 0) outPar << "males : \t"; - else outPar << "females: \t"; + outPar << "DENSITY-DEPENDENCE IN DEVELOPMENT:\t"; + if (sstruct.devDens) { + outPar << "yes - coefficient: " << ddparams.devCoeff << endl; + if (sstruct.devStageDens) { + outPar << "STAGE'S WEIGHTS:" << endl; + for (int i = 0; i < mSize; i++) { + if (dem.repType == 2) { + outPar << "stage " << i / NSEXES << " "; + if (i % NSEXES == 0) outPar << "males : \t"; + else outPar << "females: \t"; + } + else outPar << "stage " << i << ": \t"; + for (int j = 0; j < mSize; j++) outPar << pSpecies->getDDwtDev(j, i) << "\t"; + outPar << endl; } - else outPar << "stage " << i << ": \t"; - for (int j = 0; j < mSize; j++) outPar << pSpecies->getDDwtDev(j,i) << "\t"; - outPar << endl; } + else outPar << "not stage-dependent" << endl; } - else outPar << "not stage-dependent" << endl; - } - else outPar << "no" << endl; + else outPar << "no" << endl; - outPar << "DENSITY-DEPENDENCE IN SURVIVAL:\t\t"; - if (sstruct.survDens) { - outPar << "yes - coefficient: " << ddparams.survCoeff << endl; - if (sstruct.survStageDens) { - outPar << "STAGE'S WEIGHTS:" << endl; - for (int i = 0; i < mSize; i++) { - if (dem.repType == 2) { - outPar << "stage " << i/NSEXES << " "; - if (i%NSEXES == 0) outPar << "males : \t"; - else outPar << "females: \t"; + outPar << "DENSITY-DEPENDENCE IN SURVIVAL:\t\t"; + if (sstruct.survDens) { + outPar << "yes - coefficient: " << ddparams.survCoeff << endl; + if (sstruct.survStageDens) { + outPar << "STAGE'S WEIGHTS:" << endl; + for (int i = 0; i < mSize; i++) { + if (dem.repType == 2) { + outPar << "stage " << i / NSEXES << " "; + if (i % NSEXES == 0) outPar << "males : \t"; + else outPar << "females: \t"; + } + else outPar << "stage " << i << ": \t"; + for (int j = 0; j < mSize; j++) outPar << pSpecies->getDDwtSurv(j, i) << "\t"; + outPar << endl; } - else outPar << "stage " << i << ": \t"; - for (int j = 0; j < mSize; j++) outPar << pSpecies->getDDwtSurv(j,i) << "\t"; - outPar << endl; } + else outPar << "not stage-dependent" << endl; } - else outPar << "not stage-dependent" << endl; + else outPar << "no" << endl; + } // end of if (dem.stageStruct) + else { // not stage-strutured + outPar << "no" << endl; + outPar << "Rmax\t" << dem.lambda << endl; + outPar << "bc\t" << dem.bc << endl; } - else outPar << "no" << endl; -} // end of if (dem.stageStruct) -else { // not stage-strutured - outPar << "no" << endl; - outPar << "Rmax\t" << dem.lambda << endl; - outPar << "bc\t" << dem.bc << endl; -} -if (dem.stageStruct) { - outPar << endl << "HABITAT SPECIFIC 1/b:" << endl; -} -else { - outPar << endl << "CARRYING CAPACITIES:" << endl; -} -int nhab = ppLand.nHab; -if (ppLand.generated) { - if (ppGenLand.continuous) nhab = 1; -} -for (int i = 0; i < nhab; i++) { - k = pSpecies->getHabK(i) * (10000.0/(float)(ppLand.resol*ppLand.resol)); - if (!ppLand.generated && ppLand.rasterType == 0) { // imported & habitat codes - outPar << "Habitat " << pLandscape->getHabCode(i) << ": \t"; + if (dem.stageStruct) { + outPar << endl << "HABITAT SPECIFIC 1/b:" << endl; } else { - outPar << "Habitat " << i << ": "; + outPar << endl << "CARRYING CAPACITIES:" << endl; } - if (dem.stageStruct) outPar << "1/b "; - else outPar << "K "; - outPar << k << endl; -} - -emigTraits ep0,ep1; -emigParams eparams0,eparams1; -string sexdept = "SEX-DEPENDENT: "; -string stgdept = "STAGE-DEPENDENT: "; -string indvar = "INDIVIDUAL VARIABILITY: "; -string emigstage = "EMIGRATION STAGE: "; - -outPar << endl << "DISPERSAL - EMIGRATION:\t"; -if (emig.densDep) { - outPar << "density-dependent" << endl; - - if (emig.sexDep) { - outPar << sexdept << "yes" << endl; - if (emig.stgDep) { - outPar << stgdept << "yes" << endl; - outPar << indvar << "no" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "stage " << i << ":" << endl; - ep0 = pSpecies->getEmigTraits(i,0); - ep1 = pSpecies->getEmigTraits(i,1); - outPar << "D0: females "<< ep0.d0 << " males " << ep1.d0 << endl; - outPar << "alpha: females "<< ep0.alpha << " males " << ep1.alpha << endl; - outPar << "beta: females "<< ep0.beta << " males " << ep1.beta << endl; - } - } - else { // !emig.stgDep - outPar << stgdept << "no" << endl; - outPar << indvar; - if (emig.indVar) { - eparams0 = pSpecies->getEmigParams(0,0); - eparams1 = pSpecies->getEmigParams(0,1); - outPar << "yes" << endl; - if (dem.stageStruct) { - outPar << emigstage << emig.emigStage << endl; - } - outPar << "D0 females: mean " << eparams0.d0Mean << " s.d. " << eparams0.d0SD - << " scaling factor " << eparams0.d0Scale << endl; - outPar << "D0 males: mean " << eparams1.d0Mean << " s.d. " << eparams1.d0SD - << " scaling factor " << eparams1.d0Scale << endl; - outPar << "Alpha females: mean " << eparams0.alphaMean << " s.d. " << eparams0.alphaSD - << " scaling factor " << eparams0.alphaScale << endl; - outPar << "Alpha males: mean " << eparams1.alphaMean << " s.d. " << eparams1.alphaSD - << " scaling factor " << eparams1.alphaScale << endl; - outPar << "Beta females: mean " << eparams0.betaMean << " s.d. " << eparams0.betaSD - << " scaling factor " << eparams0.betaScale << endl; - outPar << "Beta males: mean " << eparams1.betaMean << " s.d. " << eparams1.betaSD - << " scaling factor " << eparams1.betaScale << endl; + int nhab = ppLand.nHab; + if (ppLand.generated) { + if (ppGenLand.continuous) nhab = 1; + } + for (int i = 0; i < nhab; i++) { + k = pSpecies->getHabK(i) * (10000.0 / (float)(ppLand.resol * ppLand.resol)); + if (!ppLand.generated && ppLand.rasterType == 0) { // imported & habitat codes + outPar << "Habitat " << pLandscape->getHabCode(i) << ": \t"; + } + else { + outPar << "Habitat " << i << ": "; + } + if (dem.stageStruct) outPar << "1/b "; + else outPar << "K "; + outPar << k << endl; + } + + emigTraits ep0, ep1; + emigParams eparams0, eparams1; + string sexdept = "SEX-DEPENDENT: "; + string stgdept = "STAGE-DEPENDENT: "; + string indvar = "INDIVIDUAL VARIABILITY: "; + string emigstage = "EMIGRATION STAGE: "; + + outPar << endl << "DISPERSAL - EMIGRATION:\t"; + if (emig.densDep) { + outPar << "density-dependent" << endl; + + if (emig.sexDep) { + outPar << sexdept << "yes" << endl; + if (emig.stgDep) { + outPar << stgdept << "yes" << endl; + outPar << indvar << "no" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "stage " << i << ":" << endl; + ep0 = pSpecies->getEmigTraits(i, 0); + ep1 = pSpecies->getEmigTraits(i, 1); + outPar << "D0: females " << ep0.d0 << " males " << ep1.d0 << endl; + outPar << "alpha: females " << ep0.alpha << " males " << ep1.alpha << endl; + outPar << "beta: females " << ep0.beta << " males " << ep1.beta << endl; + } } - else { - outPar << "no" << endl; - ep0 = pSpecies->getEmigTraits(0,0); - ep1 = pSpecies->getEmigTraits(0,1); - outPar << "D0: females "<< ep0.d0 << " males " << ep1.d0 << endl; - outPar << "alpha: females "<< ep0.alpha << " males " << ep1.alpha << endl; - outPar << "beta: females "<< ep0.beta << " males " << ep1.beta << endl; + else { // !emig.stgDep + outPar << stgdept << "no" << endl; + outPar << indvar; + if (emig.indVar) { + eparams0 = pSpecies->getEmigParams(0, 0); + eparams1 = pSpecies->getEmigParams(0, 1); + outPar << "yes" << endl; + if (dem.stageStruct) { + outPar << emigstage << emig.emigStage << endl; + } + outPar << "D0 females: mean " << eparams0.d0Mean << " s.d. " << eparams0.d0SD + << " scaling factor " << eparams0.d0Scale << endl; + outPar << "D0 males: mean " << eparams1.d0Mean << " s.d. " << eparams1.d0SD + << " scaling factor " << eparams1.d0Scale << endl; + outPar << "Alpha females: mean " << eparams0.alphaMean << " s.d. " << eparams0.alphaSD + << " scaling factor " << eparams0.alphaScale << endl; + outPar << "Alpha males: mean " << eparams1.alphaMean << " s.d. " << eparams1.alphaSD + << " scaling factor " << eparams1.alphaScale << endl; + outPar << "Beta females: mean " << eparams0.betaMean << " s.d. " << eparams0.betaSD + << " scaling factor " << eparams0.betaScale << endl; + outPar << "Beta males: mean " << eparams1.betaMean << " s.d. " << eparams1.betaSD + << " scaling factor " << eparams1.betaScale << endl; + } + else { + outPar << "no" << endl; + ep0 = pSpecies->getEmigTraits(0, 0); + ep1 = pSpecies->getEmigTraits(0, 1); + outPar << "D0: females " << ep0.d0 << " males " << ep1.d0 << endl; + outPar << "alpha: females " << ep0.alpha << " males " << ep1.alpha << endl; + outPar << "beta: females " << ep0.beta << " males " << ep1.beta << endl; + } } } - } - else { // !emig.sexDep - outPar << sexdept << "no" << endl; - if (emig.stgDep) { - outPar << stgdept << "yes" << endl; - outPar << indvar << "no" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - ep0 = pSpecies->getEmigTraits(i,0); - outPar << "stage " << i << ": \t" << "D0: " << ep0.d0; - outPar<< " \talpha: " << ep0.alpha << " \tbeta: " << ep0.beta << endl; - } - } - else { // !emig.stgDep - outPar << stgdept << "no" << endl; - outPar << indvar; - if (emig.indVar) { - eparams0 = pSpecies->getEmigParams(0,0); - emigScales scale = pSpecies->getEmigScales(); - outPar << "yes" << endl; - if (dem.stageStruct) { - outPar << emigstage << emig.emigStage << endl; + else { // !emig.sexDep + outPar << sexdept << "no" << endl; + if (emig.stgDep) { + outPar << stgdept << "yes" << endl; + outPar << indvar << "no" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + ep0 = pSpecies->getEmigTraits(i, 0); + outPar << "stage " << i << ": \t" << "D0: " << ep0.d0; + outPar << " \talpha: " << ep0.alpha << " \tbeta: " << ep0.beta << endl; } - outPar << "D0 mean: " << eparams0.d0Mean << " s.d.: " << eparams0.d0SD - << " scaling factor: " << scale.d0Scale << endl; - outPar << "Alpha mean: " << eparams0.alphaMean << " s.d.: " << eparams0.alphaSD - << " scaling factor: " << scale.alphaScale << endl; - outPar << "Beta mean: " << eparams0.betaMean << " s.d.: " << eparams0.betaSD - << " scaling factor: " << scale.betaScale << endl; } - else{ - outPar << "no" << endl; - ep0 = pSpecies->getEmigTraits(0,0); - outPar << "D0: " << ep0.d0 << endl; - outPar << "alpha: " << ep0.alpha << endl; - outPar << "beta: " << ep0.beta << endl; + else { // !emig.stgDep + outPar << stgdept << "no" << endl; + outPar << indvar; + if (emig.indVar) { + eparams0 = pSpecies->getEmigParams(0, 0); + emigScales scale = pSpecies->getEmigScales(); + outPar << "yes" << endl; + if (dem.stageStruct) { + outPar << emigstage << emig.emigStage << endl; + } + outPar << "D0 mean: " << eparams0.d0Mean << " s.d.: " << eparams0.d0SD + << " scaling factor: " << scale.d0Scale << endl; + outPar << "Alpha mean: " << eparams0.alphaMean << " s.d.: " << eparams0.alphaSD + << " scaling factor: " << scale.alphaScale << endl; + outPar << "Beta mean: " << eparams0.betaMean << " s.d.: " << eparams0.betaSD + << " scaling factor: " << scale.betaScale << endl; + } + else { + outPar << "no" << endl; + ep0 = pSpecies->getEmigTraits(0, 0); + outPar << "D0: " << ep0.d0 << endl; + outPar << "alpha: " << ep0.alpha << endl; + outPar << "beta: " << ep0.beta << endl; + } } } } -} -else { // not density-dependent - string initprob = "INITIAL EMIGRATION PROB. "; - outPar << "density-independent" << endl; - if (!trfr.moveModel) { // transfer by kernel - outPar << "USE FULL KERNEL TO DETERMINE EMIGRATION: "; - if (pSpecies->useFullKernel()) outPar << "yes"; - else outPar << "no"; - outPar << endl; - } + else { // not density-dependent + string initprob = "INITIAL EMIGRATION PROB. "; + outPar << "density-independent" << endl; + if (!trfr.moveModel) { // transfer by kernel + outPar << "USE FULL KERNEL TO DETERMINE EMIGRATION: "; + if (pSpecies->useFullKernel()) outPar << "yes"; + else outPar << "no"; + outPar << endl; + } - if (emig.sexDep) { - outPar << sexdept << "yes" << endl; - if (emig.stgDep) { - outPar << stgdept << "yes" << endl; - outPar << indvar << "no" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "stage " << i << ": \t" << "EMIGRATION PROB.: \tfemales " - << pSpecies->getEmigD0(i,0) <<" \tmales "<< pSpecies->getEmigD0(i,1) << endl; - } - } - else { // !emig.stgDep - outPar << stgdept << "no" << endl; - outPar << indvar; - if (emig.indVar) { - eparams0 = pSpecies->getEmigParams(0,0); - eparams1 = pSpecies->getEmigParams(0,1); - emigScales scale = pSpecies->getEmigScales(); - outPar << "yes" << endl; - if (dem.stageStruct) { - outPar << emigstage << emig.emigStage << endl; + if (emig.sexDep) { + outPar << sexdept << "yes" << endl; + if (emig.stgDep) { + outPar << stgdept << "yes" << endl; + outPar << indvar << "no" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "stage " << i << ": \t" << "EMIGRATION PROB.: \tfemales " + << pSpecies->getEmigD0(i, 0) << " \tmales " << pSpecies->getEmigD0(i, 1) << endl; } - outPar << initprob << "mean: " << "females " << eparams0.d0Mean - << " males " << eparams1.d0Mean << endl; - outPar << initprob << "s.d.: " << "females " << eparams0.d0SD - << " males " << eparams1.d0SD << endl; - outPar << initprob << "scaling factor: " << scale.d0Scale - << endl; - } - else{ - outPar << "no" << endl; - outPar << "EMIGRATION PROB.: \tfemales "<< pSpecies->getEmigD0(0,0) - <<"\t males " << pSpecies->getEmigD0(0,1) << endl; } - } - } - else { // !emig.sexDep - outPar << sexdept << "no" << endl; - if (emig.stgDep) { - outPar << stgdept << "yes" << endl; - outPar << indvar << "no" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "stage " << i << ": \t" << "EMIGRATION PROB.: " - << pSpecies->getEmigD0(i,0) << endl; + else { // !emig.stgDep + outPar << stgdept << "no" << endl; + outPar << indvar; + if (emig.indVar) { + eparams0 = pSpecies->getEmigParams(0, 0); + eparams1 = pSpecies->getEmigParams(0, 1); + emigScales scale = pSpecies->getEmigScales(); + outPar << "yes" << endl; + if (dem.stageStruct) { + outPar << emigstage << emig.emigStage << endl; + } + outPar << initprob << "mean: " << "females " << eparams0.d0Mean + << " males " << eparams1.d0Mean << endl; + outPar << initprob << "s.d.: " << "females " << eparams0.d0SD + << " males " << eparams1.d0SD << endl; + outPar << initprob << "scaling factor: " << scale.d0Scale + << endl; + } + else { + outPar << "no" << endl; + outPar << "EMIGRATION PROB.: \tfemales " << pSpecies->getEmigD0(0, 0) + << "\t males " << pSpecies->getEmigD0(0, 1) << endl; + } } } - else { // !emig.stgDep - outPar << stgdept << "no" << endl; - outPar << indvar; - if (emig.indVar) { - eparams0 = pSpecies->getEmigParams(0,0); - emigScales scale = pSpecies->getEmigScales(); - outPar << "yes" << endl; - if (dem.stageStruct) { - outPar << emigstage << emig.emigStage << endl; + else { // !emig.sexDep + outPar << sexdept << "no" << endl; + if (emig.stgDep) { + outPar << stgdept << "yes" << endl; + outPar << indvar << "no" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "stage " << i << ": \t" << "EMIGRATION PROB.: " + << pSpecies->getEmigD0(i, 0) << endl; } - outPar << initprob << "mean: " << eparams0.d0Mean << endl; - outPar << initprob << "s.d.: " << eparams0.d0SD << endl; - outPar << initprob << "scaling factor: " << scale.d0Scale << endl; } - else { - outPar << "no" << endl; - outPar << "EMIGRATION PROB.:\t" << pSpecies->getEmigD0(0,0) << endl; + else { // !emig.stgDep + outPar << stgdept << "no" << endl; + outPar << indvar; + if (emig.indVar) { + eparams0 = pSpecies->getEmigParams(0, 0); + emigScales scale = pSpecies->getEmigScales(); + outPar << "yes" << endl; + if (dem.stageStruct) { + outPar << emigstage << emig.emigStage << endl; + } + outPar << initprob << "mean: " << eparams0.d0Mean << endl; + outPar << initprob << "s.d.: " << eparams0.d0SD << endl; + outPar << initprob << "scaling factor: " << scale.d0Scale << endl; + } + else { + outPar << "no" << endl; + outPar << "EMIGRATION PROB.:\t" << pSpecies->getEmigD0(0, 0) << endl; + } } } } -} -// Transfer + // Transfer -outPar << endl << "DISPERSAL - TRANSFER: \t"; + outPar << endl << "DISPERSAL - TRANSFER: \t"; -if (trfr.moveModel) { - bool straigtenPath; - if (trfr.moveType == 1) { // SMS - trfrSMSTraits move = pSpecies->getSMSTraits(); - straigtenPath = move.straigtenPath; - if (trfr.costMap) { - outPar << "SMS\tcosts from imported cost map" << endl; + if (trfr.moveModel) { + bool straigtenPath; + if (trfr.moveType == 1) { // SMS + trfrSMSTraits move = pSpecies->getSMSTraits(); + straigtenPath = move.straigtenPath; + if (trfr.costMap) { + outPar << "SMS\tcosts from imported cost map" << endl; #if !RS_RCPP - outPar << "FILE NAME: " << costmapname << endl; + outPar << "FILE NAME: " << costmapname << endl; #endif - } - else { - outPar << "SMS\tcosts:" << endl; - if (!ppLand.generated && ppLand.rasterType == 0) { - for (int i = 0; i < ppLand.nHab; i++) - outPar << "\thab. " << pLandscape->getHabCode(i) << "\t" - << pSpecies->getHabCost(i) << endl; } else { - for (int i = 0; i < ppLand.nHab; i++) - outPar << "\thab. " << i << "\t" + outPar << "SMS\tcosts:" << endl; + if (!ppLand.generated && ppLand.rasterType == 0) { + for (int i = 0; i < ppLand.nHab; i++) + outPar << "\thab. " << pLandscape->getHabCode(i) << "\t" << pSpecies->getHabCost(i) << endl; + } + else { + for (int i = 0; i < ppLand.nHab; i++) + outPar << "\thab. " << i << "\t" + << pSpecies->getHabCost(i) << endl; + } } - } - string pr = "PERCEPTUAL RANGE"; - outPar << pr << ": " << move.pr << endl; - outPar << pr << " METHOD: " << move.prMethod << endl; - if (!trfr.indVar) outPar << "DIRECTIONAL PERSISTENCE: " << move.dp << endl; - outPar << "MEMORY SIZE: " << move.memSize << endl; - //if (!trfr.indVar) outPar << "GOAL BIAS: " << move.gb << endl; - outPar << "GOAL TYPE: " << move.goalType << endl; - if (!trfr.indVar) { - if (move.goalType == 2) { // dispersal bias - outPar << "GOAL BIAS: " << move.gb << endl; - outPar << "ALPHA DB: " << move.alphaDB << endl; - outPar << "BETA DB: " << move.betaDB << endl; - } - } - if (trfr.indVar) { - trfrSMSParams s = pSpecies->getSMSParams(0,0); - outPar << indvar << "yes " << endl; - outPar << "DP mean: " << s.dpMean << " s.d.: " << s.dpSD - << " scaling factor: " << s.dpScale << endl; - outPar << "GB mean: " << s.gbMean << " s.d.: " << s.gbSD - << " scaling factor: " << s.gbScale << endl; - if (move.goalType == 2) { // dispersal bias - outPar << "Alpha DB mean: " << s.alphaDBMean << " s.d.: " << s.alphaDBSD - << " scaling factor: " << s.alphaDBScale << endl; - outPar << "Beta DB mean: " << s.betaDBMean << " s.d.: " << s.betaDBSD - << " scaling factor: " << s.betaDBScale << endl; + string pr = "PERCEPTUAL RANGE"; + outPar << pr << ": " << move.pr << endl; + outPar << pr << " METHOD: " << move.prMethod << endl; + if (!trfr.indVar) outPar << "DIRECTIONAL PERSISTENCE: " << move.dp << endl; + outPar << "MEMORY SIZE: " << move.memSize << endl; + //if (!trfr.indVar) outPar << "GOAL BIAS: " << move.gb << endl; + outPar << "GOAL TYPE: " << move.goalType << endl; + if (!trfr.indVar) { + if (move.goalType == 2) { // dispersal bias + outPar << "GOAL BIAS: " << move.gb << endl; + outPar << "ALPHA DB: " << move.alphaDB << endl; + outPar << "BETA DB: " << move.betaDB << endl; + } + } + if (trfr.indVar) { + trfrSMSParams s = pSpecies->getSMSParams(0, 0); + outPar << indvar << "yes " << endl; + outPar << "DP mean: " << s.dpMean << " s.d.: " << s.dpSD + << " scaling factor: " << s.dpScale << endl; + outPar << "GB mean: " << s.gbMean << " s.d.: " << s.gbSD + << " scaling factor: " << s.gbScale << endl; + if (move.goalType == 2) { // dispersal bias + outPar << "Alpha DB mean: " << s.alphaDBMean << " s.d.: " << s.alphaDBSD + << " scaling factor: " << s.alphaDBScale << endl; + outPar << "Beta DB mean: " << s.betaDBMean << " s.d.: " << s.betaDBSD + << " scaling factor: " << s.betaDBScale << endl; + } + } + else { + outPar << indvar << "no " << endl; } } - else { - outPar << indvar << "no " << endl; - } - } - else { // CRW - trfrCRWTraits move = pSpecies->getCRWTraits(); - straigtenPath = move.straigtenPath; - outPar << "CRW" << endl; - string lgth = "STEP LENGTH (m) "; - string corr = "STEP CORRELATION"; - if (trfr.indVar) { - trfrCRWParams m = pSpecies->getCRWParams(0,0); - outPar << indvar << "yes" << endl; - outPar << lgth << " mean: " << m.stepLgthMean; - outPar << " s.d.: " << m.stepLgthSD; - outPar << " scaling factor: " << m.stepLScale << endl; - outPar << corr << " mean: " << m.rhoMean; - outPar << " s.d.: " << m.rhoSD; - outPar << " scaling factor: " << m.rhoScale << endl; - } - else { - outPar << indvar << "no" << endl; - outPar << lgth << ": " << move.stepLength << endl; - outPar << corr << ": " << move.rho << endl; + else { // CRW + trfrCRWTraits move = pSpecies->getCRWTraits(); + straigtenPath = move.straigtenPath; + outPar << "CRW" << endl; + string lgth = "STEP LENGTH (m) "; + string corr = "STEP CORRELATION"; + if (trfr.indVar) { + trfrCRWParams m = pSpecies->getCRWParams(0, 0); + outPar << indvar << "yes" << endl; + outPar << lgth << " mean: " << m.stepLgthMean; + outPar << " s.d.: " << m.stepLgthSD; + outPar << " scaling factor: " << m.stepLScale << endl; + outPar << corr << " mean: " << m.rhoMean; + outPar << " s.d.: " << m.rhoSD; + outPar << " scaling factor: " << m.rhoScale << endl; + } + else { + outPar << indvar << "no" << endl; + outPar << lgth << ": " << move.stepLength << endl; + outPar << corr << ": " << move.rho << endl; + } } - } - outPar << "STRAIGHTEN PATH AFTER DECISION NOT TO SETTLE: "; - if (straigtenPath) outPar << "yes" << endl; - else outPar << "no" << endl; - outPar << "STEP MORTALITY:\t" << endl; - if (trfr.habMort) - { - outPar << "habitat dependent:\t" << endl; - if (!ppLand.generated && ppLand.rasterType == 0) { - for (int i = 0; i < ppLand.nHab; i++) - outPar << "\thab. " << pLandscape->getHabCode(i) << "\t" + outPar << "STRAIGHTEN PATH AFTER DECISION NOT TO SETTLE: "; + if (straigtenPath) outPar << "yes" << endl; + else outPar << "no" << endl; + outPar << "STEP MORTALITY:\t" << endl; + if (trfr.habMort) + { + outPar << "habitat dependent:\t" << endl; + if (!ppLand.generated && ppLand.rasterType == 0) { + for (int i = 0; i < ppLand.nHab; i++) + outPar << "\thab. " << pLandscape->getHabCode(i) << "\t" << pSpecies->getHabMort(i) << endl; - } - else{ - for (int i = 0; i < ppLand.nHab; i++) - outPar << "\thab. " << i << "\t" + } + else { + for (int i = 0; i < ppLand.nHab; i++) + outPar << "\thab. " << i << "\t" << pSpecies->getHabMort(i) << endl; - } - } - else - { - trfrCRWTraits move = pSpecies->getCRWTraits(); - outPar << "constant " << move.stepMort << endl; - } -} // end of movement process -else { // kernel - string meandist = "MEAN DISTANCE"; - string probkern = "PROB. KERNEL I"; - trfrKernTraits kern0,kern1; - trfrKernParams k0,k1; - outPar << "dispersal kernel" << endl << "TYPE: \t"; - if (trfr.twinKern) outPar << "double "; - outPar << "negative exponential" << endl; - - if (trfr.sexDep) { - outPar << sexdept << "yes" << endl; - if (trfr.stgDep) { - outPar << stgdept << "yes" << endl; - outPar << indvar << "no" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "stage " << i << ":" << endl; - kern0 = pSpecies->getKernTraits(i,0); - kern1 = pSpecies->getKernTraits(i,1); - outPar << meandist << " I: \tfemales "<< kern0.meanDist1 << " \tmales " << kern1.meanDist1 << endl; - if (trfr.twinKern) - { - outPar << meandist << " II: \tfemales "<< kern0.meanDist2 << " \tmales " << kern1.meanDist2 << endl; - outPar << probkern << ": \tfemales "<< kern0.probKern1 << " \tmales " << kern1.probKern1 << endl; - } } } - else { // !trfr.stgDep - outPar << stgdept << "no" << endl; - outPar << indvar; - if (trfr.indVar) { - k0 = pSpecies->getKernParams(0,0); - k1 = pSpecies->getKernParams(0,1); - outPar << "yes" << endl; - outPar << meandist << " I (mean): \tfemales " << k0.dist1Mean - << " \tmales " << k1.dist1Mean << endl; - outPar << meandist << " I (s.d.): \tfemales " << k0.dist1SD - << " \tmales " << k1.dist1SD << endl; - outPar << meandist << " I (scaling factor): \tfemales " << k0.dist1Scale - << " \tmales " << k1.dist1Scale << endl; - if (trfr.twinKern) - { - outPar << meandist << " II (mean): \tfemales " << k0.dist2Mean - << " \tmales " << k1.dist2Mean << endl; - outPar << meandist << " II (s.d.): \tfemales " << k0.dist2SD - << " \tmales " << k1.dist2SD << endl; - outPar << meandist << " II (scaling factor): \tfemales " << k0.dist2Scale - << " \tmales " << k1.dist2Scale << endl; - outPar << probkern << " (mean): \tfemales " << k0.PKern1Mean - << " \tmales " << k1.PKern1Mean << endl; - outPar << probkern << " (s.d.): \tfemales " << k0.PKern1SD - << " \tmales " << k1.PKern1SD << endl; - outPar << probkern << " (scaling factor): \tfemales " << k0.PKern1Scale - << " \tmales " << k1.PKern1Scale << endl; + else + { + trfrCRWTraits move = pSpecies->getCRWTraits(); + outPar << "constant " << move.stepMort << endl; + } + } // end of movement process + else { // kernel + string meandist = "MEAN DISTANCE"; + string probkern = "PROB. KERNEL I"; + trfrKernTraits kern0, kern1; + trfrKernParams k0, k1; + outPar << "dispersal kernel" << endl << "TYPE: \t"; + if (trfr.twinKern) outPar << "double "; + outPar << "negative exponential" << endl; + + if (trfr.sexDep) { + outPar << sexdept << "yes" << endl; + if (trfr.stgDep) { + outPar << stgdept << "yes" << endl; + outPar << indvar << "no" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "stage " << i << ":" << endl; + kern0 = pSpecies->getKernTraits(i, 0); + kern1 = pSpecies->getKernTraits(i, 1); + outPar << meandist << " I: \tfemales " << kern0.meanDist1 << " \tmales " << kern1.meanDist1 << endl; + if (trfr.twinKern) + { + outPar << meandist << " II: \tfemales " << kern0.meanDist2 << " \tmales " << kern1.meanDist2 << endl; + outPar << probkern << ": \tfemales " << kern0.probKern1 << " \tmales " << kern1.probKern1 << endl; + } } } - else { - outPar << "no" << endl; - kern0 = pSpecies->getKernTraits(0,0); - kern1 = pSpecies->getKernTraits(0,1); - outPar << meandist << " I: \tfemales "<< kern0.meanDist1 << " \tmales " << kern1.meanDist1 << endl; - if (trfr.twinKern) - { - outPar << meandist << " II: \tfemales "<< kern0.meanDist2 << " \tmales " << kern1.meanDist2 << endl; - outPar << probkern << ": \tfemales "<< kern0.probKern1 << " \tmales " << kern1.probKern1 << endl; + else { // !trfr.stgDep + outPar << stgdept << "no" << endl; + outPar << indvar; + if (trfr.indVar) { + k0 = pSpecies->getKernParams(0, 0); + k1 = pSpecies->getKernParams(0, 1); + outPar << "yes" << endl; + outPar << meandist << " I (mean): \tfemales " << k0.dist1Mean + << " \tmales " << k1.dist1Mean << endl; + outPar << meandist << " I (s.d.): \tfemales " << k0.dist1SD + << " \tmales " << k1.dist1SD << endl; + outPar << meandist << " I (scaling factor): \tfemales " << k0.dist1Scale + << " \tmales " << k1.dist1Scale << endl; + if (trfr.twinKern) + { + outPar << meandist << " II (mean): \tfemales " << k0.dist2Mean + << " \tmales " << k1.dist2Mean << endl; + outPar << meandist << " II (s.d.): \tfemales " << k0.dist2SD + << " \tmales " << k1.dist2SD << endl; + outPar << meandist << " II (scaling factor): \tfemales " << k0.dist2Scale + << " \tmales " << k1.dist2Scale << endl; + outPar << probkern << " (mean): \tfemales " << k0.PKern1Mean + << " \tmales " << k1.PKern1Mean << endl; + outPar << probkern << " (s.d.): \tfemales " << k0.PKern1SD + << " \tmales " << k1.PKern1SD << endl; + outPar << probkern << " (scaling factor): \tfemales " << k0.PKern1Scale + << " \tmales " << k1.PKern1Scale << endl; + } + } + else { + outPar << "no" << endl; + kern0 = pSpecies->getKernTraits(0, 0); + kern1 = pSpecies->getKernTraits(0, 1); + outPar << meandist << " I: \tfemales " << kern0.meanDist1 << " \tmales " << kern1.meanDist1 << endl; + if (trfr.twinKern) + { + outPar << meandist << " II: \tfemales " << kern0.meanDist2 << " \tmales " << kern1.meanDist2 << endl; + outPar << probkern << ": \tfemales " << kern0.probKern1 << " \tmales " << kern1.probKern1 << endl; + } } } } - } - else { // !trfr.sexDep - outPar << sexdept << "no" << endl; - if (trfr.stgDep) { - outPar << stgdept << "yes" << endl; - outPar << indvar << "no" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - kern0 = pSpecies->getKernTraits(i,0); - outPar << "stage " << i << ": \t" << meandist << " I: " << kern0.meanDist1; - if (trfr.twinKern) - { - outPar << " \t" << meandist << " II: " << kern0.meanDist2; - outPar << " \t" << probkern << ": " << kern0.probKern1; + else { // !trfr.sexDep + outPar << sexdept << "no" << endl; + if (trfr.stgDep) { + outPar << stgdept << "yes" << endl; + outPar << indvar << "no" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + kern0 = pSpecies->getKernTraits(i, 0); + outPar << "stage " << i << ": \t" << meandist << " I: " << kern0.meanDist1; + if (trfr.twinKern) + { + outPar << " \t" << meandist << " II: " << kern0.meanDist2; + outPar << " \t" << probkern << ": " << kern0.probKern1; + } + outPar << endl; } - outPar << endl; } - } - else { // !trfr.stgDep - outPar << stgdept << "no" << endl; - outPar << indvar; - if (trfr.indVar) { - k0 = pSpecies->getKernParams(0,0); - outPar << "yes" << endl; - outPar << meandist << " I (mean): " << k0.dist1Mean - << " \t(s.d.): " << k0.dist1SD - << " \t(scaling factor): " << k0.dist1Scale << endl; - if (trfr.twinKern) - { - outPar << meandist << " II (mean): " << k0.dist2Mean - << " \t(s.d.): " << k0.dist2SD - << " \t(scaling factor): " << k0.dist2Scale << endl; - outPar << probkern << " (mean): " << k0.PKern1Mean - << " \t(s.d.): " << k0.PKern1SD - << " \t(scaling factor): " << k0.PKern1Scale << endl; - } - } - else{ - outPar << "no" << endl; - kern0 = pSpecies->getKernTraits(0,0); - outPar << meandist << " I: \t" << kern0.meanDist1 <getKernParams(0, 0); + outPar << "yes" << endl; + outPar << meandist << " I (mean): " << k0.dist1Mean + << " \t(s.d.): " << k0.dist1SD + << " \t(scaling factor): " << k0.dist1Scale << endl; + if (trfr.twinKern) + { + outPar << meandist << " II (mean): " << k0.dist2Mean + << " \t(s.d.): " << k0.dist2SD + << " \t(scaling factor): " << k0.dist2Scale << endl; + outPar << probkern << " (mean): " << k0.PKern1Mean + << " \t(s.d.): " << k0.PKern1SD + << " \t(scaling factor): " << k0.PKern1Scale << endl; + } + } + else { + outPar << "no" << endl; + kern0 = pSpecies->getKernTraits(0, 0); + outPar << meandist << " I: \t" << kern0.meanDist1 << endl; + if (trfr.twinKern) + { + outPar << meandist << " II: \t" << kern0.meanDist2 << endl; + outPar << probkern << ": \t" << kern0.probKern1 << endl; + } } } } - } - outPar << "DISPERSAL MORTALITY: "; - trfrMortParams mort = pSpecies->getMortParams(); - if (trfr.distMort) { - outPar << "distance-dependent" << endl; - outPar << "SLOPE: " << mort.mortAlpha << " \tINFLECTION POINT: " << mort.mortBeta << endl; - } - else { - outPar << "constant" << endl << "MORTALITY PROBABILITY: " << mort.fixedMort << endl; - } -} // end of kernel transfer + outPar << "DISPERSAL MORTALITY: "; + trfrMortParams mort = pSpecies->getMortParams(); + if (trfr.distMort) { + outPar << "distance-dependent" << endl; + outPar << "SLOPE: " << mort.mortAlpha << " \tINFLECTION POINT: " << mort.mortBeta << endl; + } + else { + outPar << "constant" << endl << "MORTALITY PROBABILITY: " << mort.fixedMort << endl; + } + } // end of kernel transfer -// Settlement + // Settlement -outPar << endl << "DISPERSAL - SETTLEMENT:" << endl; + outPar << endl << "DISPERSAL - SETTLEMENT:" << endl; -if (trfr.moveModel) { - string plusmating = "+ mating requirements"; - ssteps = pSpecies->getSteps(0,0); + if (trfr.moveModel) { + string plusmating = "+ mating requirements"; + ssteps = pSpecies->getSteps(0, 0); - outPar << "MIN. No. OF STEPS:\t " << ssteps.minSteps << endl; - outPar << "MAX. No. OF STEPS:\t "; - if (ssteps.maxSteps == 99999999) outPar << "not applied" << endl; - else outPar << ssteps.maxSteps << endl; + outPar << "MIN. No. OF STEPS:\t " << ssteps.minSteps << endl; + outPar << "MAX. No. OF STEPS:\t "; + if (ssteps.maxSteps == 99999999) outPar << "not applied" << endl; + else outPar << ssteps.maxSteps << endl; - if (sett.sexDep) { - nsexes = 2; - outPar << sexdept << "yes" << endl; - if (sett.stgDep) { - nstages = sstruct.nStages; - outPar << stgdept << "yes" << endl; - } - else { // !sett.stgDep - nstages = 1; - outPar << stgdept << "no" << endl; - } - } - else { // !sett.sexDep - nsexes = 1; - outPar << sexdept << "no" << endl; - if (sett.stgDep) { - nstages = sstruct.nStages; - outPar << stgdept << "yes" << endl; - } - else { // !sett.stgDep - nstages = 1; - outPar << stgdept << "no" << endl; - } - } - for (int sx = 0; sx < nsexes; sx++) { if (sett.sexDep) { - if (sx == 0) outPar << "FEMALES:" << endl; - else outPar << "MALES:" << endl; - } - outPar << "SETTLE IF: "; - for (int i = 0; i < nstages; i++) { - if (dem.stageStruct && nstages > 1) outPar << "stage " << i << ": " << endl; - outPar << "find a suitable cell/patch "; - srules = pSpecies->getSettRules(i,sx); - if (srules.densDep) { - settleDD = pSpecies->getSettTraits(i,sx); - outPar << "+ density dependence "; - if (srules.findMate) outPar << plusmating; - outPar << endl; - if (!sett.indVar) { - outPar << "S0: " << settleDD.s0 << " AlphaS: " << settleDD.alpha - << " BetaS: " << settleDD.beta << endl; - } + nsexes = 2; + outPar << sexdept << "yes" << endl; + if (sett.stgDep) { + nstages = sstruct.nStages; + outPar << stgdept << "yes" << endl; } - else { - if (srules.findMate) outPar << plusmating << endl; - else outPar << "(not the natal one)" << endl; + else { // !sett.stgDep + nstages = 1; + outPar << stgdept << "no" << endl; } - if (dem.stageStruct) { - ssteps = pSpecies->getSteps(i,sx); - outPar << "MAX. No. OF STEPS/YEAR:\t "; - if (ssteps.maxStepsYr == 99999999) outPar << "not applied" << endl; - else outPar << ssteps.maxStepsYr << endl; + } + else { // !sett.sexDep + nsexes = 1; + outPar << sexdept << "no" << endl; + if (sett.stgDep) { + nstages = sstruct.nStages; + outPar << stgdept << "yes" << endl; + } + else { // !sett.stgDep + nstages = 1; + outPar << stgdept << "no" << endl; } } - } - if (sett.indVar) { - settParams sparams0; - outPar << "DENSITY DEPENDENCE + " << indvar << "yes" << endl; - for (int sex = 0; sex < nsexes; sex++) { + for (int sx = 0; sx < nsexes; sx++) { if (sett.sexDep) { - if (sex == 0) outPar << "FEMALES:" << endl; + if (sx == 0) outPar << "FEMALES:" << endl; else outPar << "MALES:" << endl; } - sparams0 = pSpecies->getSettParams(0,sex); - settScales scale = pSpecies->getSettScales(); - outPar << "S0 - mean: " << sparams0.s0Mean << " s.d.: " << sparams0.s0SD - << " scaling factor: " << scale.s0Scale << endl; - outPar << "AlphaS - mean: " << sparams0.alphaSMean << " s.d.: " << sparams0.alphaSSD - << " scaling factor: " << scale.alphaSScale << endl; - outPar << "BetaS - mean: " << sparams0.betaSMean << " s.d.: " << sparams0.betaSSD - << " scaling factor: " << scale.betaSScale << endl; - } - } -} -else { // kernel-based transfer - string notsuit = "IF THE ARRIVAL CELL/PATCH IS UNSUITABLE: "; - string rchoose = " randomly choose a suitable neighb. cell/patch or "; - string matereq = "MATING REQUIREMENTS: "; - if (sett.sexDep) { - nsexes = 2; - outPar << sexdept << "yes" << endl; - if (sett.stgDep) { - nstages = sstruct.nStages; - outPar << stgdept << "yes" << endl; - outPar << notsuit << endl; + outPar << "SETTLE IF: "; + for (int i = 0; i < nstages; i++) { + if (dem.stageStruct && nstages > 1) outPar << "stage " << i << ": " << endl; + outPar << "find a suitable cell/patch "; + srules = pSpecies->getSettRules(i, sx); + if (srules.densDep) { + settleDD = pSpecies->getSettTraits(i, sx); + outPar << "+ density dependence "; + if (srules.findMate) outPar << plusmating; + outPar << endl; + if (!sett.indVar) { + outPar << "S0: " << settleDD.s0 << " AlphaS: " << settleDD.alpha + << " BetaS: " << settleDD.beta << endl; + } + } + else { + if (srules.findMate) outPar << plusmating << endl; + else outPar << "(not the natal one)" << endl; + } + if (dem.stageStruct) { + ssteps = pSpecies->getSteps(i, sx); + outPar << "MAX. No. OF STEPS/YEAR:\t "; + if (ssteps.maxStepsYr == 99999999) outPar << "not applied" << endl; + else outPar << ssteps.maxStepsYr << endl; + } + } } - else { - nstages = 1; - outPar << stgdept << "no" << endl; + if (sett.indVar) { + settParams sparams0; + outPar << "DENSITY DEPENDENCE + " << indvar << "yes" << endl; + for (int sex = 0; sex < nsexes; sex++) { + if (sett.sexDep) { + if (sex == 0) outPar << "FEMALES:" << endl; + else outPar << "MALES:" << endl; + } + sparams0 = pSpecies->getSettParams(0, sex); + settScales scale = pSpecies->getSettScales(); + outPar << "S0 - mean: " << sparams0.s0Mean << " s.d.: " << sparams0.s0SD + << " scaling factor: " << scale.s0Scale << endl; + outPar << "AlphaS - mean: " << sparams0.alphaSMean << " s.d.: " << sparams0.alphaSSD + << " scaling factor: " << scale.alphaSScale << endl; + outPar << "BetaS - mean: " << sparams0.betaSMean << " s.d.: " << sparams0.betaSSD + << " scaling factor: " << scale.betaSScale << endl; + } } } - else { - nsexes = 1; - outPar << sexdept << "no" << endl; - if (sett.stgDep) { - nstages = sstruct.nStages; - outPar << stgdept << "yes" << endl; - outPar << notsuit << endl; + else { // kernel-based transfer + string notsuit = "IF THE ARRIVAL CELL/PATCH IS UNSUITABLE: "; + string rchoose = " randomly choose a suitable neighb. cell/patch or "; + string matereq = "MATING REQUIREMENTS: "; + if (sett.sexDep) { + nsexes = 2; + outPar << sexdept << "yes" << endl; + if (sett.stgDep) { + nstages = sstruct.nStages; + outPar << stgdept << "yes" << endl; + outPar << notsuit << endl; + } + else { + nstages = 1; + outPar << stgdept << "no" << endl; + } } else { - nstages = 1; - outPar << stgdept << "no" << endl; - outPar << notsuit; - } - } - for (int i = 0; i < nstages; i++) { - if (sett.stgDep) { - outPar << "stage " << i << ":" << endl; - } - for (int sx = 0; sx < nsexes; sx++) { - if (sett.sexDep) { - if (sx == 0) outPar << "FEMALES: "; - else outPar << "MALES: "; - if (!sett.stgDep) outPar << notsuit; - } - srules = pSpecies->getSettRules(i,sx); - if (srules.go2nbrLocn) { - outPar << rchoose; - if (srules.wait) outPar << "wait" << endl; - else outPar << "die" << endl; + nsexes = 1; + outPar << sexdept << "no" << endl; + if (sett.stgDep) { + nstages = sstruct.nStages; + outPar << stgdept << "yes" << endl; + outPar << notsuit << endl; } else { - if (srules.wait) outPar << "wait" << endl; - else outPar << "die" << endl; + nstages = 1; + outPar << stgdept << "no" << endl; + outPar << notsuit; + } + } + for (int i = 0; i < nstages; i++) { + if (sett.stgDep) { + outPar << "stage " << i << ":" << endl; + } + for (int sx = 0; sx < nsexes; sx++) { + if (sett.sexDep) { + if (sx == 0) outPar << "FEMALES: "; + else outPar << "MALES: "; + if (!sett.stgDep) outPar << notsuit; + } + srules = pSpecies->getSettRules(i, sx); + if (srules.go2nbrLocn) { + outPar << rchoose; + if (srules.wait) outPar << "wait" << endl; + else outPar << "die" << endl; + } + else { + if (srules.wait) outPar << "wait" << endl; + else outPar << "die" << endl; + } + outPar << matereq; + if (srules.findMate) outPar << "yes" << endl; + else outPar << "no" << endl; } - outPar << matereq; - if (srules.findMate) outPar << "yes" <getNTraits(); -outPar << "No. of variable traits: " << nspptraits << endl; + outPar << endl << "GENETICS:" << endl; + int nspptraits = pSpecies->getNTraits(); + outPar << "No. of variable traits: " << nspptraits << endl; -genomeData d = pSpecies->getGenomeData(); -if (emig.indVar || trfr.indVar || sett.indVar || d.neutralMarkers) -{ - if (d.diploid) outPar << "DIPLOID" << endl; else outPar << "HAPLOID" << endl; - int nchromosomes = pSpecies->getNChromosomes(); - outPar << "No. of chromosomes: " << nchromosomes; - if (d.trait1Chromosome) { - outPar << endl << "No. of loci/chromosome: " << d.nLoci << endl; - } - else { - outPar << " (chrom:loci)"; - for (int i = 0; i < nchromosomes; i++) { - outPar << " " << i << ":" << pSpecies->getNLoci(i); + genomeData d = pSpecies->getGenomeData(); + if (emig.indVar || trfr.indVar || sett.indVar || d.neutralMarkers) + { + if (d.diploid) outPar << "DIPLOID" << endl; else outPar << "HAPLOID" << endl; + int nchromosomes = pSpecies->getNChromosomes(); + outPar << "No. of chromosomes: " << nchromosomes; + if (d.trait1Chromosome) { + outPar << endl << "No. of loci/chromosome: " << d.nLoci << endl; } - outPar << endl; - } - outPar << "Mutation probability: " << d.probMutn << endl; - outPar << "Crossover probability: " << d.probCrossover << endl; - outPar << "Initial allele s.d.: " << d.alleleSD << endl; - outPar << "Mutation s.d.: " << d.mutationSD << endl; - if (d.neutralMarkers) { - outPar << "NEUTRAL MARKERS ONLY" << endl; - } - else { - if (!d.trait1Chromosome) { - traitAllele allele; - outPar << "TRAIT MAPPING:" << endl; - outPar << "Architecture file: " << genfilename << endl; - int ntraitmaps = pSpecies->getNTraitMaps(); - outPar << "No. of traits defined: " << ntraitmaps << endl; - for (int i = 0; i < ntraitmaps; i++) { - int nalleles = pSpecies->getNTraitAlleles(i); - outPar << "Trait " << i << ": (" << pSpecies->getTraitName(i) - << ") alleles: " << nalleles << " (chrom:locus)"; - for (int j = 0; j < nalleles; j++) { - allele = pSpecies->getTraitAllele(i,j); - outPar << " " << allele.chromo << ":" << allele.locus; - } - outPar << endl; - } - if (ntraitmaps < nspptraits) { // list undefined traits - outPar << "WARNING - the following traits were not defined" - << " in the genetic architecture file:" << endl; - for (int i = ntraitmaps; i < nspptraits; i++) { + else { + outPar << " (chrom:loci)"; + for (int i = 0; i < nchromosomes; i++) { + outPar << " " << i << ":" << pSpecies->getNLoci(i); + } + outPar << endl; + } + outPar << "Mutation probability: " << d.probMutn << endl; + outPar << "Crossover probability: " << d.probCrossover << endl; + outPar << "Initial allele s.d.: " << d.alleleSD << endl; + outPar << "Mutation s.d.: " << d.mutationSD << endl; + if (d.neutralMarkers) { + outPar << "NEUTRAL MARKERS ONLY" << endl; + } + else { + if (!d.trait1Chromosome) { + traitAllele allele; + outPar << "TRAIT MAPPING:" << endl; + outPar << "Architecture file: " << genfilename << endl; + int ntraitmaps = pSpecies->getNTraitMaps(); + outPar << "No. of traits defined: " << ntraitmaps << endl; + for (int i = 0; i < ntraitmaps; i++) { + int nalleles = pSpecies->getNTraitAlleles(i); outPar << "Trait " << i << ": (" << pSpecies->getTraitName(i) - << ") all individuals have mean phenotype" << endl; + << ") alleles: " << nalleles << " (chrom:locus)"; + for (int j = 0; j < nalleles; j++) { + allele = pSpecies->getTraitAllele(i, j); + outPar << " " << allele.chromo << ":" << allele.locus; + } + outPar << endl; } - } - int nneutral = pSpecies->getNNeutralLoci(); - if (nneutral > 0) { - outPar << "Neutral loci: " << nneutral << " (chrom:locus)"; - for (int i = 0; i < nneutral; i++) { - allele = pSpecies->getNeutralAllele(i); - outPar << " " << allele.chromo << ":" << allele.locus; + if (ntraitmaps < nspptraits) { // list undefined traits + outPar << "WARNING - the following traits were not defined" + << " in the genetic architecture file:" << endl; + for (int i = ntraitmaps; i < nspptraits; i++) { + outPar << "Trait " << i << ": (" << pSpecies->getTraitName(i) + << ") all individuals have mean phenotype" << endl; + } } - outPar << endl; + int nneutral = pSpecies->getNNeutralLoci(); + if (nneutral > 0) { + outPar << "Neutral loci: " << nneutral << " (chrom:locus)"; + for (int i = 0; i < nneutral; i++) { + allele = pSpecies->getNeutralAllele(i); + outPar << " " << allele.chromo << ":" << allele.locus; + } + outPar << endl; + } + if (d.pleiotropic) + outPar << "Genome exhibits pleiotropy" << endl; } - if (d.pleiotropic) - outPar << "Genome exhibits pleiotropy" << endl; } } -} -// Initialisation + // Initialisation -initParams init = paramsInit->getInit(); -outPar << endl << "INITIALISATION CONDITIONS:" << endl; -switch (init.seedType) { -case 0: - outPar << "Free initialisation: \t" ; - switch (init.freeType) { + initParams init = paramsInit->getInit(); + outPar << endl << "INITIALISATION CONDITIONS:" << endl; + switch (init.seedType) { case 0: - outPar << "Random \t" ; - outPar << "No. of cells/patches: " << init.nSeedPatches << endl; + outPar << "Free initialisation: \t"; + switch (init.freeType) { + case 0: + outPar << "Random \t"; + outPar << "No. of cells/patches: " << init.nSeedPatches << endl; + break; + case 1: + outPar << "all suitable cells/patches" << endl; + break; + case 2: + outPar << "manually selected cells/patches" << endl; + break; + } break; case 1: - outPar << "all suitable cells/patches" << endl; - break; - case 2: - outPar << "manually selected cells/patches" << endl; - break; - } - break; -case 1: - outPar << "From species distribution: \t" << endl; - switch (init.spDistType) { + outPar << "From species distribution: \t" << endl; + switch (init.spDistType) { case 0: outPar << "all presence cells/patches" << endl; break; @@ -2122,139 +2122,139 @@ case 1: case 2: outPar << "all cells/patches within selected distribution cells" << endl; break; - } - break; -case 2: - outPar << "From initial individuals file: " << paramsSim->getDir(1) + init.indsFile << endl; - break; -case 3: - outPar << "From file" << endl; - break; -} -if (init.seedType != 2) { - outPar << "INITIAL NO. OF INDIVIDUALS: \t"; - switch (init.initDens) { - case 0: - outPar << "at carrying capacity" << endl; - break; - case 1: - outPar << "at half carrying capacity" << endl; + } break; case 2: - if (ppLand.patchModel) { - outPar << init.indsHa << " individuals per ha" << endl; - } - else { - outPar << init.indsCell << " individuals per cell" << endl; - } + outPar << "From initial individuals file: " << paramsSim->getDir(1) + init.indsFile << endl; + break; + case 3: + outPar << "From file" << endl; break; } - if (dem.stageStruct) { - outPar << "INITIAL STAGE PROPORTIONS:" << endl; - for (int i = 1; i < sstruct.nStages; i++) { - outPar << "stage " << i << ": " << paramsInit->getProp(i) << " \t"; - } - outPar << endl; - outPar << "Initial age distribution: "; - switch (init.initAge) { + if (init.seedType != 2) { + outPar << "INITIAL NO. OF INDIVIDUALS: \t"; + switch (init.initDens) { case 0: - outPar << "lowest possible age"; + outPar << "at carrying capacity" << endl; break; case 1: - outPar << "randomised"; + outPar << "at half carrying capacity" << endl; break; case 2: - outPar << "quasi-equilibrium"; + if (ppLand.patchModel) { + outPar << init.indsHa << " individuals per ha" << endl; + } + else { + outPar << init.indsCell << " individuals per cell" << endl; + } break; } - outPar << endl; - } - outPar << "GEOGRAPHICAL CONSTRAINTS (cell numbers): " << endl; - outPar << "min X: " << init.minSeedX << " max X: " << init.maxSeedX << endl; - outPar << "min Y: " << init.minSeedY << " max Y: " << init.maxSeedY << endl; -// if (init.seedType != 1 && init.freeType < 2 && init.initFrzYr > 0) { -// outPar << "Freeze initial range until year " << init.initFrzYr << endl; -// } - if (init.seedType == 0 && init.freeType < 2) { - if (init.initFrzYr > 0) { - outPar << "Freeze initial range until year " << init.initFrzYr << endl; - } - if (init.restrictRange) { - outPar << "Restrict range to northern " << init.restrictRows - << " rows every " << init.restrictFreq << " years" << endl; - if (init.finalFrzYr < sim.years) { - outPar << "Freeze range at year " << init.finalFrzYr << endl; + if (dem.stageStruct) { + outPar << "INITIAL STAGE PROPORTIONS:" << endl; + for (int i = 1; i < sstruct.nStages; i++) { + outPar << "stage " << i << ": " << paramsInit->getProp(i) << " \t"; + } + outPar << endl; + outPar << "Initial age distribution: "; + switch (init.initAge) { + case 0: + outPar << "lowest possible age"; + break; + case 1: + outPar << "randomised"; + break; + case 2: + outPar << "quasi-equilibrium"; + break; + } + outPar << endl; + } + outPar << "GEOGRAPHICAL CONSTRAINTS (cell numbers): " << endl; + outPar << "min X: " << init.minSeedX << " max X: " << init.maxSeedX << endl; + outPar << "min Y: " << init.minSeedY << " max Y: " << init.maxSeedY << endl; + // if (init.seedType != 1 && init.freeType < 2 && init.initFrzYr > 0) { + // outPar << "Freeze initial range until year " << init.initFrzYr << endl; + // } + if (init.seedType == 0 && init.freeType < 2) { + if (init.initFrzYr > 0) { + outPar << "Freeze initial range until year " << init.initFrzYr << endl; + } + if (init.restrictRange) { + outPar << "Restrict range to northern " << init.restrictRows + << " rows every " << init.restrictFreq << " years" << endl; + if (init.finalFrzYr < sim.years) { + outPar << "Freeze range at year " << init.finalFrzYr << endl; + } } } } -} -outPar << endl << "OUTPUTS:" << endl; -if (sim.outRange) { - outPar << "Range - every " << sim.outIntRange << " year"; - if (sim.outIntRange > 1) outPar << "s"; -// if (sim.outStartRange > 0) outPar << " starting year " << sim.outStartRange; - outPar << endl; -} -if (sim.outOccup) { - outPar << "Occupancy - every " << sim.outIntOcc << " year"; - if (sim.outIntOcc > 1) outPar << "s"; -// if (sim.outStartOcc > 0) outPar << " starting year " << sim.outStartOcc; - outPar << endl; -} -if (sim.outPop) { - outPar << "Populations - every " << sim.outIntPop << " year"; - if (sim.outIntPop > 1) outPar << "s"; - if (sim.outStartPop > 0) outPar << " starting year " << sim.outStartPop; - outPar << endl; -} -if (sim.outInds) { - outPar << "Individuals - every " << sim.outIntInd << " year"; - if (sim.outIntInd > 1) outPar << "s"; - if (sim.outStartInd > 0) outPar << " starting year " << sim.outStartInd; - outPar << endl; -} -if (sim.outGenetics) { - outPar << "Genetics - every " << sim.outIntGenetic << " year"; - if (sim.outIntGenetic > 1) outPar << "s"; - if (sim.outStartGenetic > 0) outPar << " starting year " << sim.outStartGenetic; - if (dem.stageStruct) { - switch (sim.outGenType) { - case 0: - outPar << " - juveniles only"; - break; - case 1: - outPar << " - all individuals"; - break; - case 2: - outPar << " - adults only"; - break; - } + outPar << endl << "OUTPUTS:" << endl; + if (sim.outRange) { + outPar << "Range - every " << sim.outIntRange << " year"; + if (sim.outIntRange > 1) outPar << "s"; + // if (sim.outStartRange > 0) outPar << " starting year " << sim.outStartRange; + outPar << endl; + } + if (sim.outOccup) { + outPar << "Occupancy - every " << sim.outIntOcc << " year"; + if (sim.outIntOcc > 1) outPar << "s"; + // if (sim.outStartOcc > 0) outPar << " starting year " << sim.outStartOcc; + outPar << endl; + } + if (sim.outPop) { + outPar << "Populations - every " << sim.outIntPop << " year"; + if (sim.outIntPop > 1) outPar << "s"; + if (sim.outStartPop > 0) outPar << " starting year " << sim.outStartPop; + outPar << endl; + } + if (sim.outInds) { + outPar << "Individuals - every " << sim.outIntInd << " year"; + if (sim.outIntInd > 1) outPar << "s"; + if (sim.outStartInd > 0) outPar << " starting year " << sim.outStartInd; + outPar << endl; + } + if (sim.outGenetics) { + outPar << "Genetics - every " << sim.outIntGenetic << " year"; + if (sim.outIntGenetic > 1) outPar << "s"; + if (sim.outStartGenetic > 0) outPar << " starting year " << sim.outStartGenetic; + if (dem.stageStruct) { + switch (sim.outGenType) { + case 0: + outPar << " - juveniles only"; + break; + case 1: + outPar << " - all individuals"; + break; + case 2: + outPar << " - adults only"; + break; + } + } + if (sim.outGenXtab) outPar << " (as cross table)"; + outPar << endl; } - if (sim.outGenXtab) outPar << " (as cross table)"; - outPar << endl; -} -if (sim.outTraitsCells) { - outPar << "Traits per "; - if (ppLand.patchModel) outPar << "patch"; else outPar << "cell"; - outPar << " - every " << sim.outIntTraitCell << " year"; - if (sim.outIntTraitCell > 1) outPar << "s"; - if (sim.outStartTraitCell > 0) outPar << " starting year " << sim.outStartTraitCell; - outPar << endl; -} -if (sim.outTraitsRows) { - outPar << "Traits per row - every " << sim.outIntTraitRow << " year"; - if (sim.outIntTraitRow > 1) outPar << "s"; - if (sim.outStartTraitRow > 0) outPar << " starting year " << sim.outStartTraitRow; - outPar << endl; -} -if (sim.outConnect) { - outPar << "Connectivity matrix - every " << sim.outIntConn << " year"; - if (sim.outIntConn > 1) outPar << "s"; - if (sim.outStartConn > 0) outPar << " starting year " << sim.outStartConn; - outPar << endl; -} + if (sim.outTraitsCells) { + outPar << "Traits per "; + if (ppLand.patchModel) outPar << "patch"; else outPar << "cell"; + outPar << " - every " << sim.outIntTraitCell << " year"; + if (sim.outIntTraitCell > 1) outPar << "s"; + if (sim.outStartTraitCell > 0) outPar << " starting year " << sim.outStartTraitCell; + outPar << endl; + } + if (sim.outTraitsRows) { + outPar << "Traits per row - every " << sim.outIntTraitRow << " year"; + if (sim.outIntTraitRow > 1) outPar << "s"; + if (sim.outStartTraitRow > 0) outPar << " starting year " << sim.outStartTraitRow; + outPar << endl; + } + if (sim.outConnect) { + outPar << "Connectivity matrix - every " << sim.outIntConn << " year"; + if (sim.outIntConn > 1) outPar << "s"; + if (sim.outStartConn > 0) outPar << " starting year " << sim.outStartConn; + outPar << endl; + } #if RS_RCPP if (sim.outPaths) { outPar << "SMS paths - every " << sim.outIntPaths << " year"; @@ -2263,27 +2263,27 @@ if (sim.outConnect) { outPar << endl; } #endif -outPar << "SAVE MAPS: "; -if (sim.saveMaps) { - outPar << "yes - every " << sim.mapInt << " year"; - if (sim.mapInt > 1) outPar << "s"; - outPar << endl; -} -else outPar << "no" << endl; -outPar << "SAVE TRAITS MAPS: "; -if (sim.saveTraitMaps) { - outPar << "yes - every " << sim.traitInt << " year"; - if (sim.traitInt > 1) outPar << "s"; - outPar << endl; -} -else outPar << "no" << endl; -if (trfr.moveModel && trfr.moveType == 1) { - outPar << "SMS HEAT MAPS: "; - if (sim.saveVisits) outPar << "yes" << endl; + outPar << "SAVE MAPS: "; + if (sim.saveMaps) { + outPar << "yes - every " << sim.mapInt << " year"; + if (sim.mapInt > 1) outPar << "s"; + outPar << endl; + } else outPar << "no" << endl; -} + outPar << "SAVE TRAITS MAPS: "; + if (sim.saveTraitMaps) { + outPar << "yes - every " << sim.traitInt << " year"; + if (sim.traitInt > 1) outPar << "s"; + outPar << endl; + } + else outPar << "no" << endl; + if (trfr.moveModel && trfr.moveType == 1) { + outPar << "SMS HEAT MAPS: "; + if (sim.saveVisits) outPar << "yes" << endl; + else outPar << "no" << endl; + } -outPar.close(); outPar.clear(); + outPar.close(); outPar.clear(); } diff --git a/Model.h b/Model.h index 4acf37a..41c50a3 100644 --- a/Model.h +++ b/Model.h @@ -1,47 +1,47 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ -RangeShifter v2.0 Model -Implements three functions which run the model and produce output common to both -GUI and batch version. + /*------------------------------------------------------------------------------ -RunModel() handles looping through replicates, years and generations + RangeShifter v2.0 Model -Further functions are declared here, but defined differently in main function of -GUI and batch versions. + Implements three functions which run the model and produce output common to both + GUI and batch version. -For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. -and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. -Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 + RunModel() handles looping through replicates, years and generations -Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + Further functions are declared here, but defined differently in main function of + GUI and batch versions. -Last updated: 26 October 2021 by Steve Palmer -------------------------------------------------------------------------------*/ + For full details of RangeShifter, please see: + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. + and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial + eco-evolutionary dynamics and species’ responses to environmental changes. + Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 + + Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + + Last updated: 26 October 2021 by Steve Palmer + ------------------------------------------------------------------------------*/ #ifndef ModelH #define ModelH @@ -49,7 +49,7 @@ Last updated: 26 October 2021 by Steve Palmer #include #include -//#if RS_RCPP && !R_CMD + //#if RS_RCPP && !R_CMD #include "../Version.h" //#endif @@ -115,12 +115,12 @@ void OutParameters( Landscape* // pointer to Landscape ); -extern paramGrad *paramsGrad; -extern paramStoch *paramsStoch; -extern Species *pSpecies; -extern paramSim *paramsSim; -extern paramInit *paramsInit; -extern Community *pComm; +extern paramGrad* paramsGrad; +extern paramStoch* paramsStoch; +extern Species* pSpecies; +extern paramSim* paramsSim; +extern paramInit* paramsInit; +extern Community* pComm; const bool batchMode = true; extern string landFile; @@ -130,7 +130,7 @@ extern string patchmapname; // see FormLand.cpp (VCL) OR Main.cpp (batch) extern string distnmapname; // see FormLand.cpp (VCL) OR Main.cpp (batch) extern string costmapname; // see FormMove.cpp (VCL) OR Main.cpp (batch) extern string genfilename; // see FormGenetics.cpp (VCL) OR Main.cpp (batch) -extern RSrandom *pRandom; +extern RSrandom* pRandom; // these functions to have different version for GUI and batch applications ... #if BATCH diff --git a/Parameters.cpp b/Parameters.cpp index b7c6a34..28c2c67 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Parameters.h" //--------------------------------------------------------------------------- @@ -30,34 +30,34 @@ // Environmental gradient parameters paramGrad::paramGrad(void) { -gradient = false; gradType = 0; grad_inc = 0.05f; -opt_y0 = opt_y = factor = extProbOpt = 0.0; -shifting = false; shift_rate = 0.5; shift_begin = 0; shift_stop = 100; + gradient = false; gradType = 0; grad_inc = 0.05f; + opt_y0 = opt_y = factor = extProbOpt = 0.0; + shifting = false; shift_rate = 0.5; shift_begin = 0; shift_stop = 100; } paramGrad::~paramGrad() { } void paramGrad::setGradient(int gtype, float inc, float y, float f, float p) { -if (gtype > 0 && gtype < 4) -{ // valid gradient type - gradient = true; gradType = gtype; - if (inc >= 0.0 && inc <= 1.0) grad_inc = inc; - if (y >= 0.0) opt_y0 = opt_y = y; - if (f >= 0.0) factor = f; - if (p > 0.0 && p < 1.0) extProbOpt = p; -} -else { - gradient = false; gradType = 0; -} + if (gtype > 0 && gtype < 4) + { // valid gradient type + gradient = true; gradType = gtype; + if (inc >= 0.0 && inc <= 1.0) grad_inc = inc; + if (y >= 0.0) opt_y0 = opt_y = y; + if (f >= 0.0) factor = f; + if (p > 0.0 && p < 1.0) extProbOpt = p; + } + else { + gradient = false; gradType = 0; + } } void paramGrad::setShifting(float r, int begin, int end) { -shifting = true; -if (r > 0.0) shift_rate = r; -if (begin >= 0) shift_begin = begin; -if (end > 0) shift_stop = end; + shifting = true; + if (r > 0.0) shift_rate = r; + if (begin >= 0) shift_begin = begin; + if (end > 0) shift_stop = end; } void paramGrad::noGradient(void) { gradient = false; gradType = 0; } @@ -65,16 +65,18 @@ void paramGrad::noGradient(void) { gradient = false; gradType = 0; } void paramGrad::noShifting(void) { shifting = false; } envGradParams paramGrad::getGradient(void) { -envGradParams g; -g.gradient = gradient; g.gradType = gradType; g.grad_inc = grad_inc; -g.opt_y = opt_y; g.factor = factor; g.extProbOpt = extProbOpt; -g.shifting = shifting; g.shift_rate = shift_rate; -g.shift_begin = shift_begin; g.shift_stop = shift_stop; -return g; + envGradParams g; + g.gradient = gradient; g.gradType = gradType; g.grad_inc = grad_inc; + g.opt_y = opt_y; g.factor = factor; g.extProbOpt = extProbOpt; + g.shifting = shifting; g.shift_rate = shift_rate; + g.shift_begin = shift_begin; g.shift_stop = shift_stop; + return g; } void paramGrad::incrOptY(void) -{ if (gradient && shifting) opt_y += shift_rate; } +{ + if (gradient && shifting) opt_y += shift_rate; +} void paramGrad::resetOptY(void) { opt_y = opt_y0; } @@ -83,9 +85,9 @@ void paramGrad::resetOptY(void) { opt_y = opt_y0; } // Environmental stochasticity parameters paramStoch::paramStoch(void) { -stoch = false; local = false; inK = false; localExt = false; -ac = 0.0; std = 0.25; -locExtProb = 0.1; + stoch = false; local = false; inK = false; localExt = false; + ac = 0.0; std = 0.25; + locExtProb = 0.1; } paramStoch::~paramStoch(void) {} @@ -93,21 +95,21 @@ paramStoch::~paramStoch(void) {} void paramStoch::setStoch(envStochParams e) { -stoch = e.stoch; local = e.local; inK = e.inK; localExt = e.localExt; -if (e.ac >= 0.0 && e.ac < 1.0) ac = e.ac; -if (e.std > 0.0 && e.std <= 1.0) std = e.std; -locExtProb = e.locExtProb; + stoch = e.stoch; local = e.local; inK = e.inK; localExt = e.localExt; + if (e.ac >= 0.0 && e.ac < 1.0) ac = e.ac; + if (e.std > 0.0 && e.std <= 1.0) std = e.std; + locExtProb = e.locExtProb; } bool paramStoch::envStoch(void) { return stoch; } envStochParams paramStoch::getStoch(void) { -envStochParams e; -e.stoch = stoch; e.local = local; e.inK = inK; e.localExt = localExt; -e.ac = ac; e.std = std; -e.locExtProb = locExtProb; -return e; + envStochParams e; + e.stoch = stoch; e.local = local; e.inK = inK; e.localExt = localExt; + e.ac = ac; e.std = std; + e.locExtProb = locExtProb; + return e; } @@ -116,100 +118,100 @@ return e; // Initialisation (seeding) parameters paramInit::paramInit(void) { -seedType = freeType = spDistType = initDens = 0; -initAge = initFrzYr = 0; -restrictRange = false; -restrictRows = 100; -restrictFreq = 10; -finalFrzYr = 99999999; -indsCell = 1; indsHa = 0.0; -minSeedX = 0; maxSeedX = 99999999; minSeedY = 0; maxSeedY = 99999999; -nSeedPatches = 1; nSpDistPatches = 1; -indsFile = "NULL"; -for (int i = 0; i < NSTAGES; i++) { - initProp[i] = 0.0; -} + seedType = freeType = spDistType = initDens = 0; + initAge = initFrzYr = 0; + restrictRange = false; + restrictRows = 100; + restrictFreq = 10; + finalFrzYr = 99999999; + indsCell = 1; indsHa = 0.0; + minSeedX = 0; maxSeedX = 99999999; minSeedY = 0; maxSeedY = 99999999; + nSeedPatches = 1; nSpDistPatches = 1; + indsFile = "NULL"; + for (int i = 0; i < NSTAGES; i++) { + initProp[i] = 0.0; + } } paramInit::~paramInit(void) { -initinds.clear(); + initinds.clear(); } void paramInit::setInit(initParams i) { -if (i.seedType >= 0 && i.seedType <= 3) seedType = i.seedType; -if (i.freeType >= 0 && i.freeType <= 2) freeType = i.freeType; -if (i.spDistType >= 0 && i.spDistType <= 2) spDistType = i.spDistType; -initDens = i.initDens; -initAge = i.initAge; -if (i.initFrzYr >= 0) initFrzYr = i.initFrzYr; -restrictRange = i.restrictRange; -if (i.restrictRows > 0) restrictRows = i.restrictRows; -if (i.restrictFreq > 0) restrictFreq = i.restrictFreq; -if (i.finalFrzYr > 0) finalFrzYr = i.finalFrzYr; -if (i.indsCell >= 1) indsCell = i.indsCell; -if (i.indsHa > 0.0) indsHa = i.indsHa; -if (i.minSeedX >= 0) minSeedX = i.minSeedX; -if (i.maxSeedX >= 0) maxSeedX = i.maxSeedX; -if (i.minSeedY >= 0) minSeedY = i.minSeedY; -if (i.maxSeedY >= 0) maxSeedY = i.maxSeedY; -if (i.nSeedPatches >= 1) nSeedPatches = i.nSeedPatches; -if (i.nSpDistPatches >= 1) nSpDistPatches = i.nSpDistPatches; -indsFile = i.indsFile; + if (i.seedType >= 0 && i.seedType <= 3) seedType = i.seedType; + if (i.freeType >= 0 && i.freeType <= 2) freeType = i.freeType; + if (i.spDistType >= 0 && i.spDistType <= 2) spDistType = i.spDistType; + initDens = i.initDens; + initAge = i.initAge; + if (i.initFrzYr >= 0) initFrzYr = i.initFrzYr; + restrictRange = i.restrictRange; + if (i.restrictRows > 0) restrictRows = i.restrictRows; + if (i.restrictFreq > 0) restrictFreq = i.restrictFreq; + if (i.finalFrzYr > 0) finalFrzYr = i.finalFrzYr; + if (i.indsCell >= 1) indsCell = i.indsCell; + if (i.indsHa > 0.0) indsHa = i.indsHa; + if (i.minSeedX >= 0) minSeedX = i.minSeedX; + if (i.maxSeedX >= 0) maxSeedX = i.maxSeedX; + if (i.minSeedY >= 0) minSeedY = i.minSeedY; + if (i.maxSeedY >= 0) maxSeedY = i.maxSeedY; + if (i.nSeedPatches >= 1) nSeedPatches = i.nSeedPatches; + if (i.nSpDistPatches >= 1) nSpDistPatches = i.nSpDistPatches; + indsFile = i.indsFile; } initParams paramInit::getInit(void) { -initParams i; -i.seedType = seedType; i.freeType = freeType; i.spDistType = spDistType; -i.initDens = initDens; i.initAge = initAge; -i.initFrzYr = initFrzYr; -i.restrictRange = restrictRange; -i.restrictRows = restrictRows; i.restrictFreq = restrictFreq; -i.finalFrzYr = finalFrzYr; -i.indsCell = indsCell; i.indsHa = indsHa; -i.minSeedX = minSeedX; i.minSeedY = minSeedY; -i.maxSeedX = maxSeedX; i.maxSeedY = maxSeedY; -i.nSeedPatches = nSeedPatches; i.nSpDistPatches = nSpDistPatches; -i.indsFile = indsFile; -return i; + initParams i; + i.seedType = seedType; i.freeType = freeType; i.spDistType = spDistType; + i.initDens = initDens; i.initAge = initAge; + i.initFrzYr = initFrzYr; + i.restrictRange = restrictRange; + i.restrictRows = restrictRows; i.restrictFreq = restrictFreq; + i.finalFrzYr = finalFrzYr; + i.indsCell = indsCell; i.indsHa = indsHa; + i.minSeedX = minSeedX; i.minSeedY = minSeedY; + i.maxSeedX = maxSeedX; i.maxSeedY = maxSeedY; + i.nSeedPatches = nSeedPatches; i.nSpDistPatches = nSpDistPatches; + i.indsFile = indsFile; + return i; } -void paramInit::setProp(short stg,float p) { -if (stg >= 0 && stg < NSTAGES && p >= 0.0 && p <= 1.0) initProp[stg] = p; +void paramInit::setProp(short stg, float p) { + if (stg >= 0 && stg < NSTAGES && p >= 0.0 && p <= 1.0) initProp[stg] = p; } float paramInit::getProp(short stg) { -float p = 0.0; -if (stg >= 0 && stg < NSTAGES) p = initProp[stg]; -return p; + float p = 0.0; + if (stg >= 0 && stg < NSTAGES) p = initProp[stg]; + return p; } void paramInit::addInitInd(initInd iind) { #if RSDEBUG -//DebugGUI(("paramInit::addInitInd(): iind.patchID=" + Int2Str(iind.patchID) -// + " iind.x=" + Int2Str(iind.x) -// + " iind.y=" + Int2Str(iind.y) -// ).c_str()); + //DebugGUI(("paramInit::addInitInd(): iind.patchID=" + Int2Str(iind.patchID) + // + " iind.x=" + Int2Str(iind.x) + // + " iind.y=" + Int2Str(iind.y) + // ).c_str()); #endif -initinds.push_back(iind); + initinds.push_back(iind); } initInd paramInit::getInitInd(int ix) { -initInd iind; -if (ix >= 0 && ix < (int)initinds.size()) { - iind = initinds[ix]; -} -else { - iind.year = iind.patchID = iind.x = iind.y = iind.sex = iind.age = iind.stage = 0; - iind.species = -1; -} + initInd iind; + if (ix >= 0 && ix < (int)initinds.size()) { + iind = initinds[ix]; + } + else { + iind.year = iind.patchID = iind.x = iind.y = iind.sex = iind.age = iind.stage = 0; + iind.species = -1; + } #if RSDEBUG -//DEBUGLOG << "paramInit::getInitInd(): ix=" << ix << " size()=" << initinds.size() -// << " iind.patchID=" << iind.patchID -// << " iind.x=" << iind.x -// << " iind.y=" << iind.y -// << endl; + //DEBUGLOG << "paramInit::getInitInd(): ix=" << ix << " size()=" << initinds.size() + // << " iind.patchID=" << iind.patchID + // << " iind.x=" << iind.x + // << " iind.y=" << iind.y + // << endl; #endif -return iind; + return iind; } void paramInit::resetInitInds(void) { initinds.clear(); } @@ -225,7 +227,7 @@ paramSim::paramSim(void) { simulation = 0; reps = years = 1; outIntRange = 1; -// outStartRange = outStartOcc = outStartPop = outStartInd = 0; + // outStartRange = outStartOcc = outStartPop = outStartInd = 0; outStartPop = outStartInd = outStartGenetic = 0; outStartTraitCell = outStartTraitRow = outStartConn = 0; outIntOcc = outIntPop = outIntInd = outIntGenetic = 10; @@ -251,140 +253,140 @@ paramSim::paramSim(void) { paramSim::~paramSim(void) { } void paramSim::setSim(simParams s) { -if (s.batchNum >= 0) batchNum = s.batchNum; -if (s.simulation >= 0) simulation = s.simulation; -if (s.reps >= 1) reps = s.reps; -if (s.years >= 1) years = s.years; -if (s.mapInt >= 1) mapInt = s.mapInt; -if (s.traitInt >= 1) traitInt = s.traitInt; -batchMode = s.batchMode; absorbing = s.absorbing; -outRange = s.outRange; outOccup = s.outOccup; -outPop = s.outPop; outInds = s.outInds; -outGenetics = s.outGenetics; -if (s.outGenType >= 0 && s.outGenType <= 2) { - outGenType = s.outGenType; -} -outGenXtab = s.outGenXtab; -outTraitsCells = s.outTraitsCells; outTraitsRows = s.outTraitsRows; -outConnect = s.outConnect; -//if (s.outStartRange >= 0) outStartRange = s.outStartRange; -//if (s.outStartOcc >= 0) outStartOcc = s.outStartOcc; -if (s.outStartPop >= 0) outStartPop = s.outStartPop; -if (s.outStartInd >= 0) outStartInd = s.outStartInd; -if (s.outStartGenetic >= 0) outStartGenetic = s.outStartGenetic; -if (s.outStartTraitCell >= 0) outStartTraitCell = s.outStartTraitCell; -if (s.outStartTraitRow >= 0) outStartTraitRow = s.outStartTraitRow; -if (s.outStartConn >= 0) outStartConn = s.outStartConn; -if (s.outIntRange >= 1) outIntRange = s.outIntRange; -if (s.outIntOcc >= 1) outIntOcc = s.outIntOcc; -if (s.outIntPop >= 1) outIntPop = s.outIntPop; -if (s.outIntInd >= 1) outIntInd = s.outIntInd; -if (s.outIntGenetic >= 1) outIntGenetic = s.outIntGenetic; -if (s.outIntTraitCell >= 1) outIntTraitCell = s.outIntTraitCell; -if (s.outIntTraitRow >= 1) outIntTraitRow = s.outIntTraitRow; -if (s.outIntConn >= 1) outIntConn = s.outIntConn; -saveMaps = s.saveMaps; saveTraitMaps = s.saveTraitMaps; -saveVisits = s.saveVisits; + if (s.batchNum >= 0) batchNum = s.batchNum; + if (s.simulation >= 0) simulation = s.simulation; + if (s.reps >= 1) reps = s.reps; + if (s.years >= 1) years = s.years; + if (s.mapInt >= 1) mapInt = s.mapInt; + if (s.traitInt >= 1) traitInt = s.traitInt; + batchMode = s.batchMode; absorbing = s.absorbing; + outRange = s.outRange; outOccup = s.outOccup; + outPop = s.outPop; outInds = s.outInds; + outGenetics = s.outGenetics; + if (s.outGenType >= 0 && s.outGenType <= 2) { + outGenType = s.outGenType; + } + outGenXtab = s.outGenXtab; + outTraitsCells = s.outTraitsCells; outTraitsRows = s.outTraitsRows; + outConnect = s.outConnect; + //if (s.outStartRange >= 0) outStartRange = s.outStartRange; + //if (s.outStartOcc >= 0) outStartOcc = s.outStartOcc; + if (s.outStartPop >= 0) outStartPop = s.outStartPop; + if (s.outStartInd >= 0) outStartInd = s.outStartInd; + if (s.outStartGenetic >= 0) outStartGenetic = s.outStartGenetic; + if (s.outStartTraitCell >= 0) outStartTraitCell = s.outStartTraitCell; + if (s.outStartTraitRow >= 0) outStartTraitRow = s.outStartTraitRow; + if (s.outStartConn >= 0) outStartConn = s.outStartConn; + if (s.outIntRange >= 1) outIntRange = s.outIntRange; + if (s.outIntOcc >= 1) outIntOcc = s.outIntOcc; + if (s.outIntPop >= 1) outIntPop = s.outIntPop; + if (s.outIntInd >= 1) outIntInd = s.outIntInd; + if (s.outIntGenetic >= 1) outIntGenetic = s.outIntGenetic; + if (s.outIntTraitCell >= 1) outIntTraitCell = s.outIntTraitCell; + if (s.outIntTraitRow >= 1) outIntTraitRow = s.outIntTraitRow; + if (s.outIntConn >= 1) outIntConn = s.outIntConn; + saveMaps = s.saveMaps; saveTraitMaps = s.saveTraitMaps; + saveVisits = s.saveVisits; #if RS_RCPP -outStartPaths = s.outStartPaths; -outIntPaths = s.outIntPaths; -outPaths = s.outPaths; -ReturnPopRaster = s.ReturnPopRaster; -CreatePopFile = s.CreatePopFile; + outStartPaths = s.outStartPaths; + outIntPaths = s.outIntPaths; + outPaths = s.outPaths; + ReturnPopRaster = s.ReturnPopRaster; + CreatePopFile = s.CreatePopFile; #endif -drawLoaded = s.drawLoaded; + drawLoaded = s.drawLoaded; } simParams paramSim::getSim(void) { -simParams s; -s.batchNum = batchNum; -s.simulation = simulation; s.reps = reps; s.years = years; -s.outRange = outRange; s.outOccup = outOccup; s.outPop = outPop; s.outInds = outInds; -s.outGenetics = outGenetics; s.outGenType = outGenType; s.outGenXtab = outGenXtab; -s.outTraitsCells = outTraitsCells; s.outTraitsRows = outTraitsRows; s.outConnect = outConnect; -//s.outStartRange = outStartRange; -//s.outStartOcc = outStartOcc; -s.outStartPop = outStartPop; s.outStartInd = outStartInd; s.outStartGenetic = outStartGenetic; -s.outStartTraitCell = outStartTraitCell; s.outStartTraitRow = outStartTraitRow; -s.outStartConn = outStartConn; -s.outIntRange = outIntRange; -s.outIntOcc = outIntOcc; s.outIntPop = outIntPop; -s.outIntInd = outIntInd; s.outIntGenetic = outIntGenetic; -s.outIntTraitCell = outIntTraitCell; -s.outIntTraitRow = outIntTraitRow; -s.outIntConn = outIntConn; -s.batchMode = batchMode; -s.absorbing = absorbing; -s.saveMaps = saveMaps; s.saveTraitMaps = saveTraitMaps; -s.saveVisits = saveVisits; -s.mapInt = mapInt; s.traitInt = traitInt; + simParams s; + s.batchNum = batchNum; + s.simulation = simulation; s.reps = reps; s.years = years; + s.outRange = outRange; s.outOccup = outOccup; s.outPop = outPop; s.outInds = outInds; + s.outGenetics = outGenetics; s.outGenType = outGenType; s.outGenXtab = outGenXtab; + s.outTraitsCells = outTraitsCells; s.outTraitsRows = outTraitsRows; s.outConnect = outConnect; + //s.outStartRange = outStartRange; + //s.outStartOcc = outStartOcc; + s.outStartPop = outStartPop; s.outStartInd = outStartInd; s.outStartGenetic = outStartGenetic; + s.outStartTraitCell = outStartTraitCell; s.outStartTraitRow = outStartTraitRow; + s.outStartConn = outStartConn; + s.outIntRange = outIntRange; + s.outIntOcc = outIntOcc; s.outIntPop = outIntPop; + s.outIntInd = outIntInd; s.outIntGenetic = outIntGenetic; + s.outIntTraitCell = outIntTraitCell; + s.outIntTraitRow = outIntTraitRow; + s.outIntConn = outIntConn; + s.batchMode = batchMode; + s.absorbing = absorbing; + s.saveMaps = saveMaps; s.saveTraitMaps = saveTraitMaps; + s.saveVisits = saveVisits; + s.mapInt = mapInt; s.traitInt = traitInt; #if RS_RCPP -s.outStartPaths = outStartPaths; -s.outIntPaths = outIntPaths; -s.outPaths = outPaths; -s.ReturnPopRaster = ReturnPopRaster; -s.CreatePopFile = CreatePopFile; + s.outStartPaths = outStartPaths; + s.outIntPaths = outIntPaths; + s.outPaths = outPaths; + s.ReturnPopRaster = ReturnPopRaster; + s.CreatePopFile = CreatePopFile; #endif -s.drawLoaded = drawLoaded; -return s; + s.drawLoaded = drawLoaded; + return s; } int paramSim::getSimNum(void) { return simulation; } void paramSim::setViews(simView v) { -viewLand = v.viewLand; viewPatch = v.viewPatch; -viewGrad = v.viewGrad; viewCosts = v.viewCosts; -viewPop = v.viewPop; viewTraits = v.viewTraits; -viewPaths = v.viewPaths; viewGraph = v.viewGraph; -if (v.slowFactor > 0) slowFactor = v.slowFactor; + viewLand = v.viewLand; viewPatch = v.viewPatch; + viewGrad = v.viewGrad; viewCosts = v.viewCosts; + viewPop = v.viewPop; viewTraits = v.viewTraits; + viewPaths = v.viewPaths; viewGraph = v.viewGraph; + if (v.slowFactor > 0) slowFactor = v.slowFactor; } simView paramSim::getViews(void) { -simView v; -v.viewLand = viewLand; v.viewPatch = viewPatch; -v.viewGrad = viewGrad; v.viewCosts = viewCosts; -v.viewPop = viewPop; v.viewTraits = viewTraits; -v.viewPaths = viewPaths; v.viewGraph = viewGraph; -v.slowFactor = slowFactor; -return v; + simView v; + v.viewLand = viewLand; v.viewPatch = viewPatch; + v.viewGrad = viewGrad; v.viewCosts = viewCosts; + v.viewPop = viewPop; v.viewTraits = viewTraits; + v.viewPaths = viewPaths; v.viewGraph = viewGraph; + v.slowFactor = slowFactor; + return v; } void paramSim::setDir(string s) { -dir = s; + dir = s; } // return directory name depending on option specified string paramSim::getDir(int option) { -string s; -switch (option) { -case 0: // working directory - s = dir; - break; + string s; + switch (option) { + case 0: // working directory + s = dir; + break; #if LINUX_CLUSTER || RS_RCPP -case 1: // Inputs folder - s = dir + "Inputs/"; - break; -case 2: // Outputs folder - s = dir + "Outputs/"; - break; -case 3: // Maps folder - s = dir + "Output_Maps/"; - break; + case 1: // Inputs folder + s = dir + "Inputs/"; + break; + case 2: // Outputs folder + s = dir + "Outputs/"; + break; + case 3: // Maps folder + s = dir + "Output_Maps/"; + break; #else -case 1: // Inputs folder - s = dir + "Inputs\\"; - break; -case 2: // Outputs folder - s = dir + "Outputs\\"; - break; -case 3: // Maps folder - s = dir + "Output_Maps\\"; - break; + case 1: // Inputs folder + s = dir + "Inputs\\"; + break; + case 2: // Outputs folder + s = dir + "Outputs\\"; + break; + case 3: // Maps folder + s = dir + "Output_Maps\\"; + break; #endif -default: - s = "ERROR_ERROR_ERROR"; -} -return s; + default: + s = "ERROR_ERROR_ERROR"; + } + return s; } #if RS_RCPP diff --git a/Parameters.h b/Parameters.h index d44cf14..2c45bd2 100644 --- a/Parameters.h +++ b/Parameters.h @@ -1,56 +1,56 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ -RangeShifter v2.0 Parameters -Implements the following classes: + /*------------------------------------------------------------------------------ -paramGrad - Environmental gradient parameters -paramInit - Initialisation (seeding) parameters -paramSim - Simulation parameters -paramStoch - Environmental stochasticity parameters + RangeShifter v2.0 Parameters -Also declares some structures and functions used throughout the program. + Implements the following classes: -For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. -and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. -Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 + paramGrad - Environmental gradient parameters + paramInit - Initialisation (seeding) parameters + paramSim - Simulation parameters + paramStoch - Environmental stochasticity parameters -Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + Also declares some structures and functions used throughout the program. -Last updated: 25 June 2021 by Steve Palmer + For full details of RangeShifter, please see: + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. + and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial + eco-evolutionary dynamics and species’ responses to environmental changes. + Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 -------------------------------------------------------------------------------*/ + Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + + Last updated: 25 June 2021 by Steve Palmer + + ------------------------------------------------------------------------------*/ #ifndef ParametersH #define ParametersH -//#if LINUX_CLUSTER -//#include -//#else + //#if LINUX_CLUSTER + //#include + //#else #include //#endif #include @@ -88,13 +88,13 @@ typedef unsigned int intptr; #endif #if RS_RCPP - #ifndef R_EXT_CONSTANTS_H_ // the R headers define PI as a macro, so that the 'else' line results in an error - #define M_2PI 6.283185307179586 - const double PI = 3.141592653589793238462643383279502884197169399375; - #endif +#ifndef R_EXT_CONSTANTS_H_ // the R headers define PI as a macro, so that the 'else' line results in an error +#define M_2PI 6.283185307179586 +const double PI = 3.141592653589793238462643383279502884197169399375; +#endif #else - #define M_2PI 6.283185307179586 - const double PI = 3.141592654; +#define M_2PI 6.283185307179586 +const double PI = 3.141592654; #endif const double SQRT2 = std::sqrt(double(2.0)); // more efficient than calculating every time @@ -105,7 +105,7 @@ const double SQRT2 = std::sqrt(double(2.0)); // more efficient than calculating struct locn { int x; int y; }; struct rgb { // colour scheme for drawing maps - int r,g,b; + int r, g, b; }; const string Int2Str(const int); @@ -155,7 +155,7 @@ class paramGrad { bool gradient; // there a gradient bool shifting; // the gradient is shifting int gradType; // 0 = none, 1 = carrying capacity, - // 2 = growth rate, 3 = local extinction probability + // 2 = growth rate, 3 = local extinction probability float grad_inc; // gradient steepness float opt_y; // optimum row (Y dimension) float opt_y0; // optimum row at year 0 (internal use only) @@ -174,7 +174,7 @@ class paramGrad { struct envStochParams { bool stoch; bool local; bool inK; bool localExt; - float ac; float std; + float ac; float std; float locExtProb; }; @@ -212,7 +212,7 @@ struct initParams { }; struct initInd { - int year,patchID,x,y; short species,sex,age,stage; + int year, patchID, x, y; short species, sex, age, stage; }; class paramInit { @@ -236,23 +236,23 @@ class paramInit { private: short seedType; // initialisation type: 0 = free, 1 = from species distn, - // 2 = initial individuals, 3 = from file + // 2 = initial individuals, 3 = from file short freeType; // free initialisation type: - // 0 = random (given no.) - // 1 = all suitable cells/patches - // 2 = manually selected cells/patches + // 0 = random (given no.) + // 1 = all suitable cells/patches + // 2 = manually selected cells/patches short spDistType; // species distribution initialisation type: - // 0 = all suitable cells/patches, - // 1 = some randomly chosen suitable cells/patches, - // 2 = all cells/patches within selected sp. dist. cells + // 0 = all suitable cells/patches, + // 1 = some randomly chosen suitable cells/patches, + // 2 = all cells/patches within selected sp. dist. cells short initDens; // initialisation density: - // 0 = at carrying capacity - // 1 = at half carrying capacity - // 2 = specified no. per cell or density + // 0 = at carrying capacity + // 1 = at half carrying capacity + // 2 = specified no. per cell or density short initAge; // initial age distribution within each stage: - // 0 = lowest possible age - // 1 = randomised - // 2 = quasi-equilibrium + // 0 = lowest possible age + // 1 = randomised + // 2 = quasi-equilibrium int initFrzYr; // year until which initial range is frozen bool restrictRange; // restrict range to northern front int restrictRows; // no. of rows to retain behind front @@ -280,8 +280,8 @@ class paramInit { struct simParams { int batchNum; int simulation; int reps; int years; -// int outStartRange; -// int outStartOcc; + // int outStartRange; + // int outStartOcc; int outStartPop; int outStartInd; int outStartGenetic; int outStartTraitCell; int outStartTraitRow; int outStartConn; int outIntRange; int outIntOcc; int outIntPop; int outIntInd; int outIntGenetic; @@ -328,8 +328,8 @@ class paramSim { int simulation; // simulation no. int reps; // no. of replicates int years; // no. of years -// int outStartRange; // output start year for range file -// int outStartOcc; // output start year for occupancy file + // int outStartRange; // output start year for range file + // int outStartOcc; // output start year for occupancy file int outStartPop; // output start year for population file int outStartInd; // output start year for individuals file int outStartGenetic; // output start year for genetics file @@ -349,14 +349,14 @@ class paramSim { int slowFactor; // to reduce speed of movement paths on screen bool batchMode; // bool absorbing; // landscape boundary and no-data regions are - // absorbing boundaries + // absorbing boundaries bool outRange; // produce output range file? bool outOccup; // produce output occupancy file? bool outPop; // produce output population file? bool outInds; // produce output individuals file? bool outGenetics; // produce output genetics file? short outGenType; // produce output genetics for: 0 = juveniles only - // 1 = all individuals, 2 = adults (i.e. final stage) only + // 1 = all individuals, 2 = adults (i.e. final stage) only bool outGenXtab; // produce output genetics as a cross table? bool outTraitsCells; // produce output summary traits by cell file? bool outTraitsRows; // produce output summary traits by row (y) file? diff --git a/Patch.cpp b/Patch.cpp index 60421c4..abfb93a 100644 --- a/Patch.cpp +++ b/Patch.cpp @@ -1,47 +1,47 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Patch.h" //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -Patch::Patch(int seqnum,int num) +Patch::Patch(int seqnum, int num) { -patchSeqNum = seqnum; patchNum = num; nCells = 0; -xMin = yMin = 999999999; xMax = yMax = 0; x = y = 0; -subCommPtr = 0; -localK = 0.0; -for (int sex = 0; sex < NSEXES; sex++) { - nTemp[sex] = 0; -} -changed = false; + patchSeqNum = seqnum; patchNum = num; nCells = 0; + xMin = yMin = 999999999; xMax = yMax = 0; x = y = 0; + subCommPtr = 0; + localK = 0.0; + for (int sex = 0; sex < NSEXES; sex++) { + nTemp[sex] = 0; + } + changed = false; } Patch::~Patch() { -cells.clear(); -popns.clear(); + cells.clear(); + popns.clear(); } int Patch::getSeqNum(void) { return patchSeqNum; } @@ -51,68 +51,68 @@ int Patch::getPatchNum(void) { return patchNum; } int Patch::getNCells(void) { return nCells; } patchLimits Patch::getLimits(void) { -patchLimits p; -p.xMin = xMin; p.xMax = xMax; p.yMin = yMin; p.yMax = yMax; -return p; + patchLimits p; + p.xMin = xMin; p.xMax = xMax; p.yMin = yMin; p.yMax = yMax; + return p; } // Does the patch fall (partially) within a specified rectangle? -bool Patch::withinLimits(patchLimits rect){ -locn loc; -if (xMin <= rect.xMax && xMax >= rect.xMin && yMin <= rect.yMax && yMax >= rect.yMin) { - // patch is within the rectangle UNLESS it is irregular in shape and lies at a corner - // of the rectangle - if ((xMin >= rect.xMin && xMax <= rect.xMax) - || (yMin >= rect.yMin && yMax <= rect.yMax)) { - // patch lies within or along an edge of the initialistaion rectangle - return true; - } - else { - // check for any cell of the patch lying within the rectangle - int ncells = (int)cells.size(); - for (int i = 0; i < ncells; i++) { - loc = getCellLocn(i); - if (loc.x >= rect.xMin && loc.x <= rect.xMax - && loc.y >= rect.yMin && loc.y <= rect.yMax) { - // cell lies within the rectangle - return true; - } +bool Patch::withinLimits(patchLimits rect) { + locn loc; + if (xMin <= rect.xMax && xMax >= rect.xMin && yMin <= rect.yMax && yMax >= rect.yMin) { + // patch is within the rectangle UNLESS it is irregular in shape and lies at a corner + // of the rectangle + if ((xMin >= rect.xMin && xMax <= rect.xMax) + || (yMin >= rect.yMin && yMax <= rect.yMax)) { + // patch lies within or along an edge of the initialistaion rectangle + return true; + } + else { + // check for any cell of the patch lying within the rectangle + int ncells = (int)cells.size(); + for (int i = 0; i < ncells; i++) { + loc = getCellLocn(i); + if (loc.x >= rect.xMin && loc.x <= rect.xMax + && loc.y >= rect.yMin && loc.y <= rect.yMax) { + // cell lies within the rectangle + return true; } } } -return false; + } + return false; } // Reset minimum and maximum co-ordinates of the patch if it has been changed void Patch::resetLimits(void) { -if (changed) { - // remove any deleted cells - std::vector newcells; // for all retained and added cells - int ncells = (int)cells.size(); - for (int i = 0; i < ncells; i++) { - if (cells[i] != NULL) { - newcells.push_back(cells[i]); + if (changed) { + // remove any deleted cells + std::vector newcells; // for all retained and added cells + int ncells = (int)cells.size(); + for (int i = 0; i < ncells; i++) { + if (cells[i] != NULL) { + newcells.push_back(cells[i]); + } } + cells.clear(); + cells = newcells; + // reset patch limits + locn loc; + xMin = yMin = 999999999; xMax = yMax = 0; + ncells = (int)cells.size(); + for (int i = 0; i < ncells; i++) { + loc = getCellLocn(i); + if (loc.x < xMin) xMin = loc.x; + if (loc.x > xMax) xMax = loc.x; + if (loc.y < yMin) yMin = loc.y; + if (loc.y > yMax) yMax = loc.y; + } + changed = false; } - cells.clear(); - cells = newcells; - // reset patch limits - locn loc; - xMin = yMin = 999999999; xMax = yMax = 0; - ncells = (int)cells.size(); - for (int i = 0; i < ncells; i++) { - loc = getCellLocn(i); - if (loc.x < xMin) xMin = loc.x; - if (loc.x > xMax) xMax = loc.x; - if (loc.y < yMin) yMin = loc.y; - if (loc.y > yMax) yMax = loc.y; - } - changed = false; -} } // Add a cell to the patch -void Patch::addCell(Cell* pCell,int x,int y) { +void Patch::addCell(Cell* pCell, int x, int y) { cells.push_back(pCell); nCells++; if (x < xMin) xMin = x; @@ -123,126 +123,126 @@ void Patch::addCell(Cell* pCell,int x,int y) { // Calculate the total carrying capacity (no. of individuals) and // centroid co-ordinates of the patch -void Patch::setCarryingCapacity(Species *pSpecies,patchLimits landlimits, - float epsGlobal,short nHab,short rasterType,short landIx,bool gradK) { -envStochParams env = paramsStoch->getStoch(); -//Cell *pCell; -locn loc; -int xsum,ysum; -short hx; -float k,q,envval; - -localK = 0.0; // no. of suitable cells (unadjusted K > 0) in the patch -int nsuitable = 0; -double mean; +void Patch::setCarryingCapacity(Species* pSpecies, patchLimits landlimits, + float epsGlobal, short nHab, short rasterType, short landIx, bool gradK) { + envStochParams env = paramsStoch->getStoch(); + //Cell *pCell; + locn loc; + int xsum, ysum; + short hx; + float k, q, envval; + + localK = 0.0; // no. of suitable cells (unadjusted K > 0) in the patch + int nsuitable = 0; + double mean; #if RSDEBUG -//DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum -// << " xMin=" << xMin << " yMin=" << yMin << " xMax=" << xMax << " yMax=" << yMax -// << endl; + //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum + // << " xMin=" << xMin << " yMin=" << yMin << " xMax=" << xMax << " yMax=" << yMax + // << endl; #endif -if (xMin > landlimits.xMax || xMax < landlimits.xMin -|| yMin > landlimits.yMax || yMax < landlimits.yMin) { - // patch lies wholely outwith current landscape limits - // NB the next statement is unnecessary, as localK has been set to zero above - // retained only for consistency in standard variant - localK = 0.0; + if (xMin > landlimits.xMax || xMax < landlimits.xMin + || yMin > landlimits.yMax || yMax < landlimits.yMin) { + // patch lies wholely outwith current landscape limits + // NB the next statement is unnecessary, as localK has been set to zero above + // retained only for consistency in standard variant + localK = 0.0; #if RSDEBUG -//DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum -// << " localK=" << localK -// << endl; + //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum + // << " localK=" << localK + // << endl; #endif - return; -} - -int ncells = (int)cells.size(); -xsum = ysum = 0; -for (int i = 0; i < ncells; i++) { - if (gradK) // gradient in carrying capacity - envval = cells[i]->getEnvVal(); // environmental gradient value - else envval = 1.0; // no gradient effect - if (env.stoch && env.inK) { // environmental stochasticity in K - if (env.local) { -// pCell = getRandomCell(); -// if (pCell != 0) envval += pCell->getEps(); - envval += cells[i]->getEps(); - } - else { // global stochasticity - envval += epsGlobal; - } + return; } - switch (rasterType) { - case 0: // habitat codes - hx = cells[i]->getHabIndex(landIx); - k = pSpecies->getHabK(hx); - if (k > 0.0) { - nsuitable++; - localK += envval * k; - } - break; - case 1: // cover % - k = 0.0; - for (int j = 0; j < nHab; j++) { // loop through cover layers - q = cells[i]->getHabitat(j); - k += q * pSpecies->getHabK(j) / 100.0f; - } - if (k > 0.0) { - nsuitable++; - localK += envval * k; + + int ncells = (int)cells.size(); + xsum = ysum = 0; + for (int i = 0; i < ncells; i++) { + if (gradK) // gradient in carrying capacity + envval = cells[i]->getEnvVal(); // environmental gradient value + else envval = 1.0; // no gradient effect + if (env.stoch && env.inK) { // environmental stochasticity in K + if (env.local) { + // pCell = getRandomCell(); + // if (pCell != 0) envval += pCell->getEps(); + envval += cells[i]->getEps(); + } + else { // global stochasticity + envval += epsGlobal; + } } - break; - case 2: // habitat quality - q = cells[i]->getHabitat(landIx); - if (q > 0.0) { - nsuitable++; - localK += envval * pSpecies->getHabK(0) * q / 100.0f; + switch (rasterType) { + case 0: // habitat codes + hx = cells[i]->getHabIndex(landIx); + k = pSpecies->getHabK(hx); + if (k > 0.0) { + nsuitable++; + localK += envval * k; + } + break; + case 1: // cover % + k = 0.0; + for (int j = 0; j < nHab; j++) { // loop through cover layers + q = cells[i]->getHabitat(j); + k += q * pSpecies->getHabK(j) / 100.0f; + } + if (k > 0.0) { + nsuitable++; + localK += envval * k; + } + break; + case 2: // habitat quality + q = cells[i]->getHabitat(landIx); + if (q > 0.0) { + nsuitable++; + localK += envval * pSpecies->getHabK(0) * q / 100.0f; + } + break; } - break; - } #if RSDEBUG -//DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum -// << " i=" << i << " hx=" << hx << " q=" << q << " k=" << k << " localK=" << localK -// << endl; + //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum + // << " i=" << i << " hx=" << hx << " q=" << q << " k=" << k << " localK=" << localK + // << endl; #endif - loc = cells[i]->getLocn(); - xsum += loc.x; ysum += loc.y; -} + loc = cells[i]->getLocn(); + xsum += loc.x; ysum += loc.y; + } #if RSDEBUG -//DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum -// << " epsGlobal=" << epsGlobal << " localK=" << localK -// << endl; + //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum + // << " epsGlobal=" << epsGlobal << " localK=" << localK + // << endl; #endif // calculate centroid co-ordinates -if (ncells > 0) { - mean = (double)xsum / (double)ncells; - x = (int)(mean + 0.5); - mean = (double)ysum / (double)ncells; - y = (int)(mean + 0.5); -} -if (env.stoch && env.inK) { // environmental stochasticity in K - // apply min and max limits to K over the whole patch - // NB limits have been stored as N/cell rather than N/ha - float limit; - limit = pSpecies->getMinMax(0) * (float)nsuitable; - if (localK < limit) localK = limit; + if (ncells > 0) { + mean = (double)xsum / (double)ncells; + x = (int)(mean + 0.5); + mean = (double)ysum / (double)ncells; + y = (int)(mean + 0.5); + } + if (env.stoch && env.inK) { // environmental stochasticity in K + // apply min and max limits to K over the whole patch + // NB limits have been stored as N/cell rather than N/ha + float limit; + limit = pSpecies->getMinMax(0) * (float)nsuitable; + if (localK < limit) localK = limit; #if RSDEBUG -//DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum -// << " limit=" << limit << " localK=" << localK -// << endl; + //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum + // << " limit=" << limit << " localK=" << localK + // << endl; #endif - limit = pSpecies->getMinMax(1) * (float)nsuitable; - if (localK > limit) localK = limit; + limit = pSpecies->getMinMax(1) * (float)nsuitable; + if (localK > limit) localK = limit; #if RSDEBUG -//DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum -// << " limit=" << limit << " localK=" << localK -// << endl; + //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum + // << " limit=" << limit << " localK=" << localK + // << endl; #endif -} + } #if RSDEBUG -//DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum -// << " localK=" << localK -// << endl; + //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum + // << " localK=" << localK + // << endl; #endif } @@ -251,103 +251,107 @@ float Patch::getK(void) { return localK; } // Return co-ordinates of a specified cell locn Patch::getCellLocn(int ix) { -locn loc; loc.x = -666; loc.y = -666; -int ncells = (int)cells.size(); -if (ix >= 0 && ix < ncells) { - loc = cells[ix]->getLocn(); -} -return loc; + locn loc; loc.x = -666; loc.y = -666; + int ncells = (int)cells.size(); + if (ix >= 0 && ix < ncells) { + loc = cells[ix]->getLocn(); + } + return loc; } // Return pointer to a specified cell -Cell* Patch::getCell(int ix) { -int ncells = (int)cells.size(); -if (ix >= 0 && ix < ncells) return cells[ix]; -else return 0; +Cell* Patch::getCell(int ix) { + int ncells = (int)cells.size(); + if (ix >= 0 && ix < ncells) return cells[ix]; + else return 0; } // Return co-ordinates of patch centroid locn Patch::getCentroid(void) { -locn loc; loc.x = x; loc.y = y; -return loc; + locn loc; loc.x = x; loc.y = y; + return loc; } // Select a Cell within the Patch at random, and return pointer to it // For a cell-based model, this will be the only Cell Cell* Patch::getRandomCell(void) { -Cell *pCell = 0; -int ix; -int ncells = (int)cells.size(); -if (ncells > 0) { - if (ncells == 1) ix = 0; - else ix = pRandom->IRandom(0,ncells-1); - pCell = cells[ix]; -} -return pCell; + Cell* pCell = 0; + int ix; + int ncells = (int)cells.size(); + if (ncells > 0) { + if (ncells == 1) ix = 0; + else ix = pRandom->IRandom(0, ncells - 1); + pCell = cells[ix]; + } + return pCell; } // Remove a cell from the patch void Patch::removeCell(Cell* pCell) { -int ncells = (int)cells.size(); -for (int i = 0; i < ncells; i++) { - if (pCell == cells[i]) { - cells[i] = NULL; i = ncells; - nCells--; - changed = true; + int ncells = (int)cells.size(); + for (int i = 0; i < ncells; i++) { + if (pCell == cells[i]) { + cells[i] = NULL; i = ncells; + nCells--; + changed = true; + } } } -} void Patch::setSubComm(intptr sc) -{ subCommPtr = sc; } +{ + subCommPtr = sc; +} // Get pointer to corresponding Sub-community (cast as an integer) intptr Patch::getSubComm(void) -{ return subCommPtr; } +{ + return subCommPtr; +} void Patch::addPopn(patchPopn pop) { -popns.push_back(pop); + popns.push_back(pop); } // Return pointer (cast as integer) to the Population of the specified Species intptr Patch::getPopn(intptr sp) { -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { - if (popns[i].pSp == sp) return popns[i].pPop; -} -return 0; + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { + if (popns[i].pSp == sp) return popns[i].pPop; + } + return 0; } void Patch::resetPopn(void) { -popns.clear(); + popns.clear(); } void Patch::resetPossSettlers(void) { -for (int sex = 0; sex < NSEXES; sex++) { - nTemp[sex] = 0; -} + for (int sex = 0; sex < NSEXES; sex++) { + nTemp[sex] = 0; + } } // Record the presence of a potential settler within the Patch -void Patch::incrPossSettler(Species *pSpecies,int sex) { +void Patch::incrPossSettler(Species* pSpecies, int sex) { #if RSDEBUG -//DEBUGLOG << "Patch::incrPossSettler(): 5555: patchNum = " << patchNum -// << " sex = " << sex << endl; + //DEBUGLOG << "Patch::incrPossSettler(): 5555: patchNum = " << patchNum + // << " sex = " << sex << endl; #endif // NOTE: THE FOLLOWING OPERATION WILL NEED TO BE MADE SPECIES-SPECIFIC... -if (sex >= 0 && sex < NSEXES) { - nTemp[sex]++; -} + if (sex >= 0 && sex < NSEXES) { + nTemp[sex]++; + } } // Get number of a potential settlers within the Patch -int Patch::getPossSettlers(Species *pSpecies,int sex) { +int Patch::getPossSettlers(Species* pSpecies, int sex) { #if RSDEBUG -//DEBUGLOG << "Patch::getPossSettlers(): 5555: patchNum = " << patchNum -// << " sex = " << sex << endl; + //DEBUGLOG << "Patch::getPossSettlers(): 5555: patchNum = " << patchNum + // << " sex = " << sex << endl; #endif // NOTE: THE FOLLOWING OPERATION WILL NEED TO BE MADE SPECIES-SPECIFIC... -if (sex >= 0 && sex < NSEXES) return nTemp[sex]; -else return 0; + if (sex >= 0 && sex < NSEXES) return nTemp[sex]; + else return 0; } //--------------------------------------------------------------------------- diff --git a/Patch.h b/Patch.h index 2bc30e7..eccb9d2 100644 --- a/Patch.h +++ b/Patch.h @@ -1,66 +1,66 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ -RangeShifter v2.0 Patch -Implements the class: Patch + /*------------------------------------------------------------------------------ -A patch is a collection of one or more Cells in the the gridded Landscape, -which together provide the area in which a single demographic unit of a Species, -i.e. a Population, can reproduce. One or more Populations (of different Species) -form a Sub-community associated with the Patch. + RangeShifter v2.0 Patch -There is no requirement that all the Cells be adjacent, although in practice -that would usually be the case. + Implements the class: Patch -Each Patch must have a unique positive integer id number supplied by the user, -and the matrix, i.e. any part of the landscape which is not a breeding patch, -is represented by Patch 0. However, as patch numbers need not be sequential, -an internal sequential number is also applied. + A patch is a collection of one or more Cells in the the gridded Landscape, + which together provide the area in which a single demographic unit of a Species, + i.e. a Population, can reproduce. One or more Populations (of different Species) + form a Sub-community associated with the Patch. -For a 'cell-based model', the user supplies no patch numbers, and a separate -Patch is generated internally for each Cell, i.e. the 'cell-based model' is a -special case of the 'patch-based model' in which each Patch has a single Cell. -Moreover, there is also the 'matrix' Patch 0, which has no cells, but which -holds the disperser population whilst its Individuals are in transit. + There is no requirement that all the Cells be adjacent, although in practice + that would usually be the case. -In a true patch-based model, each Patch hold a list of its constituent Cells, -EXCEPT for the matrix Patch 0. This is because that list would be extremely -long for a very large landscape in which suitable patches are small and/or rare, -and removing Cells from it if the landscape is dynamic would be inefficient. + Each Patch must have a unique positive integer id number supplied by the user, + and the matrix, i.e. any part of the landscape which is not a breeding patch, + is represented by Patch 0. However, as patch numbers need not be sequential, + an internal sequential number is also applied. -For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. -and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. -Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 + For a 'cell-based model', the user supplies no patch numbers, and a separate + Patch is generated internally for each Cell, i.e. the 'cell-based model' is a + special case of the 'patch-based model' in which each Patch has a single Cell. + Moreover, there is also the 'matrix' Patch 0, which has no cells, but which + holds the disperser population whilst its Individuals are in transit. -Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + In a true patch-based model, each Patch hold a list of its constituent Cells, + EXCEPT for the matrix Patch 0. This is because that list would be extremely + long for a very large landscape in which suitable patches are small and/or rare, + and removing Cells from it if the landscape is dynamic would be inefficient. -Last updated: 25 June 2021 by Steve Palmer + For full details of RangeShifter, please see: + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. + and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial + eco-evolutionary dynamics and species’ responses to environmental changes. + Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 -------------------------------------------------------------------------------*/ + Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + + Last updated: 25 June 2021 by Steve Palmer + + ------------------------------------------------------------------------------*/ #ifndef PatchH #define PatchH @@ -83,13 +83,13 @@ using namespace std; //--------------------------------------------------------------------------- struct patchLimits { - int xMin,xMax,yMin,yMax; + int xMin, xMax, yMin, yMax; }; struct patchPopn { - intptr pSp,pPop; // pointers to Species and Population cast as integers + intptr pSp, pPop; // pointers to Species and Population cast as integers }; -class Patch{ +class Patch { public: Patch( int, // internal sequential number @@ -106,7 +106,7 @@ class Patch{ void resetLimits(void); // Reset minimum and maximum co-ordinates of the patch void addCell( Cell*, // pointer to the Cell to be added to the Patch - int,int // x (column) and y (row) co-ordinates of the Cell + int, int // x (column) and y (row) co-ordinates of the Cell ); locn getCellLocn( // Return co-ordinates of a specified cell int // index no. of the Cell within the vector cells @@ -150,19 +150,19 @@ class Patch{ ); float getK(void); // dummy function for batch version - void drawCells(float,int,rgb); + void drawCells(float, int, rgb); - private: +private: int patchSeqNum;// sequential patch number - patch 0 is reserved for the inter-patch matrix int patchNum; // patch number as supplied by the user (not forced to be sequential) int nCells; // no. of cells in the patch - int xMin,xMax,yMin,yMax; // min and max cell co-ordinates - int x,y; // centroid co-ordinates (approx.) + int xMin, xMax, yMin, yMax; // min and max cell co-ordinates + int x, y; // centroid co-ordinates (approx.) intptr subCommPtr; // pointer (cast as integer) to sub-community associated with the patch // NOTE: FOR MULTI-SPECIES MODEL, PATCH WILL NEED TO STORE K FOR EACH SPECIES float localK; // patch carrying capacity (individuals) bool changed; -// NOTE: THE FOLLOWING ARRAY WILL NEED TO BE MADE SPECIES-SPECIFIC... + // NOTE: THE FOLLOWING ARRAY WILL NEED TO BE MADE SPECIES-SPECIFIC... short nTemp[NSEXES]; // no. of potential settlers in each sex std::vector cells; @@ -172,8 +172,8 @@ class Patch{ //--------------------------------------------------------------------------- -extern paramStoch *paramsStoch; -extern RSrandom *pRandom; +extern paramStoch* paramsStoch; +extern RSrandom* pRandom; #if RSDEBUG extern ofstream DEBUGLOG; diff --git a/Population.cpp b/Population.cpp index 05d8633..76b4766 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Population.h" //--------------------------------------------------------------------------- @@ -30,734 +30,734 @@ ofstream outInds; //--------------------------------------------------------------------------- -Population::Population(void) { -nSexes = nStages = 0; -pPatch = NULL; -pSpecies = NULL; -return; +Population::Population(void) { + nSexes = nStages = 0; + pPatch = NULL; + pSpecies = NULL; + return; } -Population::Population(Species *pSp,Patch *pPch,int ninds,int resol) +Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) { -// constructor for a Population of a specified size + // constructor for a Population of a specified size #if RSDEBUG //DEBUGLOG << "Population::Population(): this=" << this // << " pPch=" << pPch << " ninds="<< ninds << endl; #endif -int n,nindivs,age = 0,minage,maxage,nAges = 0; -int cumtotal = 0; -float probmale; -double ageprob,ageprobsum; -std::vector ageProb; // for quasi-equilibrium initial age distribution -Cell *pCell; + int n, nindivs, age = 0, minage, maxage, nAges = 0; + int cumtotal = 0; + float probmale; + double ageprob, ageprobsum; + std::vector ageProb; // for quasi-equilibrium initial age distribution + Cell* pCell; -if (ninds > 0) { - inds.reserve(ninds); - juvs.reserve(ninds); -} + if (ninds > 0) { + inds.reserve(ninds); + juvs.reserve(ninds); + } -pSpecies = pSp; -pPatch = pPch; -// record the new population in the patch -patchPopn pp; -pp.pSp = (intptr)pSpecies; pp.pPop = (intptr)this; -pPatch->addPopn(pp); + pSpecies = pSp; + pPatch = pPch; + // record the new population in the patch + patchPopn pp; + pp.pSp = (intptr)pSpecies; pp.pPop = (intptr)this; + pPatch->addPopn(pp); #if RSDEBUG -//DEBUGLOG << "Population::Population(): this=" << this -// << " added population to patch " << endl; + //DEBUGLOG << "Population::Population(): this=" << this + // << " added population to patch " << endl; #endif -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -//trfrSMSTraits sms = pSpecies->getSMSTraits(); -settleType sett = pSpecies->getSettle(); -genomeData gen = pSpecies->getGenomeData(); -initParams init = paramsInit->getInit(); + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + //trfrSMSTraits sms = pSpecies->getSMSTraits(); + settleType sett = pSpecies->getSettle(); + genomeData gen = pSpecies->getGenomeData(); + initParams init = paramsInit->getInit(); -// determine no. of stages and sexes of species to initialise -if (dem.stageStruct) { - nStages = sstruct.nStages; -} -else // non-structured population has 2 stages, but user only ever sees stage 1 - nStages = 2; -if (dem.repType == 0) { nSexes = 1; probmale = 0.0; } -else { nSexes = 2; probmale = dem.propMales; } - -// set up population sub-totals -for (int stg = 0; stg < NSTAGES; stg++) { - for (int sex = 0; sex < NSEXES; sex++) { - nInds[stg][sex] = 0; + // determine no. of stages and sexes of species to initialise + if (dem.stageStruct) { + nStages = sstruct.nStages; + } + else // non-structured population has 2 stages, but user only ever sees stage 1 + nStages = 2; + if (dem.repType == 0) { nSexes = 1; probmale = 0.0; } + else { nSexes = 2; probmale = dem.propMales; } + + // set up population sub-totals + for (int stg = 0; stg < NSTAGES; stg++) { + for (int sex = 0; sex < NSEXES; sex++) { + nInds[stg][sex] = 0; + } } -} -// set up local copy of minimum age table -short minAge[NSTAGES][NSEXES]; -for (int stg = 0; stg < nStages; stg++) { - for (int sex = 0; sex < nSexes; sex++) { - if (dem.stageStruct) { - if (dem.repType == 1) { // simple sexual model - // both sexes use minimum ages recorded for females - minAge[stg][sex] = pSpecies->getMinAge(stg,0); + // set up local copy of minimum age table + short minAge[NSTAGES][NSEXES]; + for (int stg = 0; stg < nStages; stg++) { + for (int sex = 0; sex < nSexes; sex++) { + if (dem.stageStruct) { + if (dem.repType == 1) { // simple sexual model + // both sexes use minimum ages recorded for females + minAge[stg][sex] = pSpecies->getMinAge(stg, 0); + } + else { + minAge[stg][sex] = pSpecies->getMinAge(stg, sex); + } } - else { - minAge[stg][sex] = pSpecies->getMinAge(stg,sex); + else { // non-structured population + minAge[stg][sex] = 0; } - } - else { // non-structured population - minAge[stg][sex] = 0; - } #if RSDEBUG -//DEBUGLOG << "Population::Population(): 1111 " -// << " minAge[" << stg << "][" << sex << "]=" << minAge[stg][sex] -// << endl; + //DEBUGLOG << "Population::Population(): 1111 " + // << " minAge[" << stg << "][" << sex << "]=" << minAge[stg][sex] + // << endl; #endif + } } -} -// individuals of new population must be >= stage 1 -for (int stg = 1; stg < nStages; stg++) { - if (dem.stageStruct) { // allocate to stages according to initialisation conditions - // final stage is treated separately to ensure that correct total - // no. of individuals is created - if (stg == nStages-1) { - n = ninds - cumtotal; + // individuals of new population must be >= stage 1 + for (int stg = 1; stg < nStages; stg++) { + if (dem.stageStruct) { // allocate to stages according to initialisation conditions + // final stage is treated separately to ensure that correct total + // no. of individuals is created + if (stg == nStages - 1) { + n = ninds - cumtotal; + } + else { + n = (int)(ninds * paramsInit->getProp(stg) + 0.5); + cumtotal += n; + } } - else { - n = (int)(ninds * paramsInit->getProp(stg) + 0.5); - cumtotal += n; + else { // non-structured - all individuals go into stage 1 + n = ninds; } - } - else { // non-structured - all individuals go into stage 1 - n = ninds; - } -// for (int sex = 0; sex < nSexes; sex++) { -// if (n < nSexes) n = nSexes; // to ensure at least one individual of each age is created -// subPops.push_back(new SubPop(loc,stg,sex,n/nSexes)); -// } - // establish initial age distribution - minage = maxage = stg; - if (dem.stageStruct) { - // allow for stage-dependent minimum ages (use whichever sex is greater) - if (minAge[stg][0] > 0 && minage < minAge[stg][0]) minage = minAge[stg][0]; - if (nSexes == 2 && minAge[stg][1] > 0 && minage < minAge[stg][1]) minage = minAge[stg][1]; - // allow for specified age distribution - if (init.initAge != 0) { // not lowest age - if (stg == nStages-1) maxage = sstruct.maxAge; // final stage - else { // all other stages - use female max age, as sex of individuals is not predetermined - maxage = minAge[stg+1][0] - 1; - } - if (maxage < minage) maxage = minage; - nAges = maxage - minage + 1; - if (init.initAge == 2) { // quasi-equilibrium distribution - double psurv = (double)pSpecies->getSurv(stg,0); // use female survival for the stage - ageProb.clear(); - ageprobsum = 0.0; - ageprob = 1.0; - for (int i = 0; i < nAges; i++) { - ageProb.push_back(ageprob); ageprobsum += ageprob; ageprob *= psurv; + // for (int sex = 0; sex < nSexes; sex++) { + // if (n < nSexes) n = nSexes; // to ensure at least one individual of each age is created + // subPops.push_back(new SubPop(loc,stg,sex,n/nSexes)); + // } + // establish initial age distribution + minage = maxage = stg; + if (dem.stageStruct) { + // allow for stage-dependent minimum ages (use whichever sex is greater) + if (minAge[stg][0] > 0 && minage < minAge[stg][0]) minage = minAge[stg][0]; + if (nSexes == 2 && minAge[stg][1] > 0 && minage < minAge[stg][1]) minage = minAge[stg][1]; + // allow for specified age distribution + if (init.initAge != 0) { // not lowest age + if (stg == nStages - 1) maxage = sstruct.maxAge; // final stage + else { // all other stages - use female max age, as sex of individuals is not predetermined + maxage = minAge[stg + 1][0] - 1; } - for (int i = 0; i < nAges; i++) { - ageProb[i] /= ageprobsum; - if (i > 0) ageProb[i] += ageProb[i-1]; // to give cumulative probability + if (maxage < minage) maxage = minage; + nAges = maxage - minage + 1; + if (init.initAge == 2) { // quasi-equilibrium distribution + double psurv = (double)pSpecies->getSurv(stg, 0); // use female survival for the stage + ageProb.clear(); + ageprobsum = 0.0; + ageprob = 1.0; + for (int i = 0; i < nAges; i++) { + ageProb.push_back(ageprob); ageprobsum += ageprob; ageprob *= psurv; + } + for (int i = 0; i < nAges; i++) { + ageProb[i] /= ageprobsum; + if (i > 0) ageProb[i] += ageProb[i - 1]; // to give cumulative probability + } } } } - } #if RSDEBUG -//DEBUGLOG << "Population::Population(): this=" << this -// << " n=" << n << " stg=" << stg << " minage=" << minage << " maxage=" << maxage -// << endl; + //DEBUGLOG << "Population::Population(): this=" << this + // << " n=" << n << " stg=" << stg << " minage=" << minage << " maxage=" << maxage + // << endl; #endif // create individuals - int sex; - nindivs = (int)inds.size(); - for (int i = 0; i < n; i++) { - pCell = pPatch->getRandomCell(); - if (dem.stageStruct) { - switch (init.initAge) { - case 0: // lowest possible age - age = minage; - break; - case 1: // randomised - if (maxage > minage) age = pRandom->IRandom(minage,maxage); - else age = minage; - break; - case 2: // quasi-equilibrium - if (nAges > 1) { - double rrr = pRandom->Random(); - int ageclass = 0; - while (rrr > ageProb[ageclass]) ageclass++; - age = minage + ageclass; + int sex; + nindivs = (int)inds.size(); + for (int i = 0; i < n; i++) { + pCell = pPatch->getRandomCell(); + if (dem.stageStruct) { + switch (init.initAge) { + case 0: // lowest possible age + age = minage; + break; + case 1: // randomised + if (maxage > minage) age = pRandom->IRandom(minage, maxage); + else age = minage; + break; + case 2: // quasi-equilibrium + if (nAges > 1) { + double rrr = pRandom->Random(); + int ageclass = 0; + while (rrr > ageProb[ageclass]) ageclass++; + age = minage + ageclass; + } + else age = minage; + break; } - else age = minage; - break; } - } - else age = stg; + else age = stg; #if RSDEBUG - // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... - inds.push_back(new Individual(pCell,pPatch,stg,age,sstruct.repInterval, - probmale,true,trfr.moveType)); + // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... + inds.push_back(new Individual(pCell, pPatch, stg, age, sstruct.repInterval, + probmale, true, trfr.moveType)); #else - inds.push_back(new Individual(pCell,pPatch,stg,age,sstruct.repInterval, - probmale,trfr.moveModel,trfr.moveType)); -#endif - sex = inds[nindivs+i]->getSex(); - if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) - { - // individual variation - set up genetics - inds[nindivs+i]->setGenes(pSpecies,resol); + inds.push_back(new Individual(pCell, pPatch, stg, age, sstruct.repInterval, + probmale, trfr.moveModel, trfr.moveType)); +#endif + sex = inds[nindivs + i]->getSex(); + if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) + { + // individual variation - set up genetics + inds[nindivs + i]->setGenes(pSpecies, resol); + } + nInds[stg][sex]++; } - nInds[stg][sex]++; } -} #if RSDEBUG -//DEBUGLOG << "Population::Population(): this=" << this -// << " finished " << endl; + //DEBUGLOG << "Population::Population(): this=" << this + // << " finished " << endl; #endif } Population::~Population(void) { -int ninds = (int)inds.size(); -for (int i = 0; i < ninds; i++) { - if (inds[i] != NULL) delete inds[i]; -} -inds.clear(); -int njuvs = (int)juvs.size(); -for (int i = 0; i < njuvs; i++) { - if (juvs[i] != NULL) delete juvs[i]; -} -juvs.clear(); -} - -traitsums Population::getTraits(Species *pSpecies) { -int g; -traitsums ts; -for (int i = 0; i < NSEXES; i++) { - ts.ninds[i] = 0; - ts.sumD0[i] = ts.ssqD0[i] = 0.0; - ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; - ts.sumDist1[i] = ts.ssqDist1[i] = 0.0; ts.sumDist2[i] = ts.ssqDist2[i] = 0.0; - ts.sumProp1[i] = ts.ssqProp1[i] = 0.0; - ts.sumDP[i] = ts.ssqDP[i] = 0.0; - ts.sumGB[i] = ts.ssqGB[i] = 0.0; - ts.sumAlphaDB[i] = ts.ssqAlphaDB[i] = 0.0; - ts.sumBetaDB[i] = ts.ssqBetaDB[i] = 0.0; - ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; - ts.sumS0[i] = ts.ssqS0[i] = 0.0; - ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; -} -//locus loc; + int ninds = (int)inds.size(); + for (int i = 0; i < ninds; i++) { + if (inds[i] != NULL) delete inds[i]; + } + inds.clear(); + int njuvs = (int)juvs.size(); + for (int i = 0; i < njuvs; i++) { + if (juvs[i] != NULL) delete juvs[i]; + } + juvs.clear(); +} + +traitsums Population::getTraits(Species* pSpecies) { + int g; + traitsums ts; + for (int i = 0; i < NSEXES; i++) { + ts.ninds[i] = 0; + ts.sumD0[i] = ts.ssqD0[i] = 0.0; + ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; + ts.sumDist1[i] = ts.ssqDist1[i] = 0.0; ts.sumDist2[i] = ts.ssqDist2[i] = 0.0; + ts.sumProp1[i] = ts.ssqProp1[i] = 0.0; + ts.sumDP[i] = ts.ssqDP[i] = 0.0; + ts.sumGB[i] = ts.ssqGB[i] = 0.0; + ts.sumAlphaDB[i] = ts.ssqAlphaDB[i] = 0.0; + ts.sumBetaDB[i] = ts.ssqBetaDB[i] = 0.0; + ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; + ts.sumS0[i] = ts.ssqS0[i] = 0.0; + ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; + } + //locus loc; -demogrParams dem = pSpecies->getDemogr(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); + demogrParams dem = pSpecies->getDemogr(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); -int ninds = (int)inds.size(); + int ninds = (int)inds.size(); #if RSDEBUG -//DEBUGLOG << "Population::getTraits(): ninds = " << ts.ninds[0] -//// << " nalleles = "<< nalleles -//// << " nemiggenes = " << nemiggenes << " ntrfrgenes = " << ntrfrgenes -// << endl; + //DEBUGLOG << "Population::getTraits(): ninds = " << ts.ninds[0] + //// << " nalleles = "<< nalleles + //// << " nemiggenes = " << nemiggenes << " ntrfrgenes = " << ntrfrgenes + // << endl; #endif -for (int i = 0; i < ninds; i++) { - int sex = inds[i]->getSex(); - if (emig.sexDep || trfr.sexDep || sett.sexDep) g = sex; else g = 0; - ts.ninds[g] += 1; - // emigration traits - emigTraits e = inds[i]->getEmigTraits(); - if (emig.sexDep) g = sex; else g = 0; - ts.sumD0[g] += e.d0; ts.ssqD0[g] += e.d0 * e.d0; - ts.sumAlpha[g] += e.alpha; ts.ssqAlpha[g] += e.alpha * e.alpha; - ts.sumBeta[g] += e.beta; ts.ssqBeta[g] += e.beta * e.beta; - // transfer traits - trfrKernTraits k = inds[i]->getKernTraits(); - if (trfr.sexDep) g = sex; else g = 0; - ts.sumDist1[g] += k.meanDist1; ts.ssqDist1[g] += k.meanDist1 * k.meanDist1; - ts.sumDist2[g] += k.meanDist2; ts.ssqDist2[g] += k.meanDist2 * k.meanDist2; - ts.sumProp1[g] += k.probKern1; ts.ssqProp1[g] += k.probKern1 * k.probKern1; - trfrSMSTraits sms = inds[i]->getSMSTraits(); - g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ts.sumDP[g] += sms.dp; ts.ssqDP[g] += sms.dp * sms.dp; - ts.sumGB[g] += sms.gb; ts.ssqGB[g] += sms.gb * sms.gb; - ts.sumAlphaDB[g] += sms.alphaDB; ts.ssqAlphaDB[g] += sms.alphaDB * sms.alphaDB; - ts.sumBetaDB[g] += sms.betaDB; ts.ssqBetaDB[g] += sms.betaDB * sms.betaDB; -#if RSDEBUG -//DEBUGLOG << "Population::getTraits():" -// << " i=" << i << " g=" << g -// << " sms.dp= " << sms.dp << " sms.gb= " << sms.gb -// << " ts.sumDP[g]= " << ts.sumDP[g] << " ts.ssqDP[g]= " << ts.ssqDP[g] -// << " ts.sumGB[g]= " << ts.sumGB[g] << " ts.ssqGB[g]= " << ts.ssqGB[g] -// << endl; -#endif - trfrCRWTraits c = inds[i]->getCRWTraits(); - g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ts.sumStepL[g] += c.stepLength; ts.ssqStepL[g] += c.stepLength * c.stepLength; - ts.sumRho[g] += c.rho; ts.ssqRho[g] += c.rho * c.rho; - // settlement traits - settleTraits s = inds[i]->getSettTraits(); - if (sett.sexDep) g = sex; else g = 0; -// g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ts.sumS0[g] += s.s0; ts.ssqS0[g] += s.s0 * s.s0; - ts.sumAlphaS[g] += s.alpha; ts.ssqAlphaS[g] += s.alpha * s.alpha; - ts.sumBetaS[g] += s.beta; ts.ssqBetaS[g] += s.beta * s.beta; -#if RSDEBUG -//DEBUGLOG << "Population::getTraits():" -// << " i=" << i << " g=" << g << " a=" << a -// << " e.d0= " << e.d0 << " e.alpha= " << e.alpha << " e.beta= " << e.beta -// << " mnd0= " << emigTraits[g]->mnD0 << " mnAlpha= " << emigTraits[g]->mnAlpha << " mnBeta= " << emigTraits[g]->mnBeta -// << " sqd0= " << emigTraits[g]->sqD0 << " sqAlpha= " << emigTraits[g]->sqAlpha << " sqBeta= " << emigTraits[g]->sqBeta -// << endl; + for (int i = 0; i < ninds; i++) { + int sex = inds[i]->getSex(); + if (emig.sexDep || trfr.sexDep || sett.sexDep) g = sex; else g = 0; + ts.ninds[g] += 1; + // emigration traits + emigTraits e = inds[i]->getEmigTraits(); + if (emig.sexDep) g = sex; else g = 0; + ts.sumD0[g] += e.d0; ts.ssqD0[g] += e.d0 * e.d0; + ts.sumAlpha[g] += e.alpha; ts.ssqAlpha[g] += e.alpha * e.alpha; + ts.sumBeta[g] += e.beta; ts.ssqBeta[g] += e.beta * e.beta; + // transfer traits + trfrKernTraits k = inds[i]->getKernTraits(); + if (trfr.sexDep) g = sex; else g = 0; + ts.sumDist1[g] += k.meanDist1; ts.ssqDist1[g] += k.meanDist1 * k.meanDist1; + ts.sumDist2[g] += k.meanDist2; ts.ssqDist2[g] += k.meanDist2 * k.meanDist2; + ts.sumProp1[g] += k.probKern1; ts.ssqProp1[g] += k.probKern1 * k.probKern1; + trfrSMSTraits sms = inds[i]->getSMSTraits(); + g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT + ts.sumDP[g] += sms.dp; ts.ssqDP[g] += sms.dp * sms.dp; + ts.sumGB[g] += sms.gb; ts.ssqGB[g] += sms.gb * sms.gb; + ts.sumAlphaDB[g] += sms.alphaDB; ts.ssqAlphaDB[g] += sms.alphaDB * sms.alphaDB; + ts.sumBetaDB[g] += sms.betaDB; ts.ssqBetaDB[g] += sms.betaDB * sms.betaDB; +#if RSDEBUG + //DEBUGLOG << "Population::getTraits():" + // << " i=" << i << " g=" << g + // << " sms.dp= " << sms.dp << " sms.gb= " << sms.gb + // << " ts.sumDP[g]= " << ts.sumDP[g] << " ts.ssqDP[g]= " << ts.ssqDP[g] + // << " ts.sumGB[g]= " << ts.sumGB[g] << " ts.ssqGB[g]= " << ts.ssqGB[g] + // << endl; +#endif + trfrCRWTraits c = inds[i]->getCRWTraits(); + g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT + ts.sumStepL[g] += c.stepLength; ts.ssqStepL[g] += c.stepLength * c.stepLength; + ts.sumRho[g] += c.rho; ts.ssqRho[g] += c.rho * c.rho; + // settlement traits + settleTraits s = inds[i]->getSettTraits(); + if (sett.sexDep) g = sex; else g = 0; + // g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT + ts.sumS0[g] += s.s0; ts.ssqS0[g] += s.s0 * s.s0; + ts.sumAlphaS[g] += s.alpha; ts.ssqAlphaS[g] += s.alpha * s.alpha; + ts.sumBetaS[g] += s.beta; ts.ssqBetaS[g] += s.beta * s.beta; +#if RSDEBUG + //DEBUGLOG << "Population::getTraits():" + // << " i=" << i << " g=" << g << " a=" << a + // << " e.d0= " << e.d0 << " e.alpha= " << e.alpha << " e.beta= " << e.beta + // << " mnd0= " << emigTraits[g]->mnD0 << " mnAlpha= " << emigTraits[g]->mnAlpha << " mnBeta= " << emigTraits[g]->mnBeta + // << " sqd0= " << emigTraits[g]->sqD0 << " sqAlpha= " << emigTraits[g]->sqAlpha << " sqBeta= " << emigTraits[g]->sqBeta + // << endl; #endif -} + } -return ts; + return ts; } int Population::getNInds(void) { return (int)inds.size(); } -popStats Population::getStats(void) +popStats Population::getStats(void) { -popStats p; -int ninds; -float fec; -bool breeders[2]; breeders[0] = breeders[1] = false; -demogrParams dem = pSpecies->getDemogr(); -p.pSpecies = pSpecies; -p.pPatch = pPatch; -p.spNum = pSpecies->getSpNum(); -p.nInds = (int)inds.size(); -p.nNonJuvs = p.nAdults = 0; -p.breeding = false; -#if RSDEBUG -//DEBUGLOG << "Population::getStats(): this=" << this -//// << " p.pSpecies=" << p.pSpecies << " p.spNum=" << p.spNum -// << " p.pPatch=" << p.pPatch << " patchNum=" << p.pPatch->getPatchNum() -// << " nStages=" << nStages << " nSexes=" << nSexes << " p.nInds=" << p.nInds -// << endl; + popStats p; + int ninds; + float fec; + bool breeders[2]; breeders[0] = breeders[1] = false; + demogrParams dem = pSpecies->getDemogr(); + p.pSpecies = pSpecies; + p.pPatch = pPatch; + p.spNum = pSpecies->getSpNum(); + p.nInds = (int)inds.size(); + p.nNonJuvs = p.nAdults = 0; + p.breeding = false; +#if RSDEBUG + //DEBUGLOG << "Population::getStats(): this=" << this + //// << " p.pSpecies=" << p.pSpecies << " p.spNum=" << p.spNum + // << " p.pPatch=" << p.pPatch << " patchNum=" << p.pPatch->getPatchNum() + // << " nStages=" << nStages << " nSexes=" << nSexes << " p.nInds=" << p.nInds + // << endl; #endif -for (int stg = 1; stg < nStages; stg++) { - for (int sex = 0; sex < nSexes; sex++) { - ninds = nInds[stg][sex]; - p.nNonJuvs += ninds; -#if RSDEBUG -//DEBUGLOG << "Population::getStats(): this=" << this -// << " stg=" << stg << " sex=" << sex -// << " nInds[stg][sex]=" << nInds[stg][sex] << " p.nNonJuvs=" << p.nNonJuvs -// << endl; -#endif - if (ninds > 0) { - if (pSpecies->stageStructured()) { - if (dem.repType == 2) fec = pSpecies->getFec(stg,sex); - else fec = pSpecies->getFec(stg,0); - if (fec > 0.0) { breeders[sex] = true; p.nAdults += ninds; } + for (int stg = 1; stg < nStages; stg++) { + for (int sex = 0; sex < nSexes; sex++) { + ninds = nInds[stg][sex]; + p.nNonJuvs += ninds; +#if RSDEBUG + //DEBUGLOG << "Population::getStats(): this=" << this + // << " stg=" << stg << " sex=" << sex + // << " nInds[stg][sex]=" << nInds[stg][sex] << " p.nNonJuvs=" << p.nNonJuvs + // << endl; +#endif + if (ninds > 0) { + if (pSpecies->stageStructured()) { + if (dem.repType == 2) fec = pSpecies->getFec(stg, sex); + else fec = pSpecies->getFec(stg, 0); + if (fec > 0.0) { breeders[sex] = true; p.nAdults += ninds; } + } + else breeders[sex] = true; } - else breeders[sex] = true; } } -} -// is there a breeding population present? -if (nSexes == 1) { - p.breeding = breeders[0]; -} -else { - if (breeders[0] && breeders[1]) p.breeding = true; -} + // is there a breeding population present? + if (nSexes == 1) { + p.breeding = breeders[0]; + } + else { + if (breeders[0] && breeders[1]) p.breeding = true; + } #if RSDEBUG -//DEBUGLOG << "Population::getStats(): this=" << this -// << " p.nInds=" << p.nInds << " p.nAdults=" << p.nAdults << " p.nNonJuvs=" << p.nNonJuvs -// << " breeders[0]=" << breeders[0] << " breeders[1]=" << breeders[1] -// << " p.breeding=" << p.breeding -// << endl; + //DEBUGLOG << "Population::getStats(): this=" << this + // << " p.nInds=" << p.nInds << " p.nAdults=" << p.nAdults << " p.nNonJuvs=" << p.nNonJuvs + // << " breeders[0]=" << breeders[0] << " breeders[1]=" << breeders[1] + // << " p.breeding=" << p.breeding + // << endl; #endif -return p; + return p; } Species* Population::getSpecies(void) { return pSpecies; } int Population::totalPop(void) { -int t = 0; -for (int stg = 0; stg < nStages; stg++) { - for (int sex = 0; sex < nSexes; sex++) { - t += nInds[stg][sex]; + int t = 0; + for (int stg = 0; stg < nStages; stg++) { + for (int sex = 0; sex < nSexes; sex++) { + t += nInds[stg][sex]; #if RSDEBUG -//DEBUGLOG << "Population::totalPop(): this=" << this -// << " stg=" << stg << " sex=" << sex -// << " nInds[stg][sex]=" << nInds[stg][sex] << " t=" << t -// << endl; + //DEBUGLOG << "Population::totalPop(): this=" << this + // << " stg=" << stg << " sex=" << sex + // << " nInds[stg][sex]=" << nInds[stg][sex] << " t=" << t + // << endl; #endif + } } -} -return t; + return t; } int Population::stagePop(int stg) { -int t = 0; -if (stg < 0 || stg >= nStages) return t; -for (int sex = 0; sex < nSexes; sex++) { - t += nInds[stg][sex]; -} -return t; + int t = 0; + if (stg < 0 || stg >= nStages) return t; + for (int sex = 0; sex < nSexes; sex++) { + t += nInds[stg][sex]; + } + return t; } //--------------------------------------------------------------------------- // Remove all Individuals void Population::extirpate(void) { -int ninds = (int)inds.size(); -for (int i = 0; i < ninds; i++) { - if (inds[i] != NULL) delete inds[i]; -} -inds.clear(); -int njuvs = (int)juvs.size(); -for (int i = 0; i < njuvs; i++) { - if (juvs[i] != NULL) delete juvs[i]; -} -juvs.clear(); -for (int sex = 0; sex < nSexes; sex++) { - for (int stg = 0; stg < nStages; stg++) { - nInds[stg][sex] = 0; + int ninds = (int)inds.size(); + for (int i = 0; i < ninds; i++) { + if (inds[i] != NULL) delete inds[i]; + } + inds.clear(); + int njuvs = (int)juvs.size(); + for (int i = 0; i < njuvs; i++) { + if (juvs[i] != NULL) delete juvs[i]; + } + juvs.clear(); + for (int sex = 0; sex < nSexes; sex++) { + for (int stg = 0; stg < nStages; stg++) { + nInds[stg][sex] = 0; + } } -} } //--------------------------------------------------------------------------- // Produce juveniles and hold them in the juvs vector -void Population::reproduction(const float localK,const float envval,const int resol) +void Population::reproduction(const float localK, const float envval, const int resol) { -// get population size at start of reproduction -int ninds = (int)inds.size(); -#if RSDEBUG -//DEBUGLOG << "Population::reproduction(): this=" << this -//#if BUTTERFLYDISP -// << " option=" << option -//#endif // BUTTERFLYDISP -//#if RS_CONTAIN -// << " hab=" << hab -//#endif // RS_CONTAIN -// << " ninds=" << ninds -// << endl; + // get population size at start of reproduction + int ninds = (int)inds.size(); +#if RSDEBUG + //DEBUGLOG << "Population::reproduction(): this=" << this + //#if BUTTERFLYDISP + // << " option=" << option + //#endif // BUTTERFLYDISP + //#if RS_CONTAIN + // << " hab=" << hab + //#endif // RS_CONTAIN + // << " ninds=" << ninds + // << endl; #endif // RSDEBUG -if (ninds == 0) return; - -int nsexes,stage,sex,njuvs,nj,nmales,nfemales; -Cell *pCell; -indStats ind; -double expected; -bool skipbreeding; - -//envGradParams grad = paramsGrad->getGradient(); -envStochParams env = paramsStoch->getStoch(); -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -genomeData gen = pSpecies->getGenomeData(); -simView v = paramsSim->getViews(); - -if (dem.repType == 0) nsexes = 1; else nsexes = 2; - -#if RSDEBUG -//DEBUGLOG << "Population::reproduction(): this=" << this -//#if RS_CONTAIN -// << " hab=" << hab -//#else -// << " pSpecies=" << pSpecies -// << " localK=" << localK << " envval=" << envval << " resol=" << resol -//#endif // RS_CONTAIN -// << " sstruct.nStages=" << sstruct.nStages << " nsexes=" << nsexes << " ninds=" << ninds -// << endl; + if (ninds == 0) return; + + int nsexes, stage, sex, njuvs, nj, nmales, nfemales; + Cell* pCell; + indStats ind; + double expected; + bool skipbreeding; + + //envGradParams grad = paramsGrad->getGradient(); + envStochParams env = paramsStoch->getStoch(); + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + genomeData gen = pSpecies->getGenomeData(); + simView v = paramsSim->getViews(); + + if (dem.repType == 0) nsexes = 1; else nsexes = 2; + +#if RSDEBUG + //DEBUGLOG << "Population::reproduction(): this=" << this + //#if RS_CONTAIN + // << " hab=" << hab + //#else + // << " pSpecies=" << pSpecies + // << " localK=" << localK << " envval=" << envval << " resol=" << resol + //#endif // RS_CONTAIN + // << " sstruct.nStages=" << sstruct.nStages << " nsexes=" << nsexes << " ninds=" << ninds + // << endl; #endif // set up local copy of species fecundity table -float fec[NSTAGES][NSEXES]; -for (int stg = 0; stg < sstruct.nStages; stg++) { - for (int sex = 0; sex < nsexes; sex++) { - if (dem.stageStruct) { - if (dem.repType == 1) { // simple sexual model - // both sexes use fecundity recorded for females - fec[stg][sex] = pSpecies->getFec(stg,0); + float fec[NSTAGES][NSEXES]; + for (int stg = 0; stg < sstruct.nStages; stg++) { + for (int sex = 0; sex < nsexes; sex++) { + if (dem.stageStruct) { + if (dem.repType == 1) { // simple sexual model + // both sexes use fecundity recorded for females + fec[stg][sex] = pSpecies->getFec(stg, 0); + } + else + fec[stg][sex] = pSpecies->getFec(stg, sex); + // if (sex == 0 && fec[stg][sex] > dem.lambda) dem.lambda = fec[stg][sex]; + } + else { // non-structured population + if (stg == 1) fec[stg][sex] = dem.lambda; // adults + else fec[stg][sex] = 0.0; // juveniles } - else - fec[stg][sex] = pSpecies->getFec(stg,sex); -// if (sex == 0 && fec[stg][sex] > dem.lambda) dem.lambda = fec[stg][sex]; - } - else { // non-structured population - if (stg == 1) fec[stg][sex] = dem.lambda; // adults - else fec[stg][sex] = 0.0; // juveniles - } #if RSDEBUG -//if (ninds > 0) { -//DEBUGLOG << "Population::reproduction(): fec[" << stg << "][" << sex << "] = " << fec[stg][sex] -// << endl; -//} + //if (ninds > 0) { + //DEBUGLOG << "Population::reproduction(): fec[" << stg << "][" << sex << "] = " << fec[stg][sex] + // << endl; + //} #endif + } } -} -if (dem.stageStruct) { + if (dem.stageStruct) { #if RSDEBUG -//if (ninds > 0) { -// DEBUGLOG << "Population::reproduction(): ninds=" << ninds << " localK=" << localK -// << " effect of density dependence:" << endl; -//} + //if (ninds > 0) { + // DEBUGLOG << "Population::reproduction(): ninds=" << ninds << " localK=" << localK + // << " effect of density dependence:" << endl; + //} #endif // apply environmental effects and density dependence // to all non-zero female non-juvenile stages - for (int stg = 1; stg < nStages; stg++) { - if (fec[stg][0] > 0.0) { - // apply any effect of environmental gradient and/or stochasticty - fec[stg][0] *= envval; - if (env.stoch && !env.inK) { - // fecundity (at low density) is constrained to lie between limits specified - // for the species - float limit; - limit = pSpecies->getMinMax(0); - if (fec[stg][0] < limit) fec[stg][0] = limit; - limit = pSpecies->getMinMax(1); - if (fec[stg][0] > limit) fec[stg][0] = limit; - } - if (sstruct.fecDens) { // apply density dependence - float effect = 0.0; - if (sstruct.fecStageDens) { // stage-specific density dependence - // NOTE: matrix entries represent effect of ROW on COLUMN - // AND males precede females - float weight = 0.0; - for (int effstg = 0; effstg < nStages; effstg++) { - for (int effsex = 0; effsex < nSexes; effsex++) { - if (dem.repType == 2) { - if (effsex == 0) weight = pSpecies->getDDwtFec(2*stg+1,2*effstg+1); - else weight = pSpecies->getDDwtFec(2*stg+1,2*effstg); - } - else { - weight = pSpecies->getDDwtFec(stg,effstg); - } - effect += (float)nInds[effstg][effsex] * weight; + for (int stg = 1; stg < nStages; stg++) { + if (fec[stg][0] > 0.0) { + // apply any effect of environmental gradient and/or stochasticty + fec[stg][0] *= envval; + if (env.stoch && !env.inK) { + // fecundity (at low density) is constrained to lie between limits specified + // for the species + float limit; + limit = pSpecies->getMinMax(0); + if (fec[stg][0] < limit) fec[stg][0] = limit; + limit = pSpecies->getMinMax(1); + if (fec[stg][0] > limit) fec[stg][0] = limit; + } + if (sstruct.fecDens) { // apply density dependence + float effect = 0.0; + if (sstruct.fecStageDens) { // stage-specific density dependence + // NOTE: matrix entries represent effect of ROW on COLUMN + // AND males precede females + float weight = 0.0; + for (int effstg = 0; effstg < nStages; effstg++) { + for (int effsex = 0; effsex < nSexes; effsex++) { + if (dem.repType == 2) { + if (effsex == 0) weight = pSpecies->getDDwtFec(2 * stg + 1, 2 * effstg + 1); + else weight = pSpecies->getDDwtFec(2 * stg + 1, 2 * effstg); + } + else { + weight = pSpecies->getDDwtFec(stg, effstg); + } + effect += (float)nInds[effstg][effsex] * weight; #if RSDEBUG -//if (ninds > 0) { -// DEBUGLOG << " effstg=" << effstg << " effsex=" << effsex << " nInds=" << nInds[effstg][effsex]; -// DEBUGLOG << " weight=" << weight << " effect=" << effect -// << endl; -//} + //if (ninds > 0) { + // DEBUGLOG << " effstg=" << effstg << " effsex=" << effsex << " nInds=" << nInds[effstg][effsex]; + // DEBUGLOG << " weight=" << weight << " effect=" << effect + // << endl; + //} #endif + } } } - } - else // not stage-specific - effect = (float)totalPop(); - if (localK > 0.0) fec[stg][0] *= exp(-effect/localK); -#if RSDEBUG -//if (ninds > 0) { -// DEBUGLOG << " eff popn=" << effect << " exponential=" << exp(-effect/localK); -// DEBUGLOG << " fec[" << stg << "][0]=" << fec[stg][0] -// << endl; -//} + else // not stage-specific + effect = (float)totalPop(); + if (localK > 0.0) fec[stg][0] *= exp(-effect / localK); +#if RSDEBUG + //if (ninds > 0) { + // DEBUGLOG << " eff popn=" << effect << " exponential=" << exp(-effect/localK); + // DEBUGLOG << " fec[" << stg << "][0]=" << fec[stg][0] + // << endl; + //} #endif + } } } } -} -else { // non-structured - set fecundity for adult females only - // apply any effect of environmental gradient and/or stochasticty - fec[1][0] *= envval; - if (env.stoch && !env.inK) { - // fecundity (at low density) is constrained to lie between limits specified - // for the species - float limit; - limit = pSpecies->getMinMax(0); - if (fec[1][0] < limit) fec[1][0] = limit; - limit = pSpecies->getMinMax(1); - if (fec[1][0] > limit) fec[1][0] = limit; - } - // apply density dependence - if (localK > 0.0) { -//#if GOBYMODEL -// ddeffect[1] = (float)ninds/localK; -//#else - if (dem.repType == 1 || dem.repType == 2) { // sexual model - // apply factor of 2 (as in manual, eqn. 6) - fec[1][0] *= 2.0; + else { // non-structured - set fecundity for adult females only + // apply any effect of environmental gradient and/or stochasticty + fec[1][0] *= envval; + if (env.stoch && !env.inK) { + // fecundity (at low density) is constrained to lie between limits specified + // for the species + float limit; + limit = pSpecies->getMinMax(0); + if (fec[1][0] < limit) fec[1][0] = limit; + limit = pSpecies->getMinMax(1); + if (fec[1][0] > limit) fec[1][0] = limit; + } + // apply density dependence + if (localK > 0.0) { + //#if GOBYMODEL + // ddeffect[1] = (float)ninds/localK; + //#else + if (dem.repType == 1 || dem.repType == 2) { // sexual model + // apply factor of 2 (as in manual, eqn. 6) + fec[1][0] *= 2.0; + } + fec[1][0] /= (1.0f + fabs(dem.lambda - 1.0f) * pow(((float)ninds / localK), dem.bc)); + //#endif } - fec[1][0] /= (1.0f + fabs(dem.lambda-1.0f)*pow(((float)ninds/localK),dem.bc)); -//#endif - } #if RSDEBUG -//DEBUGLOG << "Population::reproduction(): dem.lambda=" << dem.lambda << " ninds=" << ninds -// << " localK=" << localK << " dem.bc=" << dem.bc << " fec[1][0]=" << fec[1][0] -// << endl; + //DEBUGLOG << "Population::reproduction(): dem.lambda=" << dem.lambda << " ninds=" << ninds + // << " localK=" << localK << " dem.bc=" << dem.bc << " fec[1][0]=" << fec[1][0] + // << endl; #endif -} + } -double propBreed; -Individual *father; -std::vector fathers; + double propBreed; + Individual* father; + std::vector fathers; -switch (dem.repType) { + switch (dem.repType) { -case 0: // asexual model - for (int i = 0; i < ninds; i++) { - stage = inds[i]->breedingFem(); + case 0: // asexual model + for (int i = 0; i < ninds; i++) { + stage = inds[i]->breedingFem(); #if RSDEBUG -//DEBUGLOG << "Population::reproduction():" -// << " i=" << i << " ID=" << inds[i]->getId() << " stage=" << stage -// << endl; + //DEBUGLOG << "Population::reproduction():" + // << " i=" << i << " ID=" << inds[i]->getId() << " stage=" << stage + // << endl; #endif - if (stage > 0) { // female of breeding age - if (dem.stageStruct) { - // determine whether she must miss current breeding attempt - ind = inds[i]->getStats(); - if (ind.fallow >= sstruct.repInterval) { - if (pRandom->Bernoulli(sstruct.probRep)) skipbreeding = false; - else skipbreeding = true; + if (stage > 0) { // female of breeding age + if (dem.stageStruct) { + // determine whether she must miss current breeding attempt + ind = inds[i]->getStats(); + if (ind.fallow >= sstruct.repInterval) { + if (pRandom->Bernoulli(sstruct.probRep)) skipbreeding = false; + else skipbreeding = true; + } + else skipbreeding = true; // cannot breed this time } - else skipbreeding = true; // cannot breed this time - } - else skipbreeding = false; // not structured - always breed - if (skipbreeding) { - inds[i]->incFallow(); - } - else { // attempt to breed - inds[i]->resetFallow(); - expected = fec[stage][0]; - if (expected <= 0.0) njuvs = 0; - else njuvs = pRandom->Poisson(expected); + else skipbreeding = false; // not structured - always breed + if (skipbreeding) { + inds[i]->incFallow(); + } + else { // attempt to breed + inds[i]->resetFallow(); + expected = fec[stage][0]; + if (expected <= 0.0) njuvs = 0; + else njuvs = pRandom->Poisson(expected); nj = (int)juvs.size(); pCell = pPatch->getRandomCell(); for (int j = 0; j < njuvs; j++) { #if RSDEBUG - // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... - juvs.push_back(new Individual(pCell,pPatch,0,0,0,0.0,true,trfr.moveType)); + // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... + juvs.push_back(new Individual(pCell, pPatch, 0, 0, 0, 0.0, true, trfr.moveType)); #else - juvs.push_back(new Individual(pCell,pPatch,0,0,0,0.0,trfr.moveModel,trfr.moveType)); + juvs.push_back(new Individual(pCell, pPatch, 0, 0, 0, 0.0, trfr.moveModel, trfr.moveType)); #endif nInds[0][0]++; if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) { - // juv inherits genome from parent (mother) - juvs[nj+j]->setGenes(pSpecies,inds[i],0,resol); + // juv inherits genome from parent (mother) + juvs[nj + j]->setGenes(pSpecies, inds[i], 0, resol); } } + } } } - } - break; + break; -case 1: // simple sexual model -case 2: // complex sexual model - // count breeding females and males - // add breeding males to list of potential fathers + case 1: // simple sexual model + case 2: // complex sexual model + // count breeding females and males + // add breeding males to list of potential fathers #if RSDEBUG //DEBUGLOG << "Population::reproduction(): case 1:" // << " fec[1][0]=" << fec[1][0] << " fec[1][1]=" << fec[1][1] // << endl; #endif - nfemales = nmales = 0; - for (int i = 0; i < ninds; i++) { - ind = inds[i]->getStats(); - if (ind.sex == 0 && fec[ind.stage][0] > 0.0) nfemales++; - if (ind.sex == 1 && fec[ind.stage][1] > 0.0) { - fathers.push_back(inds[i]); - nmales++; + nfemales = nmales = 0; + for (int i = 0; i < ninds; i++) { + ind = inds[i]->getStats(); + if (ind.sex == 0 && fec[ind.stage][0] > 0.0) nfemales++; + if (ind.sex == 1 && fec[ind.stage][1] > 0.0) { + fathers.push_back(inds[i]); + nmales++; #if RSDEBUG -//DEBUGLOG << "Population::reproduction(): i=" << i << " nmales=" << nmales -// << " inds[i]=" << inds[i] << endl; + //DEBUGLOG << "Population::reproduction(): i=" << i << " nmales=" << nmales + // << " inds[i]=" << inds[i] << endl; #endif + } } - } #if RSDEBUG -//DEBUGLOG << "Population::reproduction(): breeding nfemales=" << nfemales -// << " breeding nmales=" << nmales << endl; + //DEBUGLOG << "Population::reproduction(): breeding nfemales=" << nfemales + // << " breeding nmales=" << nmales << endl; #endif - if (nfemales > 0 && nmales > 0) - { // population can breed - if (dem.repType == 2) { // complex sexual model - // calculate proportion of eligible females which breed - propBreed = (2.0*dem.harem*nmales)/(nfemales+dem.harem*nmales); - if (propBreed > 1.0) propBreed = 1.0; + if (nfemales > 0 && nmales > 0) + { // population can breed + if (dem.repType == 2) { // complex sexual model + // calculate proportion of eligible females which breed + propBreed = (2.0 * dem.harem * nmales) / (nfemales + dem.harem * nmales); + if (propBreed > 1.0) propBreed = 1.0; #if RSDEBUG -//DEBUGLOG << "Population::reproduction(): harem=" << dem.harem -// << " nfemales=" << nfemales << " nmales=" << nmales << " propBreed=" << propBreed -// << endl; + //DEBUGLOG << "Population::reproduction(): harem=" << dem.harem + // << " nfemales=" << nfemales << " nmales=" << nmales << " propBreed=" << propBreed + // << endl; #endif - } - else propBreed = 1.0; - for (int i = 0; i < ninds; i++) { - stage = inds[i]->breedingFem(); - if (stage > 0 && fec[stage][0] > 0.0) { // (potential) breeding female - if (dem.stageStruct) { - // determine whether she must miss current breeding attempt - ind = inds[i]->getStats(); - if (ind.fallow >= sstruct.repInterval) { - if (pRandom->Bernoulli(sstruct.probRep)) skipbreeding = false; - else skipbreeding = true; + } + else propBreed = 1.0; + for (int i = 0; i < ninds; i++) { + stage = inds[i]->breedingFem(); + if (stage > 0 && fec[stage][0] > 0.0) { // (potential) breeding female + if (dem.stageStruct) { + // determine whether she must miss current breeding attempt + ind = inds[i]->getStats(); + if (ind.fallow >= sstruct.repInterval) { + if (pRandom->Bernoulli(sstruct.probRep)) skipbreeding = false; + else skipbreeding = true; + } + else skipbreeding = true; // cannot breed this time } - else skipbreeding = true; // cannot breed this time - } - else skipbreeding = false; // not structured - always breed - if (skipbreeding) { - inds[i]->incFallow(); - } - else { // attempt to breed - inds[i]->resetFallow(); - // NOTE: FOR COMPLEX SEXUAL MODEL, NO. OF FEMALES *ACTUALLY* BREEDING DOES NOT - // NECESSARILY EQUAL THE EXPECTED NO. FROM EQN. 7 IN THE MANUAL... - if (pRandom->Bernoulli(propBreed)) { - expected = fec[stage][0]; // breeds + else skipbreeding = false; // not structured - always breed + if (skipbreeding) { + inds[i]->incFallow(); + } + else { // attempt to breed + inds[i]->resetFallow(); + // NOTE: FOR COMPLEX SEXUAL MODEL, NO. OF FEMALES *ACTUALLY* BREEDING DOES NOT + // NECESSARILY EQUAL THE EXPECTED NO. FROM EQN. 7 IN THE MANUAL... + if (pRandom->Bernoulli(propBreed)) { + expected = fec[stage][0]; // breeds #if RSDEBUG -//DEBUGLOG << "Population::reproduction(): THIS LINE SHOULD NOT APPEAR FOR GOBY MODEL" -// << " expected=" << expected -// << endl; + //DEBUGLOG << "Population::reproduction(): THIS LINE SHOULD NOT APPEAR FOR GOBY MODEL" + // << " expected=" << expected + // << endl; #endif - } - else expected = 0.0; // fails to breed - if (expected <= 0.0) njuvs = 0; - else njuvs = pRandom->Poisson(expected); + } + else expected = 0.0; // fails to breed + if (expected <= 0.0) njuvs = 0; + else njuvs = pRandom->Poisson(expected); #if RSDEBUG -//DEBUGLOG << "Population::reproduction():" -// << " i " << i << " ID=" << inds[i]->getId() << " stage=" << stage -// << " expected=" << expected << " njuvs=" << njuvs << endl; + //DEBUGLOG << "Population::reproduction():" + // << " i " << i << " ID=" << inds[i]->getId() << " stage=" << stage + // << " expected=" << expected << " njuvs=" << njuvs << endl; #endif - if (njuvs > 0) - { - nj = (int)juvs.size(); + if (njuvs > 0) + { + nj = (int)juvs.size(); // select father at random from breeding males ... int rrr = 0; - if (nmales > 1) rrr = pRandom->IRandom(0,nmales-1); + if (nmales > 1) rrr = pRandom->IRandom(0, nmales - 1); father = fathers[rrr]; #if RSDEBUG -//DEBUGLOG << "Population::reproduction(): i = " << i << " rrr = " << rrr -// << " father = " << father << endl; + //DEBUGLOG << "Population::reproduction(): i = " << i << " rrr = " << rrr + // << " father = " << father << endl; #endif pCell = pPatch->getRandomCell(); for (int j = 0; j < njuvs; j++) { #if RSDEBUG // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... - juvs.push_back(new Individual(pCell,pPatch,0,0,0,dem.propMales,true,trfr.moveType)); + juvs.push_back(new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, true, trfr.moveType)); #else - juvs.push_back(new Individual(pCell,pPatch,0,0,0,dem.propMales,trfr.moveModel,trfr.moveType)); + juvs.push_back(new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.moveModel, trfr.moveType)); #endif - sex = juvs[nj+j]->getSex(); + sex = juvs[nj + j]->getSex(); nInds[0][sex]++; if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) { // juv inherits genome from parents - juvs[nj+j]->setGenes(pSpecies,inds[i],father,resol); + juvs[nj + j]->setGenes(pSpecies, inds[i], father, resol); } } + } } } } } - } - fathers.clear(); - break; + fathers.clear(); + break; -} // end of switch (dem.repType) + } // end of switch (dem.repType) #if RSDEBUG //DEBUGLOG << "Population::reproduction(): before reprodn. " << " inds.size() = " << inds.size() @@ -779,303 +779,303 @@ case 2: // complex sexual model void Population::fledge(void) { #if RSDEBUG -//DEBUGLOG << "Population::fledge(): this=" << this -// << " ninds=" << (int)inds.size() -// << " njuvs=" << (int)juvs.size() -// << endl; + //DEBUGLOG << "Population::fledge(): this=" << this + // << " ninds=" << (int)inds.size() + // << " njuvs=" << (int)juvs.size() + // << endl; #endif -demogrParams dem = pSpecies->getDemogr(); + demogrParams dem = pSpecies->getDemogr(); -if (dem.stageStruct) { // juveniles are added to the individuals vector - inds.insert(inds.end(),juvs.begin(),juvs.end()); -// nInds += nJuvs; nJuvs = 0; -} -else { // all adults die and juveniles replace adults - int ninds = (int)inds.size(); - for (int i = 0; i < ninds; i++) { - delete inds[i]; + if (dem.stageStruct) { // juveniles are added to the individuals vector + inds.insert(inds.end(), juvs.begin(), juvs.end()); + // nInds += nJuvs; nJuvs = 0; } - inds.clear(); - for (int sex = 0; sex < nSexes; sex++) { - nInds[1][sex] = 0; // set count of adults to zero + else { // all adults die and juveniles replace adults + int ninds = (int)inds.size(); + for (int i = 0; i < ninds; i++) { + delete inds[i]; + } + inds.clear(); + for (int sex = 0; sex < nSexes; sex++) { + nInds[1][sex] = 0; // set count of adults to zero + } + inds = juvs; } - inds = juvs; -} -juvs.clear(); + juvs.clear(); } // Determine which individuals will disperse void Population::emigration(float localK) { -int nsexes; -double disp,Pdisp,NK; -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -emigRules emig = pSpecies->getEmig(); -emigTraits eparams; -trfrRules trfr = pSpecies->getTrfr(); -indStats ind; -#if RSDEBUG -//DEBUGLOG << "Population::emigration(): this=" << this -// << " nStages=" << sstruct.nStages -//// << " emig.emigGenes[0]=" << emig.emigGenes[0] -//// << " emig.emigGenes[1]=" << emig.emigGenes[1] -// << endl; + int nsexes; + double disp, Pdisp, NK; + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + emigRules emig = pSpecies->getEmig(); + emigTraits eparams; + trfrRules trfr = pSpecies->getTrfr(); + indStats ind; +#if RSDEBUG + //DEBUGLOG << "Population::emigration(): this=" << this + // << " nStages=" << sstruct.nStages + //// << " emig.emigGenes[0]=" << emig.emigGenes[0] + //// << " emig.emigGenes[1]=" << emig.emigGenes[1] + // << endl; #endif // to avoid division by zero, assume carrying capacity is at least one individual // localK can be zero if there is a moving gradient or stochasticity in K -if (localK < 1.0) localK = 1.0; -NK = (float)totalPop() / localK; + if (localK < 1.0) localK = 1.0; + NK = (float)totalPop() / localK; -int ninds = (int)inds.size(); + int ninds = (int)inds.size(); -// set up local copy of emigration probability table -// used when there is no individual variability -// NB - IT IS DOUBTFUL THIS CONTRIBUTES ANY SUBSTANTIAL TIME SAVING -if (dem.repType == 0) nsexes = 1; else nsexes = 2; -double Pemig[NSTAGES][NSEXES]; + // set up local copy of emigration probability table + // used when there is no individual variability + // NB - IT IS DOUBTFUL THIS CONTRIBUTES ANY SUBSTANTIAL TIME SAVING + if (dem.repType == 0) nsexes = 1; else nsexes = 2; + double Pemig[NSTAGES][NSEXES]; -for (int stg = 0; stg < sstruct.nStages; stg++) { - for (int sex = 0; sex < nsexes; sex++) { - if (emig.indVar) Pemig[stg][sex] = 0.0; - else { - if (emig.densDep) { - if (emig.sexDep) { - if (emig.stgDep) { - eparams = pSpecies->getEmigTraits(stg,sex); - } - else { - eparams = pSpecies->getEmigTraits(0,sex); - } - } - else { // !emig.sexDep - if (emig.stgDep) { - eparams = pSpecies->getEmigTraits(stg,0); + for (int stg = 0; stg < sstruct.nStages; stg++) { + for (int sex = 0; sex < nsexes; sex++) { + if (emig.indVar) Pemig[stg][sex] = 0.0; + else { + if (emig.densDep) { + if (emig.sexDep) { + if (emig.stgDep) { + eparams = pSpecies->getEmigTraits(stg, sex); + } + else { + eparams = pSpecies->getEmigTraits(0, sex); + } } - else { - eparams = pSpecies->getEmigTraits(0,0); + else { // !emig.sexDep + if (emig.stgDep) { + eparams = pSpecies->getEmigTraits(stg, 0); + } + else { + eparams = pSpecies->getEmigTraits(0, 0); + } } - } - Pemig[stg][sex] = eparams.d0/(1.0+exp(-(NK - eparams.beta)*eparams.alpha)); -#if RSDEBUG -//if (ppLand.patch_model) { -// DEBUGLOG << "Population::emigration(): stg=" << stg << " sex=" << sex -// << " totalPop=" << totalPop() << " localK=" << localK << " NK=" << NK -// << " d0=" << eparams.d0 << " beta=" << eparams.beta << " alpha=" << eparams.alpha -// << " Pemig[stg][sex]=" << Pemig[stg][sex] -// << endl; -//} + Pemig[stg][sex] = eparams.d0 / (1.0 + exp(-(NK - eparams.beta) * eparams.alpha)); +#if RSDEBUG + //if (ppLand.patch_model) { + // DEBUGLOG << "Population::emigration(): stg=" << stg << " sex=" << sex + // << " totalPop=" << totalPop() << " localK=" << localK << " NK=" << NK + // << " d0=" << eparams.d0 << " beta=" << eparams.beta << " alpha=" << eparams.alpha + // << " Pemig[stg][sex]=" << Pemig[stg][sex] + // << endl; + //} #endif - } - else { // density-independent - if (emig.sexDep) { - if (emig.stgDep) { - Pemig[stg][sex] = pSpecies->getEmigD0(stg,sex); - } - else { // !emig.stgDep - Pemig[stg][sex] = pSpecies->getEmigD0(0,sex); - } } - else { // !emig.sexDep - if (emig.stgDep) { - Pemig[stg][sex] = pSpecies->getEmigD0(stg,0); + else { // density-independent + if (emig.sexDep) { + if (emig.stgDep) { + Pemig[stg][sex] = pSpecies->getEmigD0(stg, sex); + } + else { // !emig.stgDep + Pemig[stg][sex] = pSpecies->getEmigD0(0, sex); + } } - else { // !emig.stgDep - Pemig[stg][sex] = pSpecies->getEmigD0(0,0); + else { // !emig.sexDep + if (emig.stgDep) { + Pemig[stg][sex] = pSpecies->getEmigD0(stg, 0); + } + else { // !emig.stgDep + Pemig[stg][sex] = pSpecies->getEmigD0(0, 0); + } } } - } - } // end of !emig.indVar + } // end of !emig.indVar #if RSDEBUG //DEBUGLOG << "Population::emigration(): this=" << (int)this // << " totalPop()=" << totalPop() // << " Pemig[" << stg << "][" << sex << "]="<< Pemig[stg][sex] << endl; #endif + } } -} -//#if GROUPDISP -//bool newgroup = true; -//int currentsize = 0; -//#endif // GROUPDISP - -//#if PARTMIGRN -//double cumprop[7]; -//cumprop[0] = 0.0; -//for (int i = 1; i < 7; i++) { -// cumprop[i] = cumprop[i-1] + pSpecies->getPropDispMigrn(i); -//#if RSDEBUG -//DEBUGLOG << "Population::emigration(): i=" << i -// << " cumprop[i]=" << cumprop[i] -// << endl; -//#endif -//} -//#endif // PARTMIGRN -// - -for (int i = 0; i < ninds; i++) { - ind = inds[i]->getStats(); - if (ind.status < 1) - { - if (emig.indVar) { // individual variability in emigration - if (dem.stageStruct && ind.stage != emig.emigStage) { - // emigration may not occur - Pdisp = 0.0; - } - else { // non-structured or individual is in emigration stage - eparams = inds[i]->getEmigTraits(); - if (emig.densDep) { // density-dependent - NK = (float)totalPop() / localK; - Pdisp = eparams.d0/(1.0+exp(-(NK - eparams.beta)*eparams.alpha)); + //#if GROUPDISP + //bool newgroup = true; + //int currentsize = 0; + //#endif // GROUPDISP + + //#if PARTMIGRN + //double cumprop[7]; + //cumprop[0] = 0.0; + //for (int i = 1; i < 7; i++) { + // cumprop[i] = cumprop[i-1] + pSpecies->getPropDispMigrn(i); + //#if RSDEBUG + //DEBUGLOG << "Population::emigration(): i=" << i + // << " cumprop[i]=" << cumprop[i] + // << endl; + //#endif + //} + //#endif // PARTMIGRN + // + + for (int i = 0; i < ninds; i++) { + ind = inds[i]->getStats(); + if (ind.status < 1) + { + if (emig.indVar) { // individual variability in emigration + if (dem.stageStruct && ind.stage != emig.emigStage) { + // emigration may not occur + Pdisp = 0.0; } - else { // density-independent - if (emig.sexDep) { - Pdisp = Pemig[0][ind.sex] + eparams.d0; + else { // non-structured or individual is in emigration stage + eparams = inds[i]->getEmigTraits(); + if (emig.densDep) { // density-dependent + NK = (float)totalPop() / localK; + Pdisp = eparams.d0 / (1.0 + exp(-(NK - eparams.beta) * eparams.alpha)); } - else { - Pdisp = Pemig[0][0] + eparams.d0; + else { // density-independent + if (emig.sexDep) { + Pdisp = Pemig[0][ind.sex] + eparams.d0; + } + else { + Pdisp = Pemig[0][0] + eparams.d0; + } } } - } - } // end of individual variability - else { // no individual variability + } // end of individual variability + else { // no individual variability - if (emig.densDep) { - if (emig.sexDep) { - if (emig.stgDep) { - Pdisp = Pemig[ind.stage][ind.sex]; - } - else { - Pdisp = Pemig[0][ind.sex]; - } - } - else { // !emig.sexDep - if (emig.stgDep) { - Pdisp = Pemig[ind.stage][0]; + if (emig.densDep) { + if (emig.sexDep) { + if (emig.stgDep) { + Pdisp = Pemig[ind.stage][ind.sex]; + } + else { + Pdisp = Pemig[0][ind.sex]; + } } - else { - Pdisp = Pemig[0][0]; + else { // !emig.sexDep + if (emig.stgDep) { + Pdisp = Pemig[ind.stage][0]; + } + else { + Pdisp = Pemig[0][0]; + } } - } #if RSDEBUG -//if (ppLand.patch_model) { -// DEBUGLOG << "Population::emigration(): i=" << i << " sex=" << ind.sex << " stage=" << ind.stage -// << " totalPop=" << totalPop() << " localK=" << localK << " NK=" << NK -// << " Pdisp=" << Pdisp -// << endl; -//} + //if (ppLand.patch_model) { + // DEBUGLOG << "Population::emigration(): i=" << i << " sex=" << ind.sex << " stage=" << ind.stage + // << " totalPop=" << totalPop() << " localK=" << localK << " NK=" << NK + // << " Pdisp=" << Pdisp + // << endl; + //} #endif - } - else { // density-independent - if (emig.sexDep) { - if (emig.stgDep) { - Pdisp = Pemig[ind.stage][ind.sex]; - } - else { // !emig.stgDep - Pdisp = Pemig[0][ind.sex]; - } } - else { // !emig.sexDep - if (emig.stgDep) { - Pdisp = Pemig[ind.stage][0]; + else { // density-independent + if (emig.sexDep) { + if (emig.stgDep) { + Pdisp = Pemig[ind.stage][ind.sex]; + } + else { // !emig.stgDep + Pdisp = Pemig[0][ind.sex]; + } } - else { // !emig.stgDep - Pdisp = Pemig[0][0]; + else { // !emig.sexDep + if (emig.stgDep) { + Pdisp = Pemig[ind.stage][0]; + } + else { // !emig.stgDep + Pdisp = Pemig[0][0]; + } } + //#if GROUPDISP + // if (emig.groupdisp) { + // if (Pdisp > 0) { + // + // } + // + // } + //#endif // GROUPDISP } -//#if GROUPDISP -// if (emig.groupdisp) { -// if (Pdisp > 0) { -// -// } -// -// } -//#endif // GROUPDISP - } - - } // end of no individual variability - disp = pRandom->Bernoulli(Pdisp); + } // end of no individual variability + + disp = pRandom->Bernoulli(Pdisp); #if RSDEBUG -//DEBUGLOG << "Population::emigration(): i=" << i << " sex=" << ind.sex << " stage=" << ind.stage -// << " Pdisp=" << Pdisp << " disp=" << disp << endl; + //DEBUGLOG << "Population::emigration(): i=" << i << " sex=" << ind.sex << " stage=" << ind.stage + // << " Pdisp=" << Pdisp << " disp=" << disp << endl; #endif - if (disp == 1) { // emigrant - inds[i]->setStatus(1); - } - } // end of if (ind.status < 1) condition -} // end of for loop + if (disp == 1) { // emigrant + inds[i]->setStatus(1); + } + } // end of if (ind.status < 1) condition + } // end of for loop } // All individuals emigrate after patch destruction void Population::allEmigrate(void) { -int ninds = (int)inds.size(); -for (int i = 0; i < ninds; i++) { - inds[i]->setStatus(1); -} + int ninds = (int)inds.size(); + for (int i = 0; i < ninds; i++) { + inds[i]->setStatus(1); + } } // If an Individual has been identified as an emigrant, remove it from the Population disperser Population::extractDisperser(int ix) { -disperser d; -indStats ind = inds[ix]->getStats(); -#if RSDEBUG -//if (ind.status > 0) { -// DEBUGLOG << "Population::extractDisperser(): ix = " << ix << " inds[ix] = " << inds[ix] -// << " indId = " << inds[ix]->getId() << " ind.status = " << ind.status -// << endl; -//} -#endif -if (ind.status == 1) { // emigrant - d.pInd = inds[ix]; d.yes = true; - inds[ix] = 0; - nInds[ind.stage][ind.sex]--; -} -else { - d.pInd = NULL; d.yes = false; -} -return d; + disperser d; + indStats ind = inds[ix]->getStats(); +#if RSDEBUG + //if (ind.status > 0) { + // DEBUGLOG << "Population::extractDisperser(): ix = " << ix << " inds[ix] = " << inds[ix] + // << " indId = " << inds[ix]->getId() << " ind.status = " << ind.status + // << endl; + //} +#endif + if (ind.status == 1) { // emigrant + d.pInd = inds[ix]; d.yes = true; + inds[ix] = 0; + nInds[ind.stage][ind.sex]--; + } + else { + d.pInd = NULL; d.yes = false; + } + return d; } // For an individual identified as being in the matrix population: // if it is a settler, return its new location and remove it from the current population // otherwise, leave it in the matrix population for possible reporting before deletion disperser Population::extractSettler(int ix) { -disperser d; -Cell* pCell; -//Patch* pPatch; + disperser d; + Cell* pCell; + //Patch* pPatch; -indStats ind = inds[ix]->getStats(); + indStats ind = inds[ix]->getStats(); -pCell = inds[ix]->getLocn(1); + pCell = inds[ix]->getLocn(1); #if RSDEBUG -//DEBUGLOG << "Population::extractSettler(): ix = " << ix << " inds[ix] = " << inds[ix] -// << " indId = " << inds[ix]->getId() << " ind.status = " << ind.status << endl; + //DEBUGLOG << "Population::extractSettler(): ix = " << ix << " inds[ix] = " << inds[ix] + // << " indId = " << inds[ix]->getId() << " ind.status = " << ind.status << endl; #endif -d.pInd = inds[ix]; d.pCell = pCell; d.yes = false; -if (ind.status == 4 || ind.status == 5) { // settled - d.yes = true; - inds[ix] = 0; - nInds[ind.stage][ind.sex]--; -} -return d; + d.pInd = inds[ix]; d.pCell = pCell; d.yes = false; + if (ind.status == 4 || ind.status == 5) { // settled + d.yes = true; + inds[ix] = 0; + nInds[ind.stage][ind.sex]--; + } + return d; } // Add a specified individual to the new/current dispersal group // Add a specified individual to the population -void Population::recruit(Individual *pInd) { -inds.push_back(pInd); -indStats ind = pInd->getStats(); -nInds[ind.stage][ind.sex]++; -#if RSDEBUG -//DEBUGLOG << "Population::recruit(): patchNum=" << pPatch->getPatchNum() -// << " indId=" << pInd->getId() -// << " nInds[" << ind.stage << "][" << ind.sex << "]=" << nInds[ind.stage][ind.sex] -// << endl; +void Population::recruit(Individual* pInd) { + inds.push_back(pInd); + indStats ind = pInd->getStats(); + nInds[ind.stage][ind.sex]++; +#if RSDEBUG + //DEBUGLOG << "Population::recruit(): patchNum=" << pPatch->getPatchNum() + // << " indId=" << pInd->getId() + // << " nInds[" << ind.stage << "][" << ind.sex << "]=" << nInds[ind.stage][ind.sex] + // << endl; #endif } @@ -1083,306 +1083,307 @@ nInds[ind.stage][ind.sex]++; // Transfer is run for populations in the matrix only #if RS_RCPP // included also SEASONAL -int Population::transfer(Landscape *pLandscape,short landIx,short nextseason) +int Population::transfer(Landscape* pLandscape, short landIx, short nextseason) #else -int Population::transfer(Landscape *pLandscape,short landIx) +int Population::transfer(Landscape* pLandscape, short landIx) #endif { -int ndispersers = 0; -int disperser; -short othersex; -bool mateOK,densdepOK; -intptr patch,popn; -int patchnum; -double localK,popsize,settprob; -Patch *pPatch = 0; -Cell *pCell = 0; -indStats ind; -Population *pNewPopn = 0; -locn newloc,nbrloc; - -landData ppLand = pLandscape->getLandData(); -short reptype = pSpecies->getRepType(); -trfrRules trfr = pSpecies->getTrfr(); -settleType settletype = pSpecies->getSettle(); -settleRules sett; -settleTraits settDD; -settlePatch settle; -simParams sim = paramsSim->getSim(); - -// each individual takes one step -// for dispersal by kernel, this should be the only step taken -int ninds = (int)inds.size(); -#if RSDEBUG -//DEBUGLOG << "Population::transfer(): 0000: ninds = " << ninds -// << " ndispersers = " << ndispersers << endl; -#endif -for (int i = 0; i < ninds; i++) { -#if RSDEBUG -//DEBUGLOG << "Population::transfer(): 1111: i = " << i << " ID = " << inds[i]->getId() -// << endl; + int ndispersers = 0; + int disperser; + short othersex; + bool mateOK, densdepOK; + intptr patch, popn; + int patchnum; + double localK, popsize, settprob; + Patch* pPatch = 0; + Cell* pCell = 0; + indStats ind; + Population* pNewPopn = 0; + locn newloc, nbrloc; + + landData ppLand = pLandscape->getLandData(); + short reptype = pSpecies->getRepType(); + trfrRules trfr = pSpecies->getTrfr(); + settleType settletype = pSpecies->getSettle(); + settleRules sett; + settleTraits settDD; + settlePatch settle; + simParams sim = paramsSim->getSim(); + + // each individual takes one step + // for dispersal by kernel, this should be the only step taken + int ninds = (int)inds.size(); +#if RSDEBUG + //DEBUGLOG << "Population::transfer(): 0000: ninds = " << ninds + // << " ndispersers = " << ndispersers << endl; #endif - if (trfr.moveModel) { + for (int i = 0; i < ninds; i++) { #if RSDEBUG -//pCell = inds[i]->getLocn(1); -//locn loc = pCell->getLocn(); -//DEBUGLOG << "Population::transfer(): 1112: i = " << i << " ID = " << inds[i]->getId() -// << " before:" << " x = " << loc.x << " y = " << loc.y -// << endl; + //DEBUGLOG << "Population::transfer(): 1111: i = " << i << " ID = " << inds[i]->getId() + // << endl; +#endif + if (trfr.moveModel) { +#if RSDEBUG + //pCell = inds[i]->getLocn(1); + //locn loc = pCell->getLocn(); + //DEBUGLOG << "Population::transfer(): 1112: i = " << i << " ID = " << inds[i]->getId() + // << " before:" << " x = " << loc.x << " y = " << loc.y + // << endl; #endif - disperser = inds[i]->moveStep(pLandscape,pSpecies,landIx,sim.absorbing); + disperser = inds[i]->moveStep(pLandscape, pSpecies, landIx, sim.absorbing); #if RSDEBUG -//pCell = inds[i]->getLocn(1); -//newloc = pCell->getLocn(); -//DEBUGLOG << "Population::transfer(): 1113: i = " << i << " ID = " << inds[i]->getId() -// << " after: " << " x = " << newloc.x << " y = " << newloc.y -// << endl; + //pCell = inds[i]->getLocn(1); + //newloc = pCell->getLocn(); + //DEBUGLOG << "Population::transfer(): 1113: i = " << i << " ID = " << inds[i]->getId() + // << " after: " << " x = " << newloc.x << " y = " << newloc.y + // << endl; #endif - } - else { - disperser = inds[i]->moveKernel(pLandscape,pSpecies,reptype,sim.absorbing); - } - ndispersers += disperser; - if (disperser) { - if (reptype > 0) - { // sexual species - record as potential settler in new patch - if (inds[i]->getStatus() == 2) - { // disperser has found a patch - pCell = inds[i]->getLocn(1); - patch = pCell->getPatch(); - if (patch != 0) { // not no-data area - pPatch = (Patch*)patch; - pPatch->incrPossSettler(pSpecies,inds[i]->getSex()); + } + else { + disperser = inds[i]->moveKernel(pLandscape, pSpecies, reptype, sim.absorbing); + } + ndispersers += disperser; + if (disperser) { + if (reptype > 0) + { // sexual species - record as potential settler in new patch + if (inds[i]->getStatus() == 2) + { // disperser has found a patch + pCell = inds[i]->getLocn(1); + patch = pCell->getPatch(); + if (patch != 0) { // not no-data area + pPatch = (Patch*)patch; + pPatch->incrPossSettler(pSpecies, inds[i]->getSex()); + } } } } } -} #if RSDEBUG -//DEBUGLOG << "Population::transfer(): 5555: ninds=" << ninds -// << " ndispersers=" << ndispersers << endl; + //DEBUGLOG << "Population::transfer(): 5555: ninds=" << ninds + // << " ndispersers=" << ndispersers << endl; #endif // each individual which has reached a potential patch decides whether to settle -for (int i = 0; i < ninds; i++) { - ind = inds[i]->getStats(); - if (ind.sex == 0) othersex = 1; else othersex = 0; - if (settletype.stgDep) { - if (settletype.sexDep) sett = pSpecies->getSettRules(ind.stage,ind.sex); - else sett = pSpecies->getSettRules(ind.stage,0); - } - else { - if (settletype.sexDep) sett = pSpecies->getSettRules(0,ind.sex); - else sett = pSpecies->getSettRules(0,0); - } - if (ind.status == 2) - { // awaiting settlement - pCell = inds[i]->getLocn(1); - if (pCell == 0) { - // this condition can occur in a patch-based model at the time of a dynamic landscape - // change when there is a range restriction in place, since a patch can straddle the - // range restriction and an individual forced to disperse upon patch removal could - // start its trajectory beyond the boundary of the restrictyed range - such a model is - // not good practice, but the condition must be handled by killing the individual conceerned - ind.status = 6; + for (int i = 0; i < ninds; i++) { + ind = inds[i]->getStats(); + if (ind.sex == 0) othersex = 1; else othersex = 0; + if (settletype.stgDep) { + if (settletype.sexDep) sett = pSpecies->getSettRules(ind.stage, ind.sex); + else sett = pSpecies->getSettRules(ind.stage, 0); } else { + if (settletype.sexDep) sett = pSpecies->getSettRules(0, ind.sex); + else sett = pSpecies->getSettRules(0, 0); + } + if (ind.status == 2) + { // awaiting settlement + pCell = inds[i]->getLocn(1); + if (pCell == 0) { + // this condition can occur in a patch-based model at the time of a dynamic landscape + // change when there is a range restriction in place, since a patch can straddle the + // range restriction and an individual forced to disperse upon patch removal could + // start its trajectory beyond the boundary of the restrictyed range - such a model is + // not good practice, but the condition must be handled by killing the individual conceerned + ind.status = 6; + } + else { #if RSDEBUG -//newloc = pCell->getLocn(); -//DEBUGLOG << "Population::transfer(): 6666: i=" << i << " ID=" << inds[i]->getId() -// << " sex=" << ind.sex << " status=" << ind.status -// << " pCell=" << pCell << " x=" << newloc.x << " y=" << newloc.y -// << " findMate=" << sett.findMate -//// << " wait=" << sett.wait -//// << " go2nbrLocn=" << sett.go2nbrLocn -// << endl; + //newloc = pCell->getLocn(); + //DEBUGLOG << "Population::transfer(): 6666: i=" << i << " ID=" << inds[i]->getId() + // << " sex=" << ind.sex << " status=" << ind.status + // << " pCell=" << pCell << " x=" << newloc.x << " y=" << newloc.y + // << " findMate=" << sett.findMate + //// << " wait=" << sett.wait + //// << " go2nbrLocn=" << sett.go2nbrLocn + // << endl; #endif - mateOK = false; - if (sett.findMate) { - // determine whether at least one individual of the opposite sex is present in the - // new population - if (matePresent(pCell,othersex)) mateOK = true; + mateOK = false; + if (sett.findMate) { + // determine whether at least one individual of the opposite sex is present in the + // new population + if (matePresent(pCell, othersex)) mateOK = true; #if RSDEBUG -//DEBUGLOG << "Population::transfer(): 7777: othersex=" << othersex -// << " this=" << this << " pNewPopn=" << pNewPopn << " popsize=" << popsize << " mateOK=" << mateOK -// << endl; + //DEBUGLOG << "Population::transfer(): 7777: othersex=" << othersex + // << " this=" << this << " pNewPopn=" << pNewPopn << " popsize=" << popsize << " mateOK=" << mateOK + // << endl; #endif - } - else { // no requirement to find a mate - mateOK = true; - } + } + else { // no requirement to find a mate + mateOK = true; + } - densdepOK = false; - settle = inds[i]->getSettPatch(); - if (sett.densDep) - { - patch = pCell->getPatch(); + densdepOK = false; + settle = inds[i]->getSettPatch(); + if (sett.densDep) + { + patch = pCell->getPatch(); #if RSDEBUG -//DEBUGLOG << "Population::transfer(): 8880: i=" << i << " patch=" << patch -// << endl; + //DEBUGLOG << "Population::transfer(): 8880: i=" << i << " patch=" << patch + // << endl; #endif - if (patch != 0) { // not no-data area - pPatch = (Patch*)patch; - if (settle.settleStatus == 0 - || settle.pSettPatch != pPatch) - // note: second condition allows for having moved from one patch to another - // adjacent one - { -// inds[i]->resetPathOut(); // reset steps out of patch to zero - // determine whether settlement occurs in the (new) patch - localK = (double)pPatch->getK(); - popn = pPatch->getPopn((intptr)pSpecies); + if (patch != 0) { // not no-data area + pPatch = (Patch*)patch; + if (settle.settleStatus == 0 + || settle.pSettPatch != pPatch) + // note: second condition allows for having moved from one patch to another + // adjacent one + { + // inds[i]->resetPathOut(); // reset steps out of patch to zero + // determine whether settlement occurs in the (new) patch + localK = (double)pPatch->getK(); + popn = pPatch->getPopn((intptr)pSpecies); #if RSDEBUG -//DEBUGLOG << "Population::transfer(): 8881: i=" << i << " patchNum=" << pPatch->getPatchNum() -// << " localK=" << localK << " popn=" << popn << endl; + //DEBUGLOG << "Population::transfer(): 8881: i=" << i << " patchNum=" << pPatch->getPatchNum() + // << " localK=" << localK << " popn=" << popn << endl; #endif - if (popn == 0) { // population has not been set up in the new patch - popsize = 0.0; - } - else { - pNewPopn = (Population*)popn; - popsize = (double)pNewPopn->totalPop(); - } - if (localK > 0.0) { - // make settlement decision - if (settletype.indVar) settDD = inds[i]->getSettTraits(); + if (popn == 0) { // population has not been set up in the new patch + popsize = 0.0; + } + else { + pNewPopn = (Population*)popn; + popsize = (double)pNewPopn->totalPop(); + } + if (localK > 0.0) { + // make settlement decision + if (settletype.indVar) settDD = inds[i]->getSettTraits(); #if RS_RCPP - else settDD = pSpecies->getSettTraits(ind.stage,ind.sex); + else settDD = pSpecies->getSettTraits(ind.stage, ind.sex); #else - else { - if (settletype.sexDep) { - if (settletype.stgDep) - settDD = pSpecies->getSettTraits(ind.stage,ind.sex); - else - settDD = pSpecies->getSettTraits(0,ind.sex); - } else { - if (settletype.stgDep) - settDD = pSpecies->getSettTraits(ind.stage,0); - else - settDD = pSpecies->getSettTraits(0,0); + if (settletype.sexDep) { + if (settletype.stgDep) + settDD = pSpecies->getSettTraits(ind.stage, ind.sex); + else + settDD = pSpecies->getSettTraits(0, ind.sex); + } + else { + if (settletype.stgDep) + settDD = pSpecies->getSettTraits(ind.stage, 0); + else + settDD = pSpecies->getSettTraits(0, 0); + } } - } #endif //RS_RCPP - settprob = settDD.s0 / - (1.0 + exp(-(popsize/localK - (double)settDD.beta) * (double)settDD.alpha)); + settprob = settDD.s0 / + (1.0 + exp(-(popsize / localK - (double)settDD.beta) * (double)settDD.alpha)); +#if RSDEBUG + //DEBUGLOG << "Population::transfer(): 8888: i=" << i << " ind.stage=" << ind.stage + // << " this=" << this << " pNewPopn=" << pNewPopn << " popsize=" << popsize + // << " localK=" << localK << " alpha=" << settDD.alpha << " beta=" << settDD.beta + // << " settprob=" << settprob + // << endl; +#endif + if (pRandom->Bernoulli(settprob)) { // settlement allowed + densdepOK = true; + settle.settleStatus = 2; + } + else { // settlement procluded + settle.settleStatus = 1; + } #if RSDEBUG -//DEBUGLOG << "Population::transfer(): 8888: i=" << i << " ind.stage=" << ind.stage -// << " this=" << this << " pNewPopn=" << pNewPopn << " popsize=" << popsize -// << " localK=" << localK << " alpha=" << settDD.alpha << " beta=" << settDD.beta -// << " settprob=" << settprob -// << endl; + //DEBUGLOG << "Population::transfer(): 8889: i=" << i + // << " settleStatus=" << settle.settleStatus << " mateOK=" << (int)mateOK; + //if (settle.settleStatus == 2 && mateOK) { + // DEBUGLOG << " SETTLES -"; + // if (ind.sex == 1) DEBUGLOG << " MALE "; else DEBUGLOG << " FEMALE "; + //} + //DEBUGLOG << endl; #endif - if (pRandom->Bernoulli(settprob)) { // settlement allowed - densdepOK = true; - settle.settleStatus = 2; - } - else { // settlement procluded - settle.settleStatus = 1; + settle.pSettPatch = pPatch; } -#if RSDEBUG -//DEBUGLOG << "Population::transfer(): 8889: i=" << i -// << " settleStatus=" << settle.settleStatus << " mateOK=" << (int)mateOK; -//if (settle.settleStatus == 2 && mateOK) { -// DEBUGLOG << " SETTLES -"; -// if (ind.sex == 1) DEBUGLOG << " MALE "; else DEBUGLOG << " FEMALE "; -//} -//DEBUGLOG << endl; -#endif - settle.pSettPatch = pPatch; + inds[i]->setSettPatch(settle); } - inds[i]->setSettPatch(settle); - } - else { - if (settle.settleStatus == 2) { // previously allowed to settle - densdepOK = true; + else { + if (settle.settleStatus == 2) { // previously allowed to settle + densdepOK = true; + } } } } - } - else { // no density-dependent settlement - densdepOK = true; - settle.settleStatus = 2; - settle.pSettPatch = pPatch; - inds[i]->setSettPatch(settle); - } + else { // no density-dependent settlement + densdepOK = true; + settle.settleStatus = 2; + settle.pSettPatch = pPatch; + inds[i]->setSettPatch(settle); + } - if (mateOK && densdepOK) { // can recruit to patch - ind.status = 4; - ndispersers--; - } - else { // does not recruit - if (trfr.moveModel) { - ind.status = 1; // continue dispersing, unless ... - // ... maximum steps has been exceeded - pathSteps steps = inds[i]->getSteps(); - settleSteps settsteps = pSpecies->getSteps(ind.stage,ind.sex); - if (steps.year >= settsteps.maxStepsYr) { - ind.status = 3; // waits until next year - } - if (steps.total >= settsteps.maxSteps) { - ind.status = 6; // dies - } + if (mateOK && densdepOK) { // can recruit to patch + ind.status = 4; + ndispersers--; } - else { // dispersal kernel - if (sett.wait) { - ind.status = 3; // wait until next dispersal event + else { // does not recruit + if (trfr.moveModel) { + ind.status = 1; // continue dispersing, unless ... + // ... maximum steps has been exceeded + pathSteps steps = inds[i]->getSteps(); + settleSteps settsteps = pSpecies->getSteps(ind.stage, ind.sex); + if (steps.year >= settsteps.maxStepsYr) { + ind.status = 3; // waits until next year + } + if (steps.total >= settsteps.maxSteps) { + ind.status = 6; // dies + } } - else { - ind.status = 6; // (dies unless a neighbouring cell is suitable) + else { // dispersal kernel + if (sett.wait) { + ind.status = 3; // wait until next dispersal event + } + else { + ind.status = 6; // (dies unless a neighbouring cell is suitable) + } + ndispersers--; } - ndispersers--; } } - } - inds[i]->setStatus(ind.status); - } + inds[i]->setStatus(ind.status); + } #if RS_RCPP - // write each individuals current movement step and status to paths file - if (trfr.moveModel && sim.outPaths) { - if(nextseason >= sim.outStartPaths && nextseason%sim.outIntPaths==0) { + // write each individuals current movement step and status to paths file + if (trfr.moveModel && sim.outPaths) { + if (nextseason >= sim.outStartPaths && nextseason % sim.outIntPaths == 0) { inds[i]->outMovePath(nextseason); + } } - } #endif - if (!trfr.moveModel && sett.go2nbrLocn && (ind.status == 3 || ind.status == 6)) - { - // for kernel-based transfer only ... - // determine whether recruitment to a neighbouring cell is possible + if (!trfr.moveModel && sett.go2nbrLocn && (ind.status == 3 || ind.status == 6)) + { + // for kernel-based transfer only ... + // determine whether recruitment to a neighbouring cell is possible #if RSDEBUG //DEBUGLOG << "Population::transfer(): neighbour cell search: sett.go2nbrLocn = " << sett.go2nbrLocn // << " ind.status = " << ind.status // << endl; #endif - pCell = inds[i]->getLocn(1); - newloc = pCell->getLocn(); - vector nbrlist; - for (int dx = -1; dx < 2; dx++) { - for (int dy = -1; dy < 2; dy++) { - if (dx !=0 || dy != 0) { //cell is not the current cell - nbrloc.x = newloc.x + dx; nbrloc.y = newloc.y + dy; - if (nbrloc.x >= 0 && nbrloc.x <= ppLand.maxX - && nbrloc.y >= 0 && nbrloc.y <= ppLand.maxY) { // within landscape - // add to list of potential neighbouring cells if suitable, etc. - pCell = pLandscape->findCell(nbrloc.x,nbrloc.y); - if (pCell != 0) { // not no-data area - patch = pCell->getPatch(); - if (patch != 0) { // not no-data area - pPatch = (Patch*)patch; - patchnum = pPatch->getPatchNum(); - if (patchnum > 0 && pPatch != inds[i]->getNatalPatch()) - { // not the matrix or natal patch - if (pPatch->getK() > 0.0) - { // suitable - if (sett.findMate) { - if (matePresent(pCell,othersex)) nbrlist.push_back(pCell); + pCell = inds[i]->getLocn(1); + newloc = pCell->getLocn(); + vector nbrlist; + for (int dx = -1; dx < 2; dx++) { + for (int dy = -1; dy < 2; dy++) { + if (dx != 0 || dy != 0) { //cell is not the current cell + nbrloc.x = newloc.x + dx; nbrloc.y = newloc.y + dy; + if (nbrloc.x >= 0 && nbrloc.x <= ppLand.maxX + && nbrloc.y >= 0 && nbrloc.y <= ppLand.maxY) { // within landscape + // add to list of potential neighbouring cells if suitable, etc. + pCell = pLandscape->findCell(nbrloc.x, nbrloc.y); + if (pCell != 0) { // not no-data area + patch = pCell->getPatch(); + if (patch != 0) { // not no-data area + pPatch = (Patch*)patch; + patchnum = pPatch->getPatchNum(); + if (patchnum > 0 && pPatch != inds[i]->getNatalPatch()) + { // not the matrix or natal patch + if (pPatch->getK() > 0.0) + { // suitable + if (sett.findMate) { + if (matePresent(pCell, othersex)) nbrlist.push_back(pCell); + } + else + nbrlist.push_back(pCell); } - else - nbrlist.push_back(pCell); } } } @@ -1390,61 +1391,60 @@ for (int i = 0; i < ninds; i++) { } } } - } - int listsize = (int)nbrlist.size(); - if (listsize > 0) { // there is at least one suitable neighbouring cell - if (listsize == 1) { - inds[i]->moveto(nbrlist[0]); - } - else { // select at random from the list - int rrr = pRandom->IRandom(0,listsize-1); - inds[i]->moveto(nbrlist[rrr]); + int listsize = (int)nbrlist.size(); + if (listsize > 0) { // there is at least one suitable neighbouring cell + if (listsize == 1) { + inds[i]->moveto(nbrlist[0]); + } + else { // select at random from the list + int rrr = pRandom->IRandom(0, listsize - 1); + inds[i]->moveto(nbrlist[rrr]); + } } + // else list empty - do nothing - individual retains its current location and status } - // else list empty - do nothing - individual retains its current location and status } -} #if RSDEBUG -//DEBUGLOG << "Population::transfer(): 9999: ninds = " << ninds -// << " ndispersers = " << ndispersers << endl; + //DEBUGLOG << "Population::transfer(): 9999: ninds = " << ninds + // << " ndispersers = " << ndispersers << endl; #endif -return ndispersers; + return ndispersers; } // Determine whether there is a potential mate present in a patch which a potential // settler has reached -bool Population::matePresent(Cell *pCell,short othersex) +bool Population::matePresent(Cell* pCell, short othersex) { -int patch; -Patch *pPatch; -Population *pNewPopn; -int popsize = 0; -bool matefound = false; - -patch = (int)pCell->getPatch(); -if (patch != 0) { - pPatch = (Patch*)pCell->getPatch(); - if (pPatch->getPatchNum() > 0) { // not the matrix patch - if (pPatch->getK() > 0.0) - { // suitable - pNewPopn = (Population*)pPatch->getPopn((intptr)pSpecies); - if (pNewPopn != 0) { - // count members of other sex already resident in the patch - for (int stg = 0; stg < nStages; stg++) { - popsize += pNewPopn->nInds[stg][othersex]; + int patch; + Patch* pPatch; + Population* pNewPopn; + int popsize = 0; + bool matefound = false; + + patch = (int)pCell->getPatch(); + if (patch != 0) { + pPatch = (Patch*)pCell->getPatch(); + if (pPatch->getPatchNum() > 0) { // not the matrix patch + if (pPatch->getK() > 0.0) + { // suitable + pNewPopn = (Population*)pPatch->getPopn((intptr)pSpecies); + if (pNewPopn != 0) { + // count members of other sex already resident in the patch + for (int stg = 0; stg < nStages; stg++) { + popsize += pNewPopn->nInds[stg][othersex]; + } + } + if (popsize < 1) { + // add any potential settlers of the other sex + popsize += pPatch->getPossSettlers(pSpecies, othersex); } - } - if (popsize < 1) { - // add any potential settlers of the other sex - popsize += pPatch->getPossSettlers(pSpecies,othersex); } } } -} -if (popsize > 0) matefound = true; -return matefound; + if (popsize > 0) matefound = true; + return matefound; } //--------------------------------------------------------------------------- @@ -1454,14 +1454,14 @@ return matefound; // FOR MULTIPLE SPECIES, MAY NEED TO SEPARATE OUT THIS IDENTIFICATION STAGE, // SO THAT IT CAN BE PERFORMED FOR ALL SPECIES BEFORE ANY UPDATING OF POPULATIONS -void Population::survival0(float localK,short option0,short option1) +void Population::survival0(float localK, short option0, short option1) { -// option0: 0 - stage 0 (juveniles) only -// 1 - all stages -// 2 - stage 1 and above (all non-juveniles) -// option1: 0 - development only (when survival is annual) -// 1 - development and survival -// 2 - survival only (when survival is annual) + // option0: 0 - stage 0 (juveniles) only + // 1 - all stages + // 2 - stage 1 and above (all non-juveniles) + // option1: 0 - development only (when survival is annual) + // 1 - development and survival + // 2 - survival only (when survival is annual) #if RSDEBUG //DEBUGLOG << "Population::survival0():" @@ -1473,255 +1473,255 @@ void Population::survival0(float localK,short option0,short option1) // << endl; #endif -densDepParams ddparams = pSpecies->getDensDep(); -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); - -// get surrent population size -int ninds = (int)inds.size(); -if (ninds == 0) return; + densDepParams ddparams = pSpecies->getDensDep(); + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); -// set up local copies of species development and survival tables -int nsexes; -if (dem.repType == 0) nsexes = 1; else nsexes = 2; -float dev[NSTAGES][NSEXES]; -float surv[NSTAGES][NSEXES]; -short minAge[NSTAGES][NSEXES]; -for (int stg = 0; stg < sstruct.nStages; stg++) { - for (int sex = 0; sex < nsexes; sex++) { - if (dem.stageStruct) { - if (dem.repType == 1) { // simple sexual model - // both sexes use development and survival recorded for females - dev[stg][sex] = pSpecies->getDev(stg,0); - surv[stg][sex] = pSpecies->getSurv(stg,0); - minAge[stg][sex] = pSpecies->getMinAge(stg,0); - } - else { - dev[stg][sex] = pSpecies->getDev(stg,sex); - surv[stg][sex] = pSpecies->getSurv(stg,sex); - minAge[stg][sex] = pSpecies->getMinAge(stg,sex); - } - if (option1 == 0) surv[stg][sex] = 1.0; // development only - all survive - if (option1 == 2) dev[stg][sex] = 0.0; // survival only - none develops - } - else { // non-structured population - if (stg == 1) { // adults - dev[stg][sex] = 0.0; surv[stg][sex] = 0.0; minAge[stg][sex] = 0; + // get surrent population size + int ninds = (int)inds.size(); + if (ninds == 0) return; + + // set up local copies of species development and survival tables + int nsexes; + if (dem.repType == 0) nsexes = 1; else nsexes = 2; + float dev[NSTAGES][NSEXES]; + float surv[NSTAGES][NSEXES]; + short minAge[NSTAGES][NSEXES]; + for (int stg = 0; stg < sstruct.nStages; stg++) { + for (int sex = 0; sex < nsexes; sex++) { + if (dem.stageStruct) { + if (dem.repType == 1) { // simple sexual model + // both sexes use development and survival recorded for females + dev[stg][sex] = pSpecies->getDev(stg, 0); + surv[stg][sex] = pSpecies->getSurv(stg, 0); + minAge[stg][sex] = pSpecies->getMinAge(stg, 0); + } + else { + dev[stg][sex] = pSpecies->getDev(stg, sex); + surv[stg][sex] = pSpecies->getSurv(stg, sex); + minAge[stg][sex] = pSpecies->getMinAge(stg, sex); + } + if (option1 == 0) surv[stg][sex] = 1.0; // development only - all survive + if (option1 == 2) dev[stg][sex] = 0.0; // survival only - none develops } - else { // juveniles - dev[stg][sex] = 1.0; surv[stg][sex] = 1.0; minAge[stg][sex] = 0; + else { // non-structured population + if (stg == 1) { // adults + dev[stg][sex] = 0.0; surv[stg][sex] = 0.0; minAge[stg][sex] = 0; + } + else { // juveniles + dev[stg][sex] = 1.0; surv[stg][sex] = 1.0; minAge[stg][sex] = 0; + } } - } #if RSDEBUG -//DEBUGLOG << "Population::survival0(): 1111 " -// << " dev[" << stg << "][" << sex << "] = " << dev[stg][sex] -// << " surv[" << stg << "][" << sex << "] = " << surv[stg][sex] -// << endl; + //DEBUGLOG << "Population::survival0(): 1111 " + // << " dev[" << stg << "][" << sex << "] = " << dev[stg][sex] + // << " surv[" << stg << "][" << sex << "] = " << surv[stg][sex] + // << endl; #endif + } } -} -if (dem.stageStruct) { + if (dem.stageStruct) { #if RSDEBUG -// DEBUGLOG << "Population::survival0(): 2222 " -// << " ninds=" << ninds << " localK=" << localK -// << " effect of density dependence:" << endl; -// for (int st = 0; st < nStages; st++) { -// for (int sx = 0; sx < nsexes; sx++) { -// DEBUGLOG << "st=" << st << " sx=" << sx << " nInds=" << nInds[st][sx] << endl; -// } -// } + // DEBUGLOG << "Population::survival0(): 2222 " + // << " ninds=" << ninds << " localK=" << localK + // << " effect of density dependence:" << endl; + // for (int st = 0; st < nStages; st++) { + // for (int sx = 0; sx < nsexes; sx++) { + // DEBUGLOG << "st=" << st << " sx=" << sx << " nInds=" << nInds[st][sx] << endl; + // } + // } #endif // apply density dependence in development and/or survival probabilities - for (int stg = 0; stg < nStages; stg++) { - for (int sex = 0; sex < nsexes; sex++) { - if (option1 != 2 && sstruct.devDens && stg > 0) { + for (int stg = 0; stg < nStages; stg++) { + for (int sex = 0; sex < nsexes; sex++) { + if (option1 != 2 && sstruct.devDens && stg > 0) { #if RSDEBUG -// DEBUGLOG << "DD in DEVELOPMENT for stg=" << stg << " sex=" << sex << endl; + // DEBUGLOG << "DD in DEVELOPMENT for stg=" << stg << " sex=" << sex << endl; #endif // NB DD in development does NOT apply to juveniles, // which must develop to stage 1 if they survive - float effect = 0.0; - if (sstruct.devStageDens) { // stage-specific density dependence - // NOTE: matrix entries represent effect of ROW on COLUMN - // AND males precede females - float weight = 0.0; - for (int effstg = 0; effstg < nStages; effstg++) { - for (int effsex = 0; effsex < nSexes; effsex++) { - if (dem.repType == 2) { - int rowincr,colincr; - if (effsex == 0) rowincr = 1; else rowincr = 0; - if (sex == 0) colincr = 1; else colincr = 0; - weight = pSpecies->getDDwtDev(2*stg+colincr,2*effstg+rowincr); - } - else { - weight = pSpecies->getDDwtDev(stg,effstg); - } - effect += (float)nInds[effstg][effsex] * weight; + float effect = 0.0; + if (sstruct.devStageDens) { // stage-specific density dependence + // NOTE: matrix entries represent effect of ROW on COLUMN + // AND males precede females + float weight = 0.0; + for (int effstg = 0; effstg < nStages; effstg++) { + for (int effsex = 0; effsex < nSexes; effsex++) { + if (dem.repType == 2) { + int rowincr, colincr; + if (effsex == 0) rowincr = 1; else rowincr = 0; + if (sex == 0) colincr = 1; else colincr = 0; + weight = pSpecies->getDDwtDev(2 * stg + colincr, 2 * effstg + rowincr); + } + else { + weight = pSpecies->getDDwtDev(stg, effstg); + } + effect += (float)nInds[effstg][effsex] * weight; #if RSDEBUG -// DEBUGLOG << " effstg=" << effstg << " effsex=" << effsex; -// DEBUGLOG << " weight=" << weight << " effect=" << effect -// << endl; + // DEBUGLOG << " effstg=" << effstg << " effsex=" << effsex; + // DEBUGLOG << " weight=" << weight << " effect=" << effect + // << endl; #endif + } } } - } - else // not stage-specific - effect = (float)totalPop(); - if (localK > 0.0) - dev[stg][sex] *= exp(-(ddparams.devCoeff*effect)/localK); -#if RSDEBUG -//DEBUGLOG << "Population::survival0(): 2288 " << " effect=" << effect; -//if (localK > 0.0) -// DEBUGLOG << " exp=" << exp(-(ddparams.devCoeff*effect)/localK); -//DEBUGLOG << " dev[" << stg << "][" << sex << "] = " << dev[stg][sex] -// << endl; -#endif - } // end of if (sstruct.devDens && stg > 0) - if (option1 != 0 && sstruct.survDens) { -#if RSDEBUG -// DEBUGLOG << "DD in SURVIVAL for stg=" << stg << " sex=" << sex << endl; -#endif - float effect = 0.0; - if (sstruct.survStageDens) { // stage-specific density dependence - // NOTE: matrix entries represent effect of ROW on COLUMN - // AND males precede females - float weight = 0.0; - for (int effstg = 0; effstg < nStages; effstg++) { - for (int effsex = 0; effsex < nSexes; effsex++) { - if (dem.repType == 2) { - int rowincr,colincr; - if (effsex == 0) rowincr = 1; else rowincr = 0; - if (sex == 0) colincr = 1; else colincr = 0; - weight = pSpecies->getDDwtSurv(2*stg+colincr,2*effstg+rowincr); - } - else { - weight = pSpecies->getDDwtSurv(stg,effstg); - } - effect += (float)nInds[effstg][effsex] * weight; + else // not stage-specific + effect = (float)totalPop(); + if (localK > 0.0) + dev[stg][sex] *= exp(-(ddparams.devCoeff * effect) / localK); +#if RSDEBUG + //DEBUGLOG << "Population::survival0(): 2288 " << " effect=" << effect; + //if (localK > 0.0) + // DEBUGLOG << " exp=" << exp(-(ddparams.devCoeff*effect)/localK); + //DEBUGLOG << " dev[" << stg << "][" << sex << "] = " << dev[stg][sex] + // << endl; +#endif + } // end of if (sstruct.devDens && stg > 0) + if (option1 != 0 && sstruct.survDens) { +#if RSDEBUG + // DEBUGLOG << "DD in SURVIVAL for stg=" << stg << " sex=" << sex << endl; +#endif + float effect = 0.0; + if (sstruct.survStageDens) { // stage-specific density dependence + // NOTE: matrix entries represent effect of ROW on COLUMN + // AND males precede females + float weight = 0.0; + for (int effstg = 0; effstg < nStages; effstg++) { + for (int effsex = 0; effsex < nSexes; effsex++) { + if (dem.repType == 2) { + int rowincr, colincr; + if (effsex == 0) rowincr = 1; else rowincr = 0; + if (sex == 0) colincr = 1; else colincr = 0; + weight = pSpecies->getDDwtSurv(2 * stg + colincr, 2 * effstg + rowincr); + } + else { + weight = pSpecies->getDDwtSurv(stg, effstg); + } + effect += (float)nInds[effstg][effsex] * weight; #if RSDEBUG -// DEBUGLOG << " effstg=" << effstg << " effsex=" << effsex; -// DEBUGLOG << " weight=" << weight << " effect=" << effect -// << endl; + // DEBUGLOG << " effstg=" << effstg << " effsex=" << effsex; + // DEBUGLOG << " weight=" << weight << " effect=" << effect + // << endl; #endif + } } } - } - else // not stage-specific - effect = (float)totalPop(); - if (localK > 0.0) - surv[stg][sex] *= exp(-(ddparams.survCoeff*effect)/localK); -#if RSDEBUG -//DEBUGLOG << "Population::survival0(): 3333 " << " effect=" << effect; -//if (localK > 0.0) -// DEBUGLOG << " exp = " << exp(-(ddparams.survCoeff*effect)/localK); -//DEBUGLOG << " surv[" << stg << "][" << sex << "] = " << surv[stg][sex] -// << endl; -#endif - } // end of if (sstruct.survDens) + else // not stage-specific + effect = (float)totalPop(); + if (localK > 0.0) + surv[stg][sex] *= exp(-(ddparams.survCoeff * effect) / localK); +#if RSDEBUG + //DEBUGLOG << "Population::survival0(): 3333 " << " effect=" << effect; + //if (localK > 0.0) + // DEBUGLOG << " exp = " << exp(-(ddparams.survCoeff*effect)/localK); + //DEBUGLOG << " surv[" << stg << "][" << sex << "] = " << surv[stg][sex] + // << endl; +#endif + } // end of if (sstruct.survDens) + } } } -} -// identify which individuals die or develop + // identify which individuals die or develop #if RSDEBUG //DEBUGLOG << "Population::survival0():" << " ninds " << ninds // << endl; #endif -for (int i = 0; i < ninds; i++) { - indStats ind = inds[i]->getStats(); -#if RSDEBUG -//DEBUGLOG << "Population::survival0():" -// << " i=" << i << " indId=" << inds[i]->getId() -// << " stage=" << ind.stage << " status=" << ind.status << " sex=" << ind.sex -//#if PARTMIGRN -// << " migrnstatus=" << inds[i]->getMigrnStatus() -//#endif // PARTMIGRN -// << endl; -#endif - if ((ind.stage == 0 && option0 < 2) || (ind.stage > 0 && option0 > 0)) { - // condition for processing the stage is met... - if (ind.status < 6) { // not already doomed - double probsurv = surv[ind.stage][ind.sex]; - // does the individual survive? - if (pRandom->Bernoulli(probsurv)) { // survives - // does the individual develop? - double probdev = dev[ind.stage][ind.sex]; - if (ind.stage < nStages-1) { // not final stage -#if RSDEBUG -//DEBUGLOG << "Population::survival0():" -// << " i=" << i << " indId=" << inds[i]->getId() -// << " age=" << ind.age << " minAge[stage+1]=" << minAge[ind.stage+1][ind.sex] -// << " probdev=" << probdev -// << endl; -#endif - if (ind.age >= minAge[ind.stage+1][ind.sex]) { // old enough to enter next stage -#if RSDEBUG -//DEBUGLOG << "Population::survival0():" -// << " i=" << i << " indId=" << inds[i]->getId() << " OLD ENOUGH" -// << endl; -#endif - if (pRandom->Bernoulli(probdev)) { - inds[i]->developing(); + for (int i = 0; i < ninds; i++) { + indStats ind = inds[i]->getStats(); +#if RSDEBUG + //DEBUGLOG << "Population::survival0():" + // << " i=" << i << " indId=" << inds[i]->getId() + // << " stage=" << ind.stage << " status=" << ind.status << " sex=" << ind.sex + //#if PARTMIGRN + // << " migrnstatus=" << inds[i]->getMigrnStatus() + //#endif // PARTMIGRN + // << endl; +#endif + if ((ind.stage == 0 && option0 < 2) || (ind.stage > 0 && option0 > 0)) { + // condition for processing the stage is met... + if (ind.status < 6) { // not already doomed + double probsurv = surv[ind.stage][ind.sex]; + // does the individual survive? + if (pRandom->Bernoulli(probsurv)) { // survives + // does the individual develop? + double probdev = dev[ind.stage][ind.sex]; + if (ind.stage < nStages - 1) { // not final stage +#if RSDEBUG + //DEBUGLOG << "Population::survival0():" + // << " i=" << i << " indId=" << inds[i]->getId() + // << " age=" << ind.age << " minAge[stage+1]=" << minAge[ind.stage+1][ind.sex] + // << " probdev=" << probdev + // << endl; +#endif + if (ind.age >= minAge[ind.stage + 1][ind.sex]) { // old enough to enter next stage +#if RSDEBUG + //DEBUGLOG << "Population::survival0():" + // << " i=" << i << " indId=" << inds[i]->getId() << " OLD ENOUGH" + // << endl; +#endif + if (pRandom->Bernoulli(probdev)) { + inds[i]->developing(); + } } } } - } - else { // doomed to die + else { // doomed to die #if RSDEBUG -//DEBUGLOG << "Population::survival0():" -// << " i=" << i << " indId=" << inds[i]->getId() << " DIES" -// << endl; + //DEBUGLOG << "Population::survival0():" + // << " i=" << i << " indId=" << inds[i]->getId() << " DIES" + // << endl; #endif - inds[i]->setStatus(8); + inds[i]->setStatus(8); + } } } - } #if RSDEBUG -//ind = inds[i]->getStats(); -//DEBUGLOG << "Population::survival0():" -// << " i = " << i << " ID = " << inds[i]->getId() -// << " stage = " << ind.stage << " status = " << ind.status -// << endl; + //ind = inds[i]->getStats(); + //DEBUGLOG << "Population::survival0():" + // << " i = " << i << " ID = " << inds[i]->getId() + // << " stage = " << ind.stage << " status = " << ind.status + // << endl; #endif -} + } } // Apply survival changes to the population void Population::survival1(void) { -int ninds = (int)inds.size(); + int ninds = (int)inds.size(); #if RSDEBUG -//DEBUGLOG << "Population::survival1(): this=" << this -// << " patchNum=" << pPatch->getPatchNum() << " ninds=" << ninds -// << endl; + //DEBUGLOG << "Population::survival1(): this=" << this + // << " patchNum=" << pPatch->getPatchNum() << " ninds=" << ninds + // << endl; #endif -for (int i = 0; i < ninds; i++) { - indStats ind = inds[i]->getStats(); + for (int i = 0; i < ninds; i++) { + indStats ind = inds[i]->getStats(); #if RSDEBUG -//DEBUGLOG << "Population::survival1(): i=" << i -// << " indId=" << inds[i]->getId() << " stage=" << ind.stage << " sex=" << ind.sex -// << " isDeveloping=" << ind.isDeveloping << " status=" << ind.status -// << endl; + //DEBUGLOG << "Population::survival1(): i=" << i + // << " indId=" << inds[i]->getId() << " stage=" << ind.stage << " sex=" << ind.sex + // << " isDeveloping=" << ind.isDeveloping << " status=" << ind.status + // << endl; #endif - if (ind.status > 5) { // doomed to die - delete inds[i]; - inds[i] = NULL; - nInds[ind.stage][ind.sex]--; - } - else { - if (ind.isDeveloping) { // develops to next stage + if (ind.status > 5) { // doomed to die + delete inds[i]; + inds[i] = NULL; nInds[ind.stage][ind.sex]--; - inds[i]->develop(); - nInds[ind.stage+1][ind.sex]++; + } + else { + if (ind.isDeveloping) { // develops to next stage + nInds[ind.stage][ind.sex]--; + inds[i]->develop(); + nInds[ind.stage + 1][ind.sex]++; + } } } -} #if RSDEBUG -//DEBUGLOG << "Population::survival1(): this=" << this -// << " patchNum=" << pPatch->getPatchNum() << " completed individuals loop" -// << endl; + //DEBUGLOG << "Population::survival1(): this=" << this + // << " patchNum=" << pPatch->getPatchNum() << " completed individuals loop" + // << endl; #endif #if RSDEBUG @@ -1731,517 +1731,517 @@ for (int i = 0; i < ninds; i++) { #endif // remove pointers to dead individuals -clean(); + clean(); #if RSDEBUG -//DEBUGLOG << "Population::survival1(): this=" << this -// << " patchNum=" << pPatch->getPatchNum() << " finished" -// << endl; + //DEBUGLOG << "Population::survival1(): this=" << this + // << " patchNum=" << pPatch->getPatchNum() << " finished" + // << endl; #endif } void Population::ageIncrement(void) { -int ninds = (int)inds.size(); -stageParams sstruct = pSpecies->getStage(); + int ninds = (int)inds.size(); + stageParams sstruct = pSpecies->getStage(); #if RSDEBUG -//DEBUGLOG << "Population::ageIncrement():" << " inds.size() = " << inds.size() -// << endl; + //DEBUGLOG << "Population::ageIncrement():" << " inds.size() = " << inds.size() + // << endl; #endif -for (int i = 0; i < ninds; i++) { - inds[i]->ageIncrement(sstruct.maxAge); -} + for (int i = 0; i < ninds; i++) { + inds[i]->ageIncrement(sstruct.maxAge); + } } //--------------------------------------------------------------------------- // Remove zero pointers to dead or dispersed individuals void Population::clean(void) { -int ninds = (int)inds.size(); -if (ninds > 0) { -// sort (inds.begin(), inds.end()); -// reverse (inds.begin(), inds.end()); -// -// while (inds.size() > 0 && inds[inds.size()-1] == NULL ) { -// inds.pop_back(); -// } - // ALTERNATIVE METHOD: AVOIDS SLOW SORTING OF POPULATION - std::vector survivors; // all surviving individuals - for (int i = 0; i < ninds; i++) { - if (inds[i] != NULL) { - survivors.push_back(inds[i]); + int ninds = (int)inds.size(); + if (ninds > 0) { + // sort (inds.begin(), inds.end()); + // reverse (inds.begin(), inds.end()); + // + // while (inds.size() > 0 && inds[inds.size()-1] == NULL ) { + // inds.pop_back(); + // } + // ALTERNATIVE METHOD: AVOIDS SLOW SORTING OF POPULATION + std::vector survivors; // all surviving individuals + for (int i = 0; i < ninds; i++) { + if (inds[i] != NULL) { + survivors.push_back(inds[i]); + } } - } - inds.clear(); - inds = survivors; + inds.clear(); + inds = survivors; #if RS_RCPP - shuffle(inds.begin(), inds.end(), pRandom->getRNG() ); + shuffle(inds.begin(), inds.end(), pRandom->getRNG()); #else #if !RSDEBUG - // do not randomise individuals in RSDEBUG mode, as the function uses rand() - // and therefore the randomisation will differ between identical runs of RS - shuffle(inds.begin(), inds.end(), pRandom->getRNG() ); + // do not randomise individuals in RSDEBUG mode, as the function uses rand() + // and therefore the randomisation will differ between identical runs of RS + shuffle(inds.begin(), inds.end(), pRandom->getRNG()); #endif // !RSDEBUG #endif // RS_RCPP -} + } } //--------------------------------------------------------------------------- // Open population file and write header record -bool Population::outPopHeaders(int landNr,bool patchModel) { +bool Population::outPopHeaders(int landNr, bool patchModel) { -if (landNr == -999) { // close file - if (outPop.is_open()) outPop.close(); - outPop.clear(); - return true; -} + if (landNr == -999) { // close file + if (outPop.is_open()) outPop.close(); + outPop.clear(); + return true; + } -string name; -//landParams ppLand = pLandscape->getLandParams(); -//envStochParams env = paramsStoch->getStoch(); -simParams sim = paramsSim->getSim(); -envGradParams grad = paramsGrad->getGradient(); + string name; + //landParams ppLand = pLandscape->getLandParams(); + //envStochParams env = paramsStoch->getStoch(); + simParams sim = paramsSim->getSim(); + envGradParams grad = paramsGrad->getGradient(); -// NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER -// ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); + // NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER + // ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); -if (sim.batchMode) { - name = paramsSim->getDir(2) - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) + "_Pop.txt"; -} -else{ - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) +"_Pop.txt"; -} -outPop.open(name.c_str()); -outPop << "Rep\tYear\tRepSeason"; -if (patchModel) outPop << "\tPatchID\tNcells"; -else outPop << "\tx\ty"; -// determine whether environmental data need be written for populations -bool writeEnv = false; -if (grad.gradient) writeEnv = true; -if (paramsStoch->envStoch()) writeEnv = true; -if (writeEnv) outPop << "\tEpsilon\tGradient\tLocal_K"; -outPop << "\tSpecies\tNInd"; -#if RSDEBUG -//DEBUGLOG << "Population::outPopHeaders(): this=" << this -// << " patchNum=" << pPatch->getPatchNum() -// << " totalPop()=" << totalPop() -// << " nStages=" << nStages << " nSexes=" << nSexes -// << endl; + if (sim.batchMode) { + name = paramsSim->getDir(2) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) + "_Pop.txt"; + } + else { + name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Pop.txt"; + } + outPop.open(name.c_str()); + outPop << "Rep\tYear\tRepSeason"; + if (patchModel) outPop << "\tPatchID\tNcells"; + else outPop << "\tx\ty"; + // determine whether environmental data need be written for populations + bool writeEnv = false; + if (grad.gradient) writeEnv = true; + if (paramsStoch->envStoch()) writeEnv = true; + if (writeEnv) outPop << "\tEpsilon\tGradient\tLocal_K"; + outPop << "\tSpecies\tNInd"; +#if RSDEBUG + //DEBUGLOG << "Population::outPopHeaders(): this=" << this + // << " patchNum=" << pPatch->getPatchNum() + // << " totalPop()=" << totalPop() + // << " nStages=" << nStages << " nSexes=" << nSexes + // << endl; #endif -if (dem.stageStruct) { - if (dem.repType == 0) - { - for (int i = 1; i < sstruct.nStages; i++) outPop << "\tNInd_stage" << i ; - outPop << "\tNJuvs"; + if (dem.stageStruct) { + if (dem.repType == 0) + { + for (int i = 1; i < sstruct.nStages; i++) outPop << "\tNInd_stage" << i; + outPop << "\tNJuvs"; + } + else { + for (int i = 1; i < sstruct.nStages; i++) + outPop << "\tNfemales_stage" << i << "\tNmales_stage" << i; + outPop << "\tNJuvFemales\tNJuvMales"; + } } else { - for (int i = 1; i < sstruct.nStages; i++) - outPop << "\tNfemales_stage" << i << "\tNmales_stage" << i ; - outPop << "\tNJuvFemales\tNJuvMales"; + if (dem.repType != 0) outPop << "\tNfemales\tNmales"; } -} -else { - if (dem.repType != 0) outPop << "\tNfemales\tNmales"; -} -outPop << endl; + outPop << endl; -return outPop.is_open(); + return outPop.is_open(); } //--------------------------------------------------------------------------- // Write record to population file -void Population::outPopulation(int rep,int yr,int gen,float eps, - bool patchModel,bool writeEnv,bool gradK) +void Population::outPopulation(int rep, int yr, int gen, float eps, + bool patchModel, bool writeEnv, bool gradK) { -Cell *pCell; + Cell* pCell; #if RSDEBUG -//DEBUGLOG << "Population::outPopulations(): this=" << this -// << " writeEnv " << (int)writeEnv -// << endl; + //DEBUGLOG << "Population::outPopulations(): this=" << this + // << " writeEnv " << (int)writeEnv + // << endl; #endif // NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER // ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -popStats p; - -outPop << rep << "\t" << yr << "\t" << gen; -if (patchModel) { - outPop << "\t" << pPatch->getPatchNum(); - outPop << "\t" << pPatch->getNCells(); -} -else { - locn loc = pPatch->getCellLocn(0); - outPop << "\t" << loc.x << "\t" << loc.y; -} -if (writeEnv) { - if (pPatch->getPatchNum() == 0) { // matrix - outPop << "\t0\t0\t0"; + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + popStats p; + + outPop << rep << "\t" << yr << "\t" << gen; + if (patchModel) { + outPop << "\t" << pPatch->getPatchNum(); + outPop << "\t" << pPatch->getNCells(); } else { - float k = pPatch->getK(); - float envval = 0.0; - pCell = pPatch->getRandomCell(); - if (pCell != 0) envval = pCell->getEnvVal(); - outPop << "\t" << eps << "\t" << envval << "\t" << k; + locn loc = pPatch->getCellLocn(0); + outPop << "\t" << loc.x << "\t" << loc.y; + } + if (writeEnv) { + if (pPatch->getPatchNum() == 0) { // matrix + outPop << "\t0\t0\t0"; + } + else { + float k = pPatch->getK(); + float envval = 0.0; + pCell = pPatch->getRandomCell(); + if (pCell != 0) envval = pCell->getEnvVal(); + outPop << "\t" << eps << "\t" << envval << "\t" << k; + } } -} #if RSDEBUG -//DEBUGLOG << "Population::outPopulation(): this=" << this -// << " patchNum=" << pPatch->getPatchNum() -// << " totalPop()=" << totalPop() -// << " nStages=" << nStages << " nSexes=" << nSexes -// << endl; + //DEBUGLOG << "Population::outPopulation(): this=" << this + // << " patchNum=" << pPatch->getPatchNum() + // << " totalPop()=" << totalPop() + // << " nStages=" << nStages << " nSexes=" << nSexes + // << endl; #endif -outPop << "\t" << pSpecies->getSpNum(); -if (dem.stageStruct) { - p = getStats(); - outPop << "\t" << p.nNonJuvs; - // non-juvenile stage totals from permanent array - for (int stg = 1; stg < nStages; stg++) { + outPop << "\t" << pSpecies->getSpNum(); + if (dem.stageStruct) { + p = getStats(); + outPop << "\t" << p.nNonJuvs; + // non-juvenile stage totals from permanent array + for (int stg = 1; stg < nStages; stg++) { + for (int sex = 0; sex < nSexes; sex++) { + outPop << "\t" << nInds[stg][sex]; + } + } + // juveniles from permanent array for (int sex = 0; sex < nSexes; sex++) { - outPop << "\t" << nInds[stg][sex]; + outPop << "\t" << nInds[0][sex]; } } - // juveniles from permanent array - for (int sex = 0; sex < nSexes; sex++) { - outPop << "\t" << nInds[0][sex]; - } -} -else { // non-structured population - outPop << "\t" << totalPop(); - if (dem.repType != 0) - { // sexual model - outPop << "\t" << nInds[1][0] << "\t" << nInds[1][1]; + else { // non-structured population + outPop << "\t" << totalPop(); + if (dem.repType != 0) + { // sexual model + outPop << "\t" << nInds[1][0] << "\t" << nInds[1][1]; + } } -} -outPop << endl; - -/* -#if RS_ABC -obsdata obs; -if (abcYear) { - int nobs = (int)pABCmaster->NObs(); - for (int i = 0; i < nobs; i++) { - obs = pABCmaster->getObsData(i); -#if RSDEBUG -//DEBUGLOG << "Population::outPopulation(): this=" << this << " i=" << i << " yr=" << yr -// << " obs.year=" << obs.year << " obs.type=" << obs.type << " obs.name=" << obs.name -// << " obs.x=" << obs.x << " obs.y=" << obs.y -// << endl; -#endif - if (obs.year == yr && obs.type == 2) { - if (obs.name == "NInds" || obs.name == "Occupied") { - bool match = false; - if (patchModel) { - if (obs.x == pPatch->getPatchNum()) { - match = true; -#if RSDEBUG -//DEBUGLOG << "Population::outPopulation(): i=" << i << " PROCESS Population NInds" -// << " obs.id=" << obs.id << " obs.value=" << obs.value << " obs.x=" << obs.x -// << " pPatch->PatchNum()=" << pPatch->getPatchNum() -// << " totalPop()=" << totalPop() << " p.nNonJuvs=" << p.nNonJuvs -// << endl; -#endif - } - } - else { - locn loc = pPatch->getCentroid(); - if (obs.x == loc.x && obs.y == loc.y) { - match = true; -#if RSDEBUG -DEBUGLOG << "Population::outPopulation(): i=" << i << " PROCESS Population NInds" - << " obs.id=" << obs.id << " obs.value=" << obs.value << " obs.x=" - << obs.x << " obs.y=" << obs.y << " loc.x=" << loc.x << " loc.y=" << loc.y - << " totalPop()=" << totalPop() << " p.nNonJuvs=" << p.nNonJuvs - << endl; -#endif + outPop << endl; + + /* + #if RS_ABC + obsdata obs; + if (abcYear) { + int nobs = (int)pABCmaster->NObs(); + for (int i = 0; i < nobs; i++) { + obs = pABCmaster->getObsData(i); + #if RSDEBUG + //DEBUGLOG << "Population::outPopulation(): this=" << this << " i=" << i << " yr=" << yr + // << " obs.year=" << obs.year << " obs.type=" << obs.type << " obs.name=" << obs.name + // << " obs.x=" << obs.x << " obs.y=" << obs.y + // << endl; + #endif + if (obs.year == yr && obs.type == 2) { + if (obs.name == "NInds" || obs.name == "Occupied") { + bool match = false; + if (patchModel) { + if (obs.x == pPatch->getPatchNum()) { + match = true; + #if RSDEBUG + //DEBUGLOG << "Population::outPopulation(): i=" << i << " PROCESS Population NInds" + // << " obs.id=" << obs.id << " obs.value=" << obs.value << " obs.x=" << obs.x + // << " pPatch->PatchNum()=" << pPatch->getPatchNum() + // << " totalPop()=" << totalPop() << " p.nNonJuvs=" << p.nNonJuvs + // << endl; + #endif + } } - } - if (match) { - if (obs.name == "NInds") { - if (dem.stageStruct) - pABCmaster->AddNewPred(sim.simulation,obs.id,rep,obs.value,p.nNonJuvs,obs.weight); - else - pABCmaster->AddNewPred(sim.simulation,obs.id,rep,obs.value,totalPop(),obs.weight); + else { + locn loc = pPatch->getCentroid(); + if (obs.x == loc.x && obs.y == loc.y) { + match = true; + #if RSDEBUG + DEBUGLOG << "Population::outPopulation(): i=" << i << " PROCESS Population NInds" + << " obs.id=" << obs.id << " obs.value=" << obs.value << " obs.x=" + << obs.x << " obs.y=" << obs.y << " loc.x=" << loc.x << " loc.y=" << loc.y + << " totalPop()=" << totalPop() << " p.nNonJuvs=" << p.nNonJuvs + << endl; + #endif + } } - else { // obs.name == "Occupied" - pABCmaster->AddNewPred(sim.simulation,obs.id,rep,obs.value,p.breeding,obs.weight); + if (match) { + if (obs.name == "NInds") { + if (dem.stageStruct) + pABCmaster->AddNewPred(sim.simulation,obs.id,rep,obs.value,p.nNonJuvs,obs.weight); + else + pABCmaster->AddNewPred(sim.simulation,obs.id,rep,obs.value,totalPop(),obs.weight); + } + else { // obs.name == "Occupied" + pABCmaster->AddNewPred(sim.simulation,obs.id,rep,obs.value,p.breeding,obs.weight); + } } } } } } -} -#endif // ABC -*/ + #endif // ABC + */ } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Open individuals file and write header record -void Population::outIndsHeaders(int rep,int landNr,bool patchModel) +void Population::outIndsHeaders(int rep, int landNr, bool patchModel) { -if (landNr == -999) { // close file - if (outInds.is_open()) { - outInds.close(); outInds.clear(); + if (landNr == -999) { // close file + if (outInds.is_open()) { + outInds.close(); outInds.clear(); + } + return; } - return; -} -string name; -demogrParams dem = pSpecies->getDemogr(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -simParams sim = paramsSim->getSim(); - -if (sim.batchMode) { - name = paramsSim->getDir(2) - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) - + "_Land" + Int2Str(landNr) + "_Rep" + Int2Str(rep) + "_Inds.txt"; -} -else { - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) - + "_Rep" + Int2Str(rep) +"_Inds.txt"; -} -outInds.open(name.c_str()); - -outInds << "Rep\tYear\tRepSeason\tSpecies\tIndID\tStatus"; -if (patchModel) outInds << "\tNatal_patch\tPatchID"; -else outInds << "\tNatal_X\tNatal_Y\tX\tY"; -if (dem.repType != 0) outInds << "\tSex"; -if (dem.stageStruct) outInds << "\tAge\tStage"; -if (emig.indVar) { - if (emig.densDep) outInds << "\tD0\tAlpha\tBeta"; - else outInds << "\tEP"; -} -if (trfr.indVar) { - if (trfr.moveModel) { - if (trfr.moveType == 1) { // SMS - outInds << "\tDP\tGB\tAlphaDB\tBetaDB"; + string name; + demogrParams dem = pSpecies->getDemogr(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + simParams sim = paramsSim->getSim(); + + if (sim.batchMode) { + name = paramsSim->getDir(2) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + + "_Land" + Int2Str(landNr) + "_Rep" + Int2Str(rep) + "_Inds.txt"; + } + else { + name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + + "_Rep" + Int2Str(rep) + "_Inds.txt"; + } + outInds.open(name.c_str()); + + outInds << "Rep\tYear\tRepSeason\tSpecies\tIndID\tStatus"; + if (patchModel) outInds << "\tNatal_patch\tPatchID"; + else outInds << "\tNatal_X\tNatal_Y\tX\tY"; + if (dem.repType != 0) outInds << "\tSex"; + if (dem.stageStruct) outInds << "\tAge\tStage"; + if (emig.indVar) { + if (emig.densDep) outInds << "\tD0\tAlpha\tBeta"; + else outInds << "\tEP"; + } + if (trfr.indVar) { + if (trfr.moveModel) { + if (trfr.moveType == 1) { // SMS + outInds << "\tDP\tGB\tAlphaDB\tBetaDB"; + } + if (trfr.moveType == 2) { // CRW + outInds << "\tStepLength\tRho"; + } } - if (trfr.moveType == 2) { // CRW - outInds << "\tStepLength\tRho"; + else { // kernel + outInds << "\tMeanDistI"; + if (trfr.twinKern) outInds << "\tMeanDistII\tPKernelI"; } } - else { // kernel - outInds << "\tMeanDistI"; - if (trfr.twinKern) outInds << "\tMeanDistII\tPKernelI"; + if (sett.indVar) { + outInds << "\tS0\tAlphaS\tBetaS"; } -} -if (sett.indVar) { - outInds << "\tS0\tAlphaS\tBetaS"; -} -outInds << "\tDistMoved"; + outInds << "\tDistMoved"; #if RSDEBUG -// ALWAYS WRITE NO. OF STEPS -outInds << "\tNsteps"; + // ALWAYS WRITE NO. OF STEPS + outInds << "\tNsteps"; #else -if (trfr.moveModel) outInds << "\tNsteps"; + if (trfr.moveModel) outInds << "\tNsteps"; #endif -outInds << endl; + outInds << endl; } //--------------------------------------------------------------------------- // Write records to individuals file -void Population::outIndividual(Landscape *pLandscape,int rep,int yr,int gen, +void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, int patchNum) { -//int x, y, p_id; -bool writeInd; -pathSteps steps; -Cell *pCell; - -landParams ppLand = pLandscape->getLandParams(); -//landOrigin lim = pLandscape->getOrigin(); -demogrParams dem = pSpecies->getDemogr(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -short spNum = pSpecies->getSpNum(); - -int ninds = (int)inds.size(); - -for (int i = 0; i < ninds; i++) { - indStats ind = inds[i]->getStats(); - if (yr == -1) { // write all initialised individuals - writeInd = true; - outInds << rep << "\t" << yr << "\t" << dem.repSeasons-1; - } - else { - if (dem.stageStruct && gen < 0) { // write status 9 individuals only - if (ind.status == 9) { - writeInd = true; - outInds << rep << "\t" << yr << "\t" << dem.repSeasons-1; - } - else writeInd = false; - } - else { + //int x, y, p_id; + bool writeInd; + pathSteps steps; + Cell* pCell; + + landParams ppLand = pLandscape->getLandParams(); + //landOrigin lim = pLandscape->getOrigin(); + demogrParams dem = pSpecies->getDemogr(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + short spNum = pSpecies->getSpNum(); + + int ninds = (int)inds.size(); + + for (int i = 0; i < ninds; i++) { + indStats ind = inds[i]->getStats(); + if (yr == -1) { // write all initialised individuals writeInd = true; - outInds << rep << "\t" << yr << "\t" << gen; - } - } - if (writeInd) { - outInds << "\t" << spNum << "\t" << inds[i]->getId(); - if (dem.stageStruct) outInds << "\t" << ind.status; - else { // non-structured population - outInds << "\t" << ind.status; - } - pCell = inds[i]->getLocn(1); - locn loc; - if (pCell == 0) loc.x = loc.y = -1; // beyond boundary or in no-data cell - else loc = pCell->getLocn(); - pCell = inds[i]->getLocn(0); - locn natalloc = pCell->getLocn(); -//#if SEASONAL -// pCell = inds[i]->getLocn(2); -// locn prevloc = pCell->getLocn(); -//#endif - if (ppLand.patchModel) { - outInds << "\t" << inds[i]->getNatalPatch()->getPatchNum(); - if (loc.x == -1) outInds << "\t-1"; - else outInds << "\t" << patchNum; + outInds << rep << "\t" << yr << "\t" << dem.repSeasons - 1; } - else { // cell-based model - // EITHER write co-ordinates in cell units ... - outInds << "\t" << (float)natalloc.x << "\t" << natalloc.y; - outInds << "\t" << (float)loc.x << "\t" << (float)loc.y ; - // ... OR write co-ordinates in real-world units -// outInds << "\t" << (float)natalloc.x * (float)ppLand.resol + (float)lim.minEast -// << "\t" << natalloc.y * (float)ppLand.resol + (float)lim.minNorth; -// outInds << "\t" << (float)loc.x * (float)ppLand.resol + (float)lim.minEast -// << "\t" << (float)loc.y * (float)ppLand.resol + (float)lim.minNorth; - } - if (dem.repType != 0) outInds <<"\t" << ind.sex; - if (dem.stageStruct) outInds <<"\t" << ind.age <<"\t"<< ind.stage; - - if (emig.indVar) { - emigTraits e = inds[i]->getEmigTraits(); - if (emig.densDep) { - outInds << "\t" << e.d0 << "\t" << e.alpha << "\t" << e.beta; + else { + if (dem.stageStruct && gen < 0) { // write status 9 individuals only + if (ind.status == 9) { + writeInd = true; + outInds << rep << "\t" << yr << "\t" << dem.repSeasons - 1; + } + else writeInd = false; } else { - outInds << "\t" << e.d0; + writeInd = true; + outInds << rep << "\t" << yr << "\t" << gen; } - } // end of if (emig.indVar) - - if (trfr.indVar) { - if (trfr.moveModel) { - if (trfr.moveType == 1) { // SMS - trfrSMSTraits s = inds[i]->getSMSTraits(); - outInds << "\t" << s.dp << "\t" << s.gb; - outInds << "\t" << s.alphaDB << "\t" << s.betaDB; - } // end of SMS - if (trfr.moveType == 2) { // CRW - trfrCRWTraits c = inds[i]->getCRWTraits(); - outInds << "\t" << c.stepLength << "\t" << c.rho; -#if RSDEBUG -//DEBUGLOG << "Population::outIndividual():" -// << " patchNum=" << patchNum << " i=" << i << " ID=" << inds[i]->getId() -// << " nTrfrGenes=" << nTrfrGenes << " loc[0][0].allele[0]=" << loc[0][0].allele[0] -// << endl; -#endif - } // end of CRW + } + if (writeInd) { + outInds << "\t" << spNum << "\t" << inds[i]->getId(); + if (dem.stageStruct) outInds << "\t" << ind.status; + else { // non-structured population + outInds << "\t" << ind.status; } - else { // kernel - trfrKernTraits k = inds[i]->getKernTraits(); - if (trfr.twinKern) - { - outInds << "\t" << k.meanDist1 << "\t" << k.meanDist2 << "\t" << k.probKern1; + pCell = inds[i]->getLocn(1); + locn loc; + if (pCell == 0) loc.x = loc.y = -1; // beyond boundary or in no-data cell + else loc = pCell->getLocn(); + pCell = inds[i]->getLocn(0); + locn natalloc = pCell->getLocn(); + //#if SEASONAL + // pCell = inds[i]->getLocn(2); + // locn prevloc = pCell->getLocn(); + //#endif + if (ppLand.patchModel) { + outInds << "\t" << inds[i]->getNatalPatch()->getPatchNum(); + if (loc.x == -1) outInds << "\t-1"; + else outInds << "\t" << patchNum; + } + else { // cell-based model + // EITHER write co-ordinates in cell units ... + outInds << "\t" << (float)natalloc.x << "\t" << natalloc.y; + outInds << "\t" << (float)loc.x << "\t" << (float)loc.y; + // ... OR write co-ordinates in real-world units + // outInds << "\t" << (float)natalloc.x * (float)ppLand.resol + (float)lim.minEast + // << "\t" << natalloc.y * (float)ppLand.resol + (float)lim.minNorth; + // outInds << "\t" << (float)loc.x * (float)ppLand.resol + (float)lim.minEast + // << "\t" << (float)loc.y * (float)ppLand.resol + (float)lim.minNorth; + } + if (dem.repType != 0) outInds << "\t" << ind.sex; + if (dem.stageStruct) outInds << "\t" << ind.age << "\t" << ind.stage; + + if (emig.indVar) { + emigTraits e = inds[i]->getEmigTraits(); + if (emig.densDep) { + outInds << "\t" << e.d0 << "\t" << e.alpha << "\t" << e.beta; } else { - outInds << "\t" << k.meanDist1; + outInds << "\t" << e.d0; + } + } // end of if (emig.indVar) + + if (trfr.indVar) { + if (trfr.moveModel) { + if (trfr.moveType == 1) { // SMS + trfrSMSTraits s = inds[i]->getSMSTraits(); + outInds << "\t" << s.dp << "\t" << s.gb; + outInds << "\t" << s.alphaDB << "\t" << s.betaDB; + } // end of SMS + if (trfr.moveType == 2) { // CRW + trfrCRWTraits c = inds[i]->getCRWTraits(); + outInds << "\t" << c.stepLength << "\t" << c.rho; +#if RSDEBUG + //DEBUGLOG << "Population::outIndividual():" + // << " patchNum=" << patchNum << " i=" << i << " ID=" << inds[i]->getId() + // << " nTrfrGenes=" << nTrfrGenes << " loc[0][0].allele[0]=" << loc[0][0].allele[0] + // << endl; +#endif + } // end of CRW + } + else { // kernel + trfrKernTraits k = inds[i]->getKernTraits(); + if (trfr.twinKern) + { + outInds << "\t" << k.meanDist1 << "\t" << k.meanDist2 << "\t" << k.probKern1; + } + else { + outInds << "\t" << k.meanDist1; + } } } - } - if (sett.indVar) { - settleTraits s = inds[i]->getSettTraits(); - outInds << "\t" << s.s0 << "\t" << s.alpha << "\t" << s.beta; - } + if (sett.indVar) { + settleTraits s = inds[i]->getSettTraits(); + outInds << "\t" << s.s0 << "\t" << s.alpha << "\t" << s.beta; + } - // distance moved (metres) - if (loc.x == -1) outInds << "\t-1"; - else { - float d = ppLand.resol * sqrt((float)((natalloc.x-loc.x)*(natalloc.x-loc.x) - + (natalloc.y-loc.y)*(natalloc.y-loc.y))); - outInds << "\t" << d; - } + // distance moved (metres) + if (loc.x == -1) outInds << "\t-1"; + else { + float d = ppLand.resol * sqrt((float)((natalloc.x - loc.x) * (natalloc.x - loc.x) + + (natalloc.y - loc.y) * (natalloc.y - loc.y))); + outInds << "\t" << d; + } #if RSDEBUG - // ALWAYS WRITE NO. OF STEPS - steps = inds[i]->getSteps(); - outInds << "\t" << steps.year; -#else - if (trfr.moveModel) { + // ALWAYS WRITE NO. OF STEPS steps = inds[i]->getSteps(); outInds << "\t" << steps.year; - } +#else + if (trfr.moveModel) { + steps = inds[i]->getSteps(); + outInds << "\t" << steps.year; + } #endif - outInds << endl; - } // end of writeInd condition + outInds << endl; + } // end of writeInd condition -} + } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Write records to genetics file -void Population::outGenetics(const int rep,const int year,const int landNr) +void Population::outGenetics(const int rep, const int year, const int landNr) { -simParams sim = paramsSim->getSim(); + simParams sim = paramsSim->getSim(); -if (landNr >= 0) { // open file - Genome *pGenome; - genomeData gen = pSpecies->getGenomeData(); - if (gen.trait1Chromosome) { - pGenome = new Genome(pSpecies->getNChromosomes(),pSpecies->getNLoci(0), - pSpecies->isDiploid()); - } - else { - pGenome = new Genome(pSpecies); + if (landNr >= 0) { // open file + Genome* pGenome; + genomeData gen = pSpecies->getGenomeData(); + if (gen.trait1Chromosome) { + pGenome = new Genome(pSpecies->getNChromosomes(), pSpecies->getNLoci(0), + pSpecies->isDiploid()); + } + else { + pGenome = new Genome(pSpecies); + } + pGenome->outGenHeaders(rep, landNr, sim.outGenXtab); + delete pGenome; + return; } - pGenome->outGenHeaders(rep,landNr,sim.outGenXtab); - delete pGenome; - return; -} -if (landNr == -999) { // close file - Genome *pGenome = new Genome(); - pGenome->outGenHeaders(rep,landNr,sim.outGenXtab); - delete pGenome; - return; -} + if (landNr == -999) { // close file + Genome* pGenome = new Genome(); + pGenome->outGenHeaders(rep, landNr, sim.outGenXtab); + delete pGenome; + return; + } -short spNum = pSpecies->getSpNum(); -short nstages = 1; -if (pSpecies->stageStructured()) { - stageParams sstruct = pSpecies->getStage(); - nstages = sstruct.nStages; -} + short spNum = pSpecies->getSpNum(); + short nstages = 1; + if (pSpecies->stageStructured()) { + stageParams sstruct = pSpecies->getStage(); + nstages = sstruct.nStages; + } -int ninds = (int)inds.size(); -for (int i = 0; i < ninds; i++) { - indStats ind = inds[i]->getStats(); - if (year == 0 || sim.outGenType == 1 - || (sim.outGenType == 0 && ind.stage == 0) - || (sim.outGenType == 2 && ind.stage == nstages-1)) { - inds[i]->outGenetics(rep,year,spNum,landNr,sim.outGenXtab); + int ninds = (int)inds.size(); + for (int i = 0; i < ninds; i++) { + indStats ind = inds[i]->getStats(); + if (year == 0 || sim.outGenType == 1 + || (sim.outGenType == 0 && ind.stage == 0) + || (sim.outGenType == 2 && ind.stage == nstages - 1)) { + inds[i]->outGenetics(rep, year, spNum, landNr, sim.outGenXtab); + } } -} } diff --git a/Population.h b/Population.h index 9c8efd8..561a429 100644 --- a/Population.h +++ b/Population.h @@ -1,58 +1,58 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ -RangeShifter v2.0 Population -Implements the Population class + /*------------------------------------------------------------------------------ -There is ONE instance of a Population for each Species within each SubCommunity -(including the matrix). The Population holds a list of all the Individuals in -the Population. + RangeShifter v2.0 Population -The matrix Population(s) hold(s) Individuals which are currently in the process -of transfer through the matrix. + Implements the Population class -For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. -and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. -Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 + There is ONE instance of a Population for each Species within each SubCommunity + (including the matrix). The Population holds a list of all the Individuals in + the Population. -Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + The matrix Population(s) hold(s) Individuals which are currently in the process + of transfer through the matrix. -Last updated: 22 January 2022 by Steve Palmer + For full details of RangeShifter, please see: + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. + and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial + eco-evolutionary dynamics and species’ responses to environmental changes. + Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 -------------------------------------------------------------------------------*/ + Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + + Last updated: 22 January 2022 by Steve Palmer + + ------------------------------------------------------------------------------*/ #ifndef PopulationH #define PopulationH #include #include -//#include -//#include -//#include + //#include + //#include + //#include using namespace std; #include "Parameters.h" @@ -65,10 +65,10 @@ using namespace std; //--------------------------------------------------------------------------- struct popStats { - Species *pSpecies; Patch *pPatch; int spNum,nInds,nNonJuvs,nAdults; bool breeding; + Species* pSpecies; Patch* pPatch; int spNum, nInds, nNonJuvs, nAdults; bool breeding; }; struct disperser { - Individual *pInd; Cell *pCell; bool yes; + Individual* pInd; Cell* pCell; bool yes; }; struct traitsums { // sums of trait genes for dispersal int ninds[NSEXES]; // no. of individuals @@ -177,8 +177,8 @@ class Population { void survival0( float, // local carrying capacity short, // option0: 0 - stage 0 (juveniles) only - // 1 - all stages - // 2 - stage 1 and above (all non-juveniles) + // 1 - all stages + // 2 - stage 1 and above (all non-juveniles) short // option1: 0 - development only (when survival is annual) // 1 - development and survival // 2 - survival only (when survival is annual) @@ -221,23 +221,23 @@ class Population { private: short nStages; short nSexes; - Species *pSpecies; // pointer to the species - Patch *pPatch; // pointer to the patch + Species* pSpecies; // pointer to the species + Patch* pPatch; // pointer to the patch int nInds[NSTAGES][NSEXES]; // no. of individuals in each stage/sex std::vector inds; // all individuals in population except ... std::vector juvs; // ... juveniles until reproduction of ALL species - // has been completed + // has been completed }; //--------------------------------------------------------------------------- -extern paramGrad *paramsGrad; -extern paramStoch *paramsStoch; -extern paramInit *paramsInit; -extern paramSim *paramsSim; -extern RSrandom *pRandom; +extern paramGrad* paramsGrad; +extern paramStoch* paramsStoch; +extern paramInit* paramsInit; +extern paramSim* paramsSim; +extern RSrandom* pRandom; #if RSDEBUG extern ofstream DEBUGLOG; diff --git a/RSrandom.cpp b/RSrandom.cpp index 79744c9..c4c569b 100644 --- a/RSrandom.cpp +++ b/RSrandom.cpp @@ -1,28 +1,28 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - + #include "RSrandom.h" -//--------------- 2.) New version of RSrandom.cpp + //--------------- 2.) New version of RSrandom.cpp #if !RS_RCPP @@ -39,73 +39,73 @@ int RS_random_seed = 0; RSrandom::RSrandom() { #if RSDEBUG - // fixed seed - RS_random_seed = 666; + // fixed seed + RS_random_seed = 666; #else - // random seed + // random seed #if LINUX_CLUSTER - std::random_device device; - RS_random_seed = device(); // old versions of g++ on Windows return a constant value within a given Windows - // session; in this case better use time stamp + std::random_device device; + RS_random_seed = device(); // old versions of g++ on Windows return a constant value within a given Windows + // session; in this case better use time stamp #else - RS_random_seed = std::time(NULL); + RS_random_seed = std::time(NULL); #endif #endif // RSDEBUG #if BATCH && RSDEBUG - DEBUGLOG << "RSrandom::RSrandom(): RS_random_seed=" << RS_random_seed << endl; + DEBUGLOG << "RSrandom::RSrandom(): RS_random_seed=" << RS_random_seed << endl; #endif // RSDEBUG - // set up Mersenne Twister RNG - gen = new mt19937(RS_random_seed); + // set up Mersenne Twister RNG + gen = new mt19937(RS_random_seed); - // Set up standard uniform distribution - pRandom01 = new uniform_real_distribution(0.0, 1.0); - // Set up standard normal distribution - pNormal = new normal_distribution(0.0, 1.0); + // Set up standard uniform distribution + pRandom01 = new uniform_real_distribution(0.0, 1.0); + // Set up standard normal distribution + pNormal = new normal_distribution(0.0, 1.0); } RSrandom::~RSrandom(void) { - delete gen; - if(pRandom01 != 0) - delete pRandom01; - if(pNormal != 0) - delete pNormal; + delete gen; + if (pRandom01 != 0) + delete pRandom01; + if (pNormal != 0) + delete pNormal; } mt19937 RSrandom::getRNG(void) { - return *gen; + return *gen; } double RSrandom::Random(void) { - // return random number between 0 and 1 - return pRandom01->operator()(*gen); + // return random number between 0 and 1 + return pRandom01->operator()(*gen); } int RSrandom::IRandom(int min, int max) { - // return random integer in the interval min <= x <= max - uniform_int_distribution unif(min, max); - return unif(*gen); + // return random integer in the interval min <= x <= max + uniform_int_distribution unif(min, max); + return unif(*gen); } int RSrandom::Bernoulli(double p) { - return Random() < p; + return Random() < p; } double RSrandom::Normal(double mean, double sd) { - return mean + sd * pNormal->operator()(*gen); + return mean + sd * pNormal->operator()(*gen); } int RSrandom::Poisson(double mean) { - poisson_distribution poiss(mean); - return poiss(*gen); + poisson_distribution poiss(mean); + return poiss(*gen); } @@ -116,140 +116,140 @@ int RSrandom::Poisson(double mean) //--------------- 3.) R package version of RSrandom.cpp - #if RSDEBUG - #include "Parameters.h" - extern paramSim *paramsSim; - //ofstream RSRANDOMLOG; - #endif - - std::uint32_t RS_random_seed = 0; - - // C'tor - // if parameter seed is negative, a random seed will be generated, else it is used as seed - RSrandom::RSrandom(std::int64_t seed) - { - // get seed - std::vector random_seed(3); - random_seed[0] = 1967593562; - random_seed[1] = 3271254416; - if (seed < 0) { - // random seed - #if RSWIN64 - random_seed[2] = std::time(NULL) + ( seed * (-17) ); - #else - std::random_device device; - random_seed[2] = device(); - #endif - #if BATCH && RSDEBUG - DEBUGLOG << "RSrandom::RSrandom(): Generated random seed = "; - #endif - } - else{ - // fixed seed - random_seed[2] = seed; - #if BATCH && RSDEBUG - DEBUGLOG << "RSrandom::RSrandom(): Use fixed seed = "; - #endif - } - - RS_random_seed = random_seed[2]; - #if BATCH && RSDEBUG - DEBUGLOG << RS_random_seed << endl; - #endif - - // set up Mersenne Twister random number generator with seed sequence - std::seed_seq seq(random_seed.begin(),random_seed.end()); - gen = new mt19937(seq); - - // Set up standard uniform distribution - pRandom01 = new uniform_real_distribution (0.0,1.0); - // Set up standard normal distribution - pNormal = new normal_distribution (0.0,1.0); - } +#if RSDEBUG +#include "Parameters.h" +extern paramSim* paramsSim; +//ofstream RSRANDOMLOG; +#endif - RSrandom::~RSrandom(void) { - delete gen; - if (pRandom01 != 0) delete pRandom01; - if (pNormal != 0) delete pNormal; - } +std::uint32_t RS_random_seed = 0; - mt19937 RSrandom::getRNG(void) { - // return random number generator - return *gen; +// C'tor +// if parameter seed is negative, a random seed will be generated, else it is used as seed +RSrandom::RSrandom(std::int64_t seed) +{ + // get seed + std::vector random_seed(3); + random_seed[0] = 1967593562; + random_seed[1] = 3271254416; + if (seed < 0) { + // random seed +#if RSWIN64 + random_seed[2] = std::time(NULL) + (seed * (-17)); +#else + std::random_device device; + random_seed[2] = device(); +#endif +#if BATCH && RSDEBUG + DEBUGLOG << "RSrandom::RSrandom(): Generated random seed = "; +#endif } - - double RSrandom::Random(void) { - // return random number between 0 and 1 - return pRandom01->operator()(*gen); + else { + // fixed seed + random_seed[2] = seed; +#if BATCH && RSDEBUG + DEBUGLOG << "RSrandom::RSrandom(): Use fixed seed = "; +#endif } - int RSrandom::IRandom(int min,int max) { - // return random integer in the interval min <= x <= max - uniform_int_distribution unif(min,max); - return unif(*gen); - } + RS_random_seed = random_seed[2]; +#if BATCH && RSDEBUG + DEBUGLOG << RS_random_seed << endl; +#endif - int RSrandom::Bernoulli(double p) { - return Random() < p; - } + // set up Mersenne Twister random number generator with seed sequence + std::seed_seq seq(random_seed.begin(), random_seed.end()); + gen = new mt19937(seq); - double RSrandom::Normal(double mean,double sd) { - return mean + sd * pNormal->operator()(*gen); - } + // Set up standard uniform distribution + pRandom01 = new uniform_real_distribution(0.0, 1.0); + // Set up standard normal distribution + pNormal = new normal_distribution(0.0, 1.0); +} - int RSrandom::Poisson(double mean) { - poisson_distribution poiss(mean); - return poiss(*gen); - } +RSrandom::~RSrandom(void) { + delete gen; + if (pRandom01 != 0) delete pRandom01; + if (pNormal != 0) delete pNormal; +} + +mt19937 RSrandom::getRNG(void) { + // return random number generator + return *gen; +} + +double RSrandom::Random(void) { + // return random number between 0 and 1 + return pRandom01->operator()(*gen); +} +int RSrandom::IRandom(int min, int max) { + // return random integer in the interval min <= x <= max + uniform_int_distribution unif(min, max); + return unif(*gen); +} + +int RSrandom::Bernoulli(double p) { + return Random() < p; +} + +double RSrandom::Normal(double mean, double sd) { + return mean + sd * pNormal->operator()(*gen); +} - /* ADDITIONAL DISTRIBUTIONS - - // Beta distribution - sample from two gamma distributions - double RSrandom::Beta(double p0,double p1) { - double g0,g1,beta; - if (p0 > 0.0 && p1 > 0.0) { // valid beta parameters - gamma_distribution gamma0(p0,1.0); - gamma_distribution gamma1(p1,1.0); - g0 = gamma0(*gen); - g1 = gamma1(*gen); - beta = g0 / (g0 + g1); - } - else { // return invalid value - beta = -666.0; - } - return beta; +int RSrandom::Poisson(double mean) { + poisson_distribution poiss(mean); + return poiss(*gen); +} + + +/* ADDITIONAL DISTRIBUTIONS + +// Beta distribution - sample from two gamma distributions +double RSrandom::Beta(double p0,double p1) { + double g0,g1,beta; + if (p0 > 0.0 && p1 > 0.0) { // valid beta parameters + gamma_distribution gamma0(p0,1.0); + gamma_distribution gamma1(p1,1.0); + g0 = gamma0(*gen); + g1 = gamma1(*gen); + beta = g0 / (g0 + g1); + } + else { // return invalid value + beta = -666.0; } + return beta; +} - // Gamma distribution - double RSrandom::Gamma(double p0,double p1) { // using shape (=p0) and scale (=p1) - double p2,gamma; - if (p0 > 0.0 && p1 > 0.0) { // valid gamma parameters - p2 = 1.0 / p1; - gamma_distribution gamma0(p0,p2); // using shape/alpha (=p0) and rate/beta (=p2=1/p1) - gamma = gamma0(*gen); - } - else { // return invalid value - gamma = -666.0; - } - return gamma; +// Gamma distribution +double RSrandom::Gamma(double p0,double p1) { // using shape (=p0) and scale (=p1) + double p2,gamma; + if (p0 > 0.0 && p1 > 0.0) { // valid gamma parameters + p2 = 1.0 / p1; + gamma_distribution gamma0(p0,p2); // using shape/alpha (=p0) and rate/beta (=p2=1/p1) + gamma = gamma0(*gen); + } + else { // return invalid value + gamma = -666.0; } +return gamma; +} - // Cauchy distribution - double RSrandom::Cauchy(double loc, double scale) { - double res; - if (scale > 0.0) { // valid scale parameter - cauchy_distribution cauchy(loc,scale); - res = cauchy(*gen); - } - else { // return invalid value - res = -666.0; - } - return res; +// Cauchy distribution +double RSrandom::Cauchy(double loc, double scale) { + double res; + if (scale > 0.0) { // valid scale parameter + cauchy_distribution cauchy(loc,scale); + res = cauchy(*gen); } + else { // return invalid value + res = -666.0; + } + return res; +} - */ +*/ #endif // RS_RCPP diff --git a/RSrandom.h b/RSrandom.h index 9293b29..8ad9a99 100644 --- a/RSrandom.h +++ b/RSrandom.h @@ -1,46 +1,46 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ -RangeShifter v2.0 RSrandom -Implements the RSrandom class + /*------------------------------------------------------------------------------ -Authors: Steve Palmer, University of Aberdeen - Anne-Kathleen Malchow, Potsdam University + RangeShifter v2.0 RSrandom -Last updated: 12 January 2021 by Steve Palmer + Implements the RSrandom class -------------------------------------------------------------------------------*/ + Authors: Steve Palmer, University of Aberdeen + Anne-Kathleen Malchow, Potsdam University + + Last updated: 12 January 2021 by Steve Palmer + + ------------------------------------------------------------------------------*/ #ifndef RSrandomH #define RSrandomH #include #include -//#include + //#include -//#if RS_RCPP && !R_CMD + //#if RS_RCPP && !R_CMD #include "../Version.h" //#endif @@ -61,30 +61,30 @@ extern ofstream DEBUGLOG; //--------------- 2.) New version of RSrandom.cpp - #include - #include - #if !LINUX_CLUSTER - #include - #endif +#include +#include +#if !LINUX_CLUSTER +#include +#endif - class RSrandom - { +class RSrandom +{ - public: - RSrandom(void); - ~RSrandom(void); - double Random(void); - int IRandom(int, int); - int Bernoulli(double); - double Normal(double, double); - int Poisson(double); - mt19937 getRNG(void); +public: + RSrandom(void); + ~RSrandom(void); + double Random(void); + int IRandom(int, int); + int Bernoulli(double); + double Normal(double, double); + int Poisson(double); + mt19937 getRNG(void); - private: - mt19937* gen; - std::uniform_real_distribution<>* pRandom01; - std::normal_distribution<>* pNormal; - }; +private: + mt19937* gen; + std::uniform_real_distribution<>* pRandom01; + std::normal_distribution<>* pNormal; +}; //-------------------------------------------------------------------------------------------------- @@ -98,34 +98,34 @@ extern ofstream DEBUGLOG; #else // if RS_RCPP - #include - #include - #if RSWIN64 - #include - #endif - - class RSrandom { +#include +#include +#if RSWIN64 +#include +#endif - public: - RSrandom(std::int64_t); // if int is negative, a random seed will be generated, else it is used as seed - ~RSrandom(void); - mt19937 getRNG(void); - double Random(void); - int IRandom(int,int); - int Bernoulli(double); - double Normal(double,double); - int Poisson(double); +class RSrandom { + +public: + RSrandom(std::int64_t); // if int is negative, a random seed will be generated, else it is used as seed + ~RSrandom(void); + mt19937 getRNG(void); + double Random(void); + int IRandom(int, int); + int Bernoulli(double); + double Normal(double, double); + int Poisson(double); /* ADDITIONAL DISTRIBUTIONS double Beta(double,double); double Gamma(double,double); // !! make sure correct definition is used: using shape and scale (as defined here) OR using shape/alpha and rate/beta (=1/scale) double Cauchy(double,double); */ - private: - mt19937 *gen; - std::uniform_real_distribution<> *pRandom01; - std::normal_distribution<> *pNormal; - }; +private: + mt19937* gen; + std::uniform_real_distribution<>* pRandom01; + std::normal_distribution<>* pNormal; +}; diff --git a/RandomCheck.cpp b/RandomCheck.cpp index e18aeaa..8468958 100644 --- a/RandomCheck.cpp +++ b/RandomCheck.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "RandomCheck.h" //--------------------------------------------------------------------------- @@ -35,17 +35,17 @@ ofstream outIRandom; void randomCheck(void) { -int samplesize,irandMin,irandMax; -double bernMean,normMean,normSD,poisMean; -string name,header; -simParams sim = paramsSim->getSim(); + int samplesize, irandMin, irandMax; + double bernMean, normMean, normSD, poisMean; + string name, header; + simParams sim = paramsSim->getSim(); name = paramsSim->getDir(1) + "RandomCheck.txt"; inRandom.open(name.c_str()); if (!inRandom.is_open()) { - #if !RS_RCPP +#if !RS_RCPP cout << endl << "***** Error opening input file RandomCheck.txt" << endl; - #endif +#endif inRandom.clear(); return; } @@ -68,9 +68,9 @@ simParams sim = paramsSim->getSim(); for (int i = 0; i < samplesize; i++) { outRandom << pRandom->Random() << endl; outBernoulli << pRandom->Bernoulli(bernMean) << endl; - outNormal << pRandom->Normal(normMean,normSD) << endl; + outNormal << pRandom->Normal(normMean, normSD) << endl; outPoisson << pRandom->Poisson(poisMean) << endl; - outIRandom << pRandom->IRandom(irandMin,irandMax) << endl; + outIRandom << pRandom->IRandom(irandMin, irandMax) << endl; } inRandom.close(); diff --git a/RandomCheck.h b/RandomCheck.h index b4f6f01..69e1128 100644 --- a/RandomCheck.h +++ b/RandomCheck.h @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #ifndef RandomCheckH #define RandomCheckH @@ -40,8 +40,8 @@ using namespace std; void randomCheck(void); -extern paramSim *paramsSim; -extern RSrandom *pRandom; +extern paramSim* paramsSim; +extern RSrandom* pRandom; //--------------------------------------------------------------------------- #endif diff --git a/Species.cpp b/Species.cpp index 727e3c3..75e9b92 100644 --- a/Species.cpp +++ b/Species.cpp @@ -1,154 +1,154 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Species.h" //--------------------------------------------------------------------------- Species::Species(void) { -// initialise demographic parameters -repType = 0; nStages = 2; -stageStruct = false; -propMales = 0.5; harem = 1.0; bc = 1.0; lambda = 1.5; probRep = 1.0; -repSeasons = 1; -repInterval = 0; maxAge = 1000; survival = 1; -fecDens = false; fecStageDens = false; -devDens = false; devStageDens = false; -survDens = false; survStageDens = false; -disperseOnLoss = false; -for (int i = 0; i < NSTAGES; i++) { - for (int j = 0; j < NSEXES; j++) { - fec[i][j] = 0.0; dev[i][j] = 0.0; surv[i][j] = 0.0; - minAge[i][j] = 0; - } -} -devCoeff = survCoeff = 1.0; -ddwtFec = ddwtDev = ddwtSurv = 0; ddwtFecDim = ddwtDevDim = ddwtSurvDim = 0; -habK = 0; habDimK = 0; -minRK = 1.0; maxRK = 2.0; - -// initialise genome attributes -nChromosomes = nTraits = 0; -emigTrait[0] = 0; emigTrait[1] = 0; -movtTrait[0] = 0; movtTrait[1] = 0; -settTrait[0] = 0; settTrait[1] = 0; -//genomeCanRecombine = false; -diploid = true; -neutralMarkers = false; -pleiotropic = false; -trait1Chromosome = true; -probMutn = 0.0001f; -probCrossover = 0.0001f; -alleleSD = mutationSD = 0.1f; -nNLoci = 0; -nLoci = NULL; -traitdata = NULL; -traitnames = NULL; -nTraitNames = 0; - -// initialise emigration parameters -densDepEmig = false; stgDepEmig = false; sexDepEmig = false; indVarEmig = false; -emigStage = 0; -for (int i = 0; i < NSTAGES; i++) { + // initialise demographic parameters + repType = 0; nStages = 2; + stageStruct = false; + propMales = 0.5; harem = 1.0; bc = 1.0; lambda = 1.5; probRep = 1.0; + repSeasons = 1; + repInterval = 0; maxAge = 1000; survival = 1; + fecDens = false; fecStageDens = false; + devDens = false; devStageDens = false; + survDens = false; survStageDens = false; + disperseOnLoss = false; + for (int i = 0; i < NSTAGES; i++) { + for (int j = 0; j < NSEXES; j++) { + fec[i][j] = 0.0; dev[i][j] = 0.0; surv[i][j] = 0.0; + minAge[i][j] = 0; + } + } + devCoeff = survCoeff = 1.0; + ddwtFec = ddwtDev = ddwtSurv = 0; ddwtFecDim = ddwtDevDim = ddwtSurvDim = 0; + habK = 0; habDimK = 0; + minRK = 1.0; maxRK = 2.0; + + // initialise genome attributes + nChromosomes = nTraits = 0; + emigTrait[0] = 0; emigTrait[1] = 0; + movtTrait[0] = 0; movtTrait[1] = 0; + settTrait[0] = 0; settTrait[1] = 0; + //genomeCanRecombine = false; + diploid = true; + neutralMarkers = false; + pleiotropic = false; + trait1Chromosome = true; + probMutn = 0.0001f; + probCrossover = 0.0001f; + alleleSD = mutationSD = 0.1f; + nNLoci = 0; + nLoci = NULL; + traitdata = NULL; + traitnames = NULL; + nTraitNames = 0; + + // initialise emigration parameters + densDepEmig = false; stgDepEmig = false; sexDepEmig = false; indVarEmig = false; + emigStage = 0; + for (int i = 0; i < NSTAGES; i++) { + for (int j = 0; j < NSEXES; j++) { + d0[i][j] = 0.0; alphaEmig[i][j] = 0.0; betaEmig[i][j] = 1.0; + } + } for (int j = 0; j < NSEXES; j++) { - d0[i][j] = 0.0; alphaEmig[i][j] = 0.0; betaEmig[i][j] = 1.0; + d0Mean[0][j] = 0.0; alphaMean[0][j] = 0.0; betaMean[0][j] = 1.0; + d0SD[0][j] = 0.0; alphaSD[0][j] = 0.0; betaSD[0][j] = 1.0; + } + d0Scale = alphaScale = betaScale = 0.0; + + // initialise transfer parameters + moveModel = false; stgDepTrfr = false; sexDepTrfr = false; distMort = false; + indVarTrfr = false; + twinKern = false; + habMort = false; + costMap = false; + moveType = 1; + for (int i = 0; i < NSTAGES; i++) { + for (int j = 0; j < NSEXES; j++) { + meanDist1[i][j] = 100.0f; meanDist2[i][j] = 1000.0f; probKern1[i][j] = 0.99f; + } } -} -for (int j = 0; j < NSEXES; j++) { - d0Mean[0][j] = 0.0; alphaMean[0][j] = 0.0; betaMean[0][j] = 1.0; - d0SD[0][j] = 0.0; alphaSD[0][j] = 0.0; betaSD[0][j] = 1.0; -} -d0Scale = alphaScale = betaScale = 0.0; - -// initialise transfer parameters -moveModel = false; stgDepTrfr = false; sexDepTrfr = false; distMort = false; -indVarTrfr = false; -twinKern = false; -habMort = false; -costMap = false; -moveType = 1; -for (int i = 0; i < NSTAGES; i++) { for (int j = 0; j < NSEXES; j++) { - meanDist1[i][j] = 100.0f; meanDist2[i][j] = 1000.0f; probKern1[i][j] = 0.99f; - } -} -for (int j = 0; j < NSEXES; j++) { - dist1Mean[0][j] = 100.0; dist1SD[0][j] = 10.0; - dist2Mean[0][j] = 1000.0; dist2SD[0][j] = 100.0; - PKern1Mean[0][j] = 0.9f; PKern1SD[0][j] = 0.01f; - stepLgthMean[0][j] = 10.0; stepLgthSD[0][j] = 1.0; - rhoMean[0][j] = 0.9f; rhoSD[0][j] = 0.01f; - dpMean[0][j] = 1.0; dpSD[0][j] = 0.1f; - gbMean[0][j] = 1.0; gbSD[0][j] = 0.1f; - alphaDBMean[0][j] = 1.0; alphaDBSD[0][j] = 0.1f; - betaDBMean[0][j] = 10.0; betaDBSD[0][j] = 1.0; -} -pr = 1; prMethod = 1; memSize = 1; goalType = 0; -dp = 1.0; gb = 1.0; alphaDB = 1.0; betaDB = 100000; -stepMort = 0.0; stepLength = 10.0; rho = 0.9f; -habStepMort = 0; habCost = 0; -//costMapFile = "NULL"; -fixedMort = 0.0; mortAlpha = 0.0; mortBeta = 1.0; -dist1Scale = dist2Scale = PKern1Scale = stepLScale = rhoScale = 0.0; -dpScale = 0.1f; gbScale = 0.1f; alphaDBScale = 0.1f; betaDBScale = 1.0; -habDimTrfr = 0; -straigtenPath = false; -fullKernel = false; - -// initialise settlement parameters -stgDepSett = false; sexDepSett = false; indVarSett = false; -minSteps = 0; maxSteps = 99999999; -for (int i = 0; i < NSTAGES; i++) { + dist1Mean[0][j] = 100.0; dist1SD[0][j] = 10.0; + dist2Mean[0][j] = 1000.0; dist2SD[0][j] = 100.0; + PKern1Mean[0][j] = 0.9f; PKern1SD[0][j] = 0.01f; + stepLgthMean[0][j] = 10.0; stepLgthSD[0][j] = 1.0; + rhoMean[0][j] = 0.9f; rhoSD[0][j] = 0.01f; + dpMean[0][j] = 1.0; dpSD[0][j] = 0.1f; + gbMean[0][j] = 1.0; gbSD[0][j] = 0.1f; + alphaDBMean[0][j] = 1.0; alphaDBSD[0][j] = 0.1f; + betaDBMean[0][j] = 10.0; betaDBSD[0][j] = 1.0; + } + pr = 1; prMethod = 1; memSize = 1; goalType = 0; + dp = 1.0; gb = 1.0; alphaDB = 1.0; betaDB = 100000; + stepMort = 0.0; stepLength = 10.0; rho = 0.9f; + habStepMort = 0; habCost = 0; + //costMapFile = "NULL"; + fixedMort = 0.0; mortAlpha = 0.0; mortBeta = 1.0; + dist1Scale = dist2Scale = PKern1Scale = stepLScale = rhoScale = 0.0; + dpScale = 0.1f; gbScale = 0.1f; alphaDBScale = 0.1f; betaDBScale = 1.0; + habDimTrfr = 0; + straigtenPath = false; + fullKernel = false; + + // initialise settlement parameters + stgDepSett = false; sexDepSett = false; indVarSett = false; + minSteps = 0; maxSteps = 99999999; + for (int i = 0; i < NSTAGES; i++) { + for (int j = 0; j < NSEXES; j++) { + densDepSett[i][j] = false; wait[i][j] = false; go2nbrLocn[i][j] = false; findMate[i][j] = false; + maxStepsYr[i][j] = 99999999; + s0[i][j] = 1.0; alphaS[i][j] = 0.0; betaS[i][j] = 1.0; + } + } for (int j = 0; j < NSEXES; j++) { - densDepSett[i][j] = false; wait[i][j] = false; go2nbrLocn[i][j] = false; findMate[i][j] = false; - maxStepsYr[i][j] = 99999999; - s0[i][j] = 1.0; alphaS[i][j] = 0.0; betaS[i][j] = 1.0; + alphaSMean[0][j] = 0.0; alphaSSD[0][j] = 0.0; + betaSMean[0][j] = 0.0; betaSSD[0][j] = 0.0; + s0Mean[0][j] = 0.0; s0SD[0][j] = 0.0; } -} -for (int j = 0; j < NSEXES; j++) { - alphaSMean[0][j] = 0.0; alphaSSD[0][j] = 0.0; - betaSMean[0][j] = 0.0; betaSSD[0][j] = 0.0; - s0Mean[0][j] = 0.0; s0SD[0][j] = 0.0; -} -alphaSScale = 0.0; betaSScale = 0.0; s0Scale = 0.0; + alphaSScale = 0.0; betaSScale = 0.0; s0Scale = 0.0; -// initialise attributes -spNum = 0; + // initialise attributes + spNum = 0; } Species::~Species() { -// demographic parameters -if (habK != NULL) deleteHabK(); -if (ddwtFec != 0) deleteDDwtFec(); -if (ddwtDev != 0) deleteDDwtDev(); -if (ddwtSurv != 0) deleteDDwtSurv(); -// transfer parameters -if (habCost != 0 || habStepMort != 0) deleteHabCostMort(); -if (nLoci != NULL) deleteLoci(); -if (traitdata != NULL) deleteTraitData(); -if (traitnames != NULL) deleteTraitNames(); + // demographic parameters + if (habK != NULL) deleteHabK(); + if (ddwtFec != 0) deleteDDwtFec(); + if (ddwtDev != 0) deleteDDwtDev(); + if (ddwtSurv != 0) deleteDDwtSurv(); + // transfer parameters + if (habCost != 0 || habStepMort != 0) deleteHabCostMort(); + if (nLoci != NULL) deleteLoci(); + if (traitdata != NULL) deleteTraitData(); + if (traitnames != NULL) deleteTraitNames(); } short Species::getSpNum(void) { return spNum; } @@ -158,25 +158,25 @@ short Species::getSpNum(void) { return spNum; } // Demographic functions void Species::setDemogr(const demogrParams d) { -if (d.repType >= 0 && d.repType <= 2) repType = d.repType; -if (d.repSeasons >= 1) repSeasons = d.repSeasons; -stageStruct = d.stageStruct; -if (d.propMales > 0.0 && d.propMales < 1.0) propMales = d.propMales; -if (d.harem > 0.0) harem = d.harem; -if (d.bc > 0.0) bc = d.bc; -if (d.lambda > 0.0) lambda = d.lambda; + if (d.repType >= 0 && d.repType <= 2) repType = d.repType; + if (d.repSeasons >= 1) repSeasons = d.repSeasons; + stageStruct = d.stageStruct; + if (d.propMales > 0.0 && d.propMales < 1.0) propMales = d.propMales; + if (d.harem > 0.0) harem = d.harem; + if (d.bc > 0.0) bc = d.bc; + if (d.lambda > 0.0) lambda = d.lambda; } demogrParams Species::getDemogr(void) { -demogrParams d; -d.repType = repType; -d.repSeasons = repSeasons; -d.stageStruct = stageStruct; -d.propMales = propMales; -d.harem = harem; -d.bc = bc; -d.lambda = lambda; -return d; + demogrParams d; + d.repType = repType; + d.repSeasons = repSeasons; + d.stageStruct = stageStruct; + d.propMales = propMales; + d.harem = harem; + d.bc = bc; + d.lambda = lambda; + return d; } short Species::getRepType(void) { return repType; } @@ -184,237 +184,237 @@ short Species::getRepType(void) { return repType; } bool Species::stageStructured(void) { return stageStruct; } void Species::createHabK(short nhab) { -if (nhab >= 0) { - habDimK = nhab; - if (habK != 0) deleteHabK(); - habK = new float[nhab]; - for (int i = 0; i < nhab; i++) habK[i] = 0.0; -} + if (nhab >= 0) { + habDimK = nhab; + if (habK != 0) deleteHabK(); + habK = new float[nhab]; + for (int i = 0; i < nhab; i++) habK[i] = 0.0; + } } -void Species::setHabK(short hx,float k) { -if (hx >= 0 && hx < habDimK) { - if (k >= 0.0) habK[hx] = k; -} +void Species::setHabK(short hx, float k) { + if (hx >= 0 && hx < habDimK) { + if (k >= 0.0) habK[hx] = k; + } } float Species::getHabK(short hx) { -float k = 0.0; -if (hx >= 0 && hx < habDimK) k = habK[hx]; -return k; + float k = 0.0; + if (hx >= 0 && hx < habDimK) k = habK[hx]; + return k; } float Species::getMaxK(void) { -float k = 0.0; -for (int i = 0; i < habDimK; i++) { - if (habK[i] > k) k = habK[i]; -} -return k; + float k = 0.0; + for (int i = 0; i < habDimK; i++) { + if (habK[i] > k) k = habK[i]; + } + return k; } void Species::deleteHabK(void) { -if (habK != 0) { - delete[] habK; habK = 0; -} + if (habK != 0) { + delete[] habK; habK = 0; + } } void Species::setStage(const stageParams s) { -if (s.nStages > 1) nStages = s.nStages; -if (s.repInterval >= 0) repInterval = s.repInterval; -if (s.maxAge >= 1) maxAge = s.maxAge; -if (s.survival >= 0 && s.survival <= 2) survival = s.survival; -if (s.probRep > 0.0 && s.probRep <= 1.0) probRep = s.probRep; -fecDens = s.fecDens; fecStageDens = s.fecStageDens; -devDens = s.devDens; devStageDens = s.devStageDens; -survDens = s.survDens; survStageDens = s.survStageDens; -disperseOnLoss = s.disperseOnLoss; + if (s.nStages > 1) nStages = s.nStages; + if (s.repInterval >= 0) repInterval = s.repInterval; + if (s.maxAge >= 1) maxAge = s.maxAge; + if (s.survival >= 0 && s.survival <= 2) survival = s.survival; + if (s.probRep > 0.0 && s.probRep <= 1.0) probRep = s.probRep; + fecDens = s.fecDens; fecStageDens = s.fecStageDens; + devDens = s.devDens; devStageDens = s.devStageDens; + survDens = s.survDens; survStageDens = s.survStageDens; + disperseOnLoss = s.disperseOnLoss; } stageParams Species::getStage(void) { -stageParams s; -s.nStages = nStages; s.repInterval = repInterval; s.maxAge = maxAge; -s.survival = survival; s.probRep = probRep; -s.fecDens = fecDens; s.fecStageDens = fecStageDens; -s.devDens = devDens; s.devStageDens = devStageDens; -s.survDens = survDens; s.survStageDens = survStageDens; -s.disperseOnLoss = disperseOnLoss; -return s; + stageParams s; + s.nStages = nStages; s.repInterval = repInterval; s.maxAge = maxAge; + s.survival = survival; s.probRep = probRep; + s.fecDens = fecDens; s.fecStageDens = fecStageDens; + s.devDens = devDens; s.devStageDens = devStageDens; + s.survDens = survDens; s.survStageDens = survStageDens; + s.disperseOnLoss = disperseOnLoss; + return s; } -void Species::setFec(short stg,short sex,float f) { -// NB fecundity for stage 0 must always be zero -if (stg > 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES && f >= 0) - fec[stg][sex] = f; +void Species::setFec(short stg, short sex, float f) { + // NB fecundity for stage 0 must always be zero + if (stg > 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES && f >= 0) + fec[stg][sex] = f; } -float Species::getFec(short stg,short sex) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - return fec[stg][sex]; -else return 0.0; +float Species::getFec(short stg, short sex) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + return fec[stg][sex]; + else return 0.0; } float Species::getMaxFec(void) { -float maxfec = 0.0; -if (stageStruct) { - for (int stg = 1; stg < NSTAGES; stg++) { - if (fec[stg][0] > maxfec) maxfec = fec[stg][0]; + float maxfec = 0.0; + if (stageStruct) { + for (int stg = 1; stg < NSTAGES; stg++) { + if (fec[stg][0] > maxfec) maxfec = fec[stg][0]; + } } -} -else maxfec = lambda; -return maxfec; + else maxfec = lambda; + return maxfec; } -void Species::setDev(short stg,short sex,float d) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES && d >= 0) - dev[stg][sex] = d; +void Species::setDev(short stg, short sex, float d) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES && d >= 0) + dev[stg][sex] = d; } -float Species::getDev(short stg,short sex) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - return dev[stg][sex]; -else return 0.0; +float Species::getDev(short stg, short sex) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + return dev[stg][sex]; + else return 0.0; } -void Species::setSurv(short stg,short sex,float s) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES && s >= 0) - surv[stg][sex] = s; +void Species::setSurv(short stg, short sex, float s) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES && s >= 0) + surv[stg][sex] = s; } -float Species::getSurv(short stg,short sex) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - return surv[stg][sex]; -else return 0.0; +float Species::getSurv(short stg, short sex) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + return surv[stg][sex]; + else return 0.0; } -void Species::setMinAge(short stg,short sex,int age) { -// NB min age for stages 0 & 1 must always be zero -if (stg > 1 && stg < NSTAGES && sex >= 0 && sex < NSEXES && age >= 0) - minAge[stg][sex] = age; +void Species::setMinAge(short stg, short sex, int age) { + // NB min age for stages 0 & 1 must always be zero + if (stg > 1 && stg < NSTAGES && sex >= 0 && sex < NSEXES && age >= 0) + minAge[stg][sex] = age; } -short Species::getMinAge(short stg,short sex) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - return minAge[stg][sex]; -else return 0; +short Species::getMinAge(short stg, short sex) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + return minAge[stg][sex]; + else return 0; } void Species::setDensDep(float d, float s) { -if (d > 0.0) devCoeff = d; -if (s > 0.0) survCoeff = s; + if (d > 0.0) devCoeff = d; + if (s > 0.0) survCoeff = s; } densDepParams Species::getDensDep(void) { -densDepParams d; -d.devCoeff = devCoeff; d.survCoeff = survCoeff; -return d; + densDepParams d; + d.devCoeff = devCoeff; d.survCoeff = survCoeff; + return d; } void Species::createDDwtFec(short mSize) { -if (mSize >= 0 && mSize < (NSTAGES * NSEXES)) { - if (ddwtFec != 0) deleteDDwtFec(); - ddwtFecDim = mSize; - ddwtFec = new float *[mSize]; - for (int i = 0; i < mSize; i++) { - ddwtFec[i] = new float[mSize]; - for (int j = 0; j < mSize; j++) ddwtFec[i][j] = 1.0; + if (mSize >= 0 && mSize < (NSTAGES * NSEXES)) { + if (ddwtFec != 0) deleteDDwtFec(); + ddwtFecDim = mSize; + ddwtFec = new float* [mSize]; + for (int i = 0; i < mSize; i++) { + ddwtFec[i] = new float[mSize]; + for (int j = 0; j < mSize; j++) ddwtFec[i][j] = 1.0; + } } } -} -void Species::setDDwtFec(short row,short col,float f) { -if (row >= 0 && row < ddwtFecDim && col >= 0 && col < ddwtFecDim) - ddwtFec[row][col] = f; +void Species::setDDwtFec(short row, short col, float f) { + if (row >= 0 && row < ddwtFecDim && col >= 0 && col < ddwtFecDim) + ddwtFec[row][col] = f; } -float Species::getDDwtFec(short row,short col) { -if (row >= 0 && row < ddwtFecDim && col >= 0 && col < ddwtFecDim) - return ddwtFec[row][col]; -else return 0.0; +float Species::getDDwtFec(short row, short col) { + if (row >= 0 && row < ddwtFecDim && col >= 0 && col < ddwtFecDim) + return ddwtFec[row][col]; + else return 0.0; } void Species::deleteDDwtFec(void) { -if (ddwtFec != 0) { - for (int i = 0; i < ddwtFecDim; i++) if (ddwtFec[i] != 0) { - delete[] ddwtFec[i]; + if (ddwtFec != 0) { + for (int i = 0; i < ddwtFecDim; i++) if (ddwtFec[i] != 0) { + delete[] ddwtFec[i]; + } + delete[] ddwtFec; ddwtFec = 0; } - delete[] ddwtFec; ddwtFec = 0; -} } void Species::createDDwtDev(short mSize) { -if (mSize >= 0 && mSize < (NSTAGES * NSEXES)) { - if (ddwtDev != 0) deleteDDwtDev(); - ddwtDevDim = mSize; - ddwtDev = new float *[mSize]; - for (int i = 0; i < mSize; i++) { - ddwtDev[i] = new float[mSize]; - for (int j = 0; j < mSize; j++) ddwtDev[i][j] = 1.0; + if (mSize >= 0 && mSize < (NSTAGES * NSEXES)) { + if (ddwtDev != 0) deleteDDwtDev(); + ddwtDevDim = mSize; + ddwtDev = new float* [mSize]; + for (int i = 0; i < mSize; i++) { + ddwtDev[i] = new float[mSize]; + for (int j = 0; j < mSize; j++) ddwtDev[i][j] = 1.0; + } } } -} -void Species::setDDwtDev(short row,short col,float f) { -if (row >= 0 && row < ddwtDevDim && col >= 0 && col < ddwtDevDim) - ddwtDev[row][col] = f; +void Species::setDDwtDev(short row, short col, float f) { + if (row >= 0 && row < ddwtDevDim && col >= 0 && col < ddwtDevDim) + ddwtDev[row][col] = f; } -float Species::getDDwtDev(short row,short col) { -if (row >= 0 && row < ddwtDevDim && col >= 0 && col < ddwtDevDim) - return ddwtDev[row][col]; -else return 0.0; +float Species::getDDwtDev(short row, short col) { + if (row >= 0 && row < ddwtDevDim && col >= 0 && col < ddwtDevDim) + return ddwtDev[row][col]; + else return 0.0; } void Species::deleteDDwtDev(void) { -if (ddwtDev != 0) { - for (int i = 0; i < ddwtDevDim; i++) if (ddwtDev[i] != 0) { - delete[] ddwtDev[i]; + if (ddwtDev != 0) { + for (int i = 0; i < ddwtDevDim; i++) if (ddwtDev[i] != 0) { + delete[] ddwtDev[i]; + } + delete[] ddwtDev; ddwtDev = 0; } - delete[] ddwtDev; ddwtDev = 0; -} } void Species::createDDwtSurv(short mSize) { -if (mSize >= 0 && mSize < (NSTAGES * NSEXES)) { - if (ddwtSurv != 0) deleteDDwtSurv(); - ddwtSurvDim = mSize; - ddwtSurv = new float *[mSize]; - for (int i = 0; i < mSize; i++) { - ddwtSurv[i] = new float[mSize] ; - for (int j = 0; j < mSize; j++) ddwtSurv[i][j] = 1.0; + if (mSize >= 0 && mSize < (NSTAGES * NSEXES)) { + if (ddwtSurv != 0) deleteDDwtSurv(); + ddwtSurvDim = mSize; + ddwtSurv = new float* [mSize]; + for (int i = 0; i < mSize; i++) { + ddwtSurv[i] = new float[mSize]; + for (int j = 0; j < mSize; j++) ddwtSurv[i][j] = 1.0; + } } } -} -void Species::setDDwtSurv(short row,short col, float f) { -if (row >= 0 && row < ddwtSurvDim && col >= 0 && col < ddwtSurvDim) - ddwtSurv[row][col] = f; +void Species::setDDwtSurv(short row, short col, float f) { + if (row >= 0 && row < ddwtSurvDim && col >= 0 && col < ddwtSurvDim) + ddwtSurv[row][col] = f; } -float Species::getDDwtSurv(short row,short col) { -if (row >= 0 && row < ddwtSurvDim && col >= 0 && col < ddwtSurvDim) - return ddwtSurv[row][col]; -else return 0.0; +float Species::getDDwtSurv(short row, short col) { + if (row >= 0 && row < ddwtSurvDim && col >= 0 && col < ddwtSurvDim) + return ddwtSurv[row][col]; + else return 0.0; } void Species::deleteDDwtSurv(void) { -if (ddwtSurv != 0) { - for (int i = 0; i < ddwtSurvDim; i++) if (ddwtSurv[i] != 0) { - delete[] ddwtSurv[i]; + if (ddwtSurv != 0) { + for (int i = 0; i < ddwtSurvDim; i++) if (ddwtSurv[i] != 0) { + delete[] ddwtSurv[i]; + } + delete[] ddwtSurv; ddwtSurv = 0; } - delete[] ddwtSurv; ddwtSurv = 0; -} } // Functions to handle min/max R or K (under environmental stochasticity) //void Species::setMinMax(float min,float max) { -void Species::setMinMax(float min, float max) { -if (min >= 0.0 && max > min) { - minRK = min; maxRK = max; -} +void Species::setMinMax(float min, float max) { + if (min >= 0.0 && max > min) { + minRK = min; maxRK = max; + } } float Species::getMinMax(short opt) { -if (opt == 0) return minRK; -else return maxRK; + if (opt == 0) return minRK; + else return maxRK; } //--------------------------------------------------------------------------- @@ -422,31 +422,31 @@ else return maxRK; // Genome functions void Species::setGenomeData(genomeData d) { -diploid = d.diploid; -neutralMarkers = d.neutralMarkers; -trait1Chromosome = d.trait1Chromosome; -if (trait1Chromosome) { - if (d.nLoci > 0) nLoci[0] = d.nLoci; -} -if (d.probMutn >= 0.0 && d.probMutn <= 1.0) probMutn = d.probMutn; -if (d.probCrossover >= 0.0 && d.probCrossover <= 1.0) probCrossover = d.probCrossover; -if (d.alleleSD > 0.0) alleleSD = d.alleleSD; -if (d.mutationSD > 0.0) mutationSD = d.mutationSD; + diploid = d.diploid; + neutralMarkers = d.neutralMarkers; + trait1Chromosome = d.trait1Chromosome; + if (trait1Chromosome) { + if (d.nLoci > 0) nLoci[0] = d.nLoci; + } + if (d.probMutn >= 0.0 && d.probMutn <= 1.0) probMutn = d.probMutn; + if (d.probCrossover >= 0.0 && d.probCrossover <= 1.0) probCrossover = d.probCrossover; + if (d.alleleSD > 0.0) alleleSD = d.alleleSD; + if (d.mutationSD > 0.0) mutationSD = d.mutationSD; } genomeData Species::getGenomeData(void) { -genomeData d; -d.diploid = diploid; -d.neutralMarkers = neutralMarkers; -d.pleiotropic = pleiotropic; -d.trait1Chromosome = trait1Chromosome; -if (nLoci != NULL) d.nLoci = nLoci[0]; -else d.nLoci = 0; -d.probMutn = probMutn; -d.probCrossover = probCrossover; -d.alleleSD = alleleSD; -d.mutationSD = mutationSD; -return d; + genomeData d; + d.diploid = diploid; + d.neutralMarkers = neutralMarkers; + d.pleiotropic = pleiotropic; + d.trait1Chromosome = trait1Chromosome; + if (nLoci != NULL) d.nLoci = nLoci[0]; + else d.nLoci = 0; + d.probMutn = probMutn; + d.probCrossover = probCrossover; + d.alleleSD = alleleSD; + d.mutationSD = mutationSD; + return d; } bool Species::isDiploid(void) { return diploid; } @@ -454,42 +454,42 @@ bool Species::isDiploid(void) { return diploid; } // Chromosome functions void Species::setNChromosomes(int c) { -if (nLoci != NULL) deleteLoci(); -if (c > 0) { - nChromosomes = nNLoci = c; - nLoci = new short [c]; - for (int i = 0; i < nNLoci; i++) nLoci[i] = 0; -} -else nChromosomes = nNLoci = 0; + if (nLoci != NULL) deleteLoci(); + if (c > 0) { + nChromosomes = nNLoci = c; + nLoci = new short[c]; + for (int i = 0; i < nNLoci; i++) nLoci[i] = 0; + } + else nChromosomes = nNLoci = 0; } int Species::getNChromosomes(void) { return nChromosomes; } -void Species::setNLoci(const short chr,const short nloc) { -if (chr >= 0 && chr < nNLoci) { - if (nloc > 0) nLoci[chr] = nloc; - else nLoci[chr] = 0; -} +void Species::setNLoci(const short chr, const short nloc) { + if (chr >= 0 && chr < nNLoci) { + if (nloc > 0) nLoci[chr] = nloc; + else nLoci[chr] = 0; + } } int Species::getNLoci(const short chr) { -if (chr >= 0 && chr < nChromosomes) return nLoci[chr]; -else return 0; + if (chr >= 0 && chr < nChromosomes) return nLoci[chr]; + else return 0; } void Species::deleteLoci(void) { -if (nLoci != NULL) { delete[] nLoci; nLoci = NULL; } + if (nLoci != NULL) { delete[] nLoci; nLoci = NULL; } } // Trait functions // Set 1:1 mapping of trait to chromosome void Species::set1ChromPerTrait(const int nloc) { -nChromosomes = nTraits; -if (nLoci != NULL) deleteLoci(); -nLoci = new short [1]; -if (nloc > 0) nLoci[0] = nloc; -else nLoci[0] = 1; + nChromosomes = nTraits; + if (nLoci != NULL) deleteLoci(); + nLoci = new short[1]; + if (nloc > 0) nLoci[0] = nloc; + else nLoci[0] = 1; } bool Species::has1ChromPerTrait(void) { return trait1Chromosome; } @@ -497,458 +497,458 @@ bool Species::has1ChromPerTrait(void) { return trait1Chromosome; } // Set trait attributes for the species void Species::setTraits(void) { -emigTrait[0] = 0; emigTrait[1] = 0; -movtTrait[0] = 0; movtTrait[1] = 0; -settTrait[0] = 0; settTrait[1] = 0; -nTraits = 0; + emigTrait[0] = 0; emigTrait[1] = 0; + movtTrait[0] = 0; movtTrait[1] = 0; + settTrait[0] = 0; settTrait[1] = 0; + nTraits = 0; #if RSDEBUG -DebugGUI("Species::setTraits(): 0000 nChromosomes=" + Int2Str(nChromosomes) - + " nTraits=" + Int2Str(nTraits) - + " indVarEmig=" + Int2Str((int)indVarEmig) - + " indVarTrfr=" + Int2Str((int)indVarTrfr) - + " indVarSett=" + Int2Str((int)indVarSett) + DebugGUI("Species::setTraits(): 0000 nChromosomes=" + Int2Str(nChromosomes) + + " nTraits=" + Int2Str(nTraits) + + " indVarEmig=" + Int2Str((int)indVarEmig) + + " indVarTrfr=" + Int2Str((int)indVarTrfr) + + " indVarSett=" + Int2Str((int)indVarSett) ); #endif -if (indVarEmig) { - if (sexDepEmig) { - if (densDepEmig) nTraits += 6; else nTraits += 2; - } - else { - if (densDepEmig) nTraits += 3; else nTraits += 1; + if (indVarEmig) { + if (sexDepEmig) { + if (densDepEmig) nTraits += 6; else nTraits += 2; + } + else { + if (densDepEmig) nTraits += 3; else nTraits += 1; + } + emigTrait[0] = 0; emigTrait[1] = nTraits; } - emigTrait[0] = 0; emigTrait[1] = nTraits; -} #if RSDEBUG -//DebugGUI("Species::setTraits(): 1111 nTraits=" + Int2Str(nTraits)); + //DebugGUI("Species::setTraits(): 1111 nTraits=" + Int2Str(nTraits)); #endif -int movttraits = 0; -if (indVarTrfr) { - if (moveModel) { - if (moveType == 1) { // SMS - movttraits = 1; // in contain batch 2 - if (goalType == 2) movttraits += 3; //in contain batch 2 - } - if (moveType == 2) movttraits = 2; - } - else { - if (sexDepTrfr) { - if (twinKern) movttraits = 6; else movttraits = 2; + int movttraits = 0; + if (indVarTrfr) { + if (moveModel) { + if (moveType == 1) { // SMS + movttraits = 1; // in contain batch 2 + if (goalType == 2) movttraits += 3; //in contain batch 2 + } + if (moveType == 2) movttraits = 2; } else { - if (twinKern) movttraits = 3; else movttraits = 1; + if (sexDepTrfr) { + if (twinKern) movttraits = 6; else movttraits = 2; + } + else { + if (twinKern) movttraits = 3; else movttraits = 1; + } } + movtTrait[0] = nTraits; movtTrait[1] = movttraits; + nTraits += movttraits; } - movtTrait[0] = nTraits; movtTrait[1] = movttraits; - nTraits += movttraits; -} #if RSDEBUG -//DebugGUI("Species::setTraits(): 2222 nTraits=" + Int2Str(nTraits)); + //DebugGUI("Species::setTraits(): 2222 nTraits=" + Int2Str(nTraits)); #endif -int setttraits = 0; -if (indVarSett) { - if (sexDepSett) setttraits = 6; else setttraits = 3; - settTrait[0] = nTraits; settTrait[1] = setttraits; - nTraits += setttraits; -} + int setttraits = 0; + if (indVarSett) { + if (sexDepSett) setttraits = 6; else setttraits = 3; + settTrait[0] = nTraits; settTrait[1] = setttraits; + nTraits += setttraits; + } -setTraitNames(); + setTraitNames(); -//if (trait1Chromosome) { -// nChromosomes = nTraits; -//} + //if (trait1Chromosome) { + // nChromosomes = nTraits; + //} #if RSDEBUG -DebugGUI("Species::setTraits(): 9999 nChromosomes=" + Int2Str(nChromosomes) - + " nTraits=" + Int2Str(nTraits)); + DebugGUI("Species::setTraits(): 9999 nChromosomes=" + Int2Str(nChromosomes) + + " nTraits=" + Int2Str(nTraits)); #endif } void Species::setTraitNames(void) { #if RSDEBUG -//DebugGUI("Species::setTraitNames(): nTraits=" + Int2Str(nTraits) -// + " nTraitNames=" + Int2Str(nTraitNames) -// + " traitnames=" + Int2Str((int)traitnames) -// ); -//if (traitnames != NULL) { -// DebugGUI("Species::setTraitNames(): traitnames[0]=" + traitnames[0] -// ); -// if (nTraits > 1) { -// DebugGUI("Species::setTraitNames(): traitnames[1]=" + traitnames[1] -// ); -// } -//} + //DebugGUI("Species::setTraitNames(): nTraits=" + Int2Str(nTraits) + // + " nTraitNames=" + Int2Str(nTraitNames) + // + " traitnames=" + Int2Str((int)traitnames) + // ); + //if (traitnames != NULL) { + // DebugGUI("Species::setTraitNames(): traitnames[0]=" + traitnames[0] + // ); + // if (nTraits > 1) { + // DebugGUI("Species::setTraitNames(): traitnames[1]=" + traitnames[1] + // ); + // } + //} #endif -deleteTraitNames(); -nTraitNames = nTraits; -traitnames = new string [nTraitNames]; -int trait = 0; -if (indVarEmig) { - if (sexDepEmig) { - if (densDepEmig) { - traitnames[trait++] = "d0_F"; - traitnames[trait++] = "d0_M"; - traitnames[trait++] = "alpha_F"; - traitnames[trait++] = "alpha_M"; - traitnames[trait++] = "beta_F"; - traitnames[trait++] = "beta_M"; + deleteTraitNames(); + nTraitNames = nTraits; + traitnames = new string[nTraitNames]; + int trait = 0; + if (indVarEmig) { + if (sexDepEmig) { + if (densDepEmig) { + traitnames[trait++] = "d0_F"; + traitnames[trait++] = "d0_M"; + traitnames[trait++] = "alpha_F"; + traitnames[trait++] = "alpha_M"; + traitnames[trait++] = "beta_F"; + traitnames[trait++] = "beta_M"; + } + else { + traitnames[trait++] = "d0_F"; + traitnames[trait++] = "d0_M"; + } } else { - traitnames[trait++] = "d0_F"; - traitnames[trait++] = "d0_M"; - } - } - else { - traitnames[trait++] = "d0"; - if (densDepEmig) { - traitnames[trait++] = "alpha"; - traitnames[trait++] = "beta"; - } - } -} - -if (indVarTrfr) { - if (moveModel) { - if (moveType == 1) { // SMS - traitnames[trait++] = "DP"; - if (goalType == 2) { - traitnames[trait++] = "GB"; - traitnames[trait++] = "alphaDB"; - traitnames[trait++] = "betaDB"; + traitnames[trait++] = "d0"; + if (densDepEmig) { + traitnames[trait++] = "alpha"; + traitnames[trait++] = "beta"; } } - if (moveType == 2) { // CRW - traitnames[trait++] = "stepL"; - traitnames[trait++] = "rho"; - } } - else { - if (sexDepTrfr) { - if (twinKern) - { - traitnames[trait++] = "meanDistI_F"; - traitnames[trait++] = "meanDistI_M"; - traitnames[trait++] = "meanDistII_F"; - traitnames[trait++] = "meanDistII_M"; - traitnames[trait++] = "probKernI_F"; - traitnames[trait++] = "probKernI_M"; + + if (indVarTrfr) { + if (moveModel) { + if (moveType == 1) { // SMS + traitnames[trait++] = "DP"; + if (goalType == 2) { + traitnames[trait++] = "GB"; + traitnames[trait++] = "alphaDB"; + traitnames[trait++] = "betaDB"; + } } - else { - traitnames[trait++] = "meanDistI_F"; - traitnames[trait++] = "meanDistI_M"; + if (moveType == 2) { // CRW + traitnames[trait++] = "stepL"; + traitnames[trait++] = "rho"; } } else { - traitnames[trait++] = "meanDistI"; - if (twinKern) - { - traitnames[trait++] = "meanDistII"; - traitnames[trait++] = "probKernI"; + if (sexDepTrfr) { + if (twinKern) + { + traitnames[trait++] = "meanDistI_F"; + traitnames[trait++] = "meanDistI_M"; + traitnames[trait++] = "meanDistII_F"; + traitnames[trait++] = "meanDistII_M"; + traitnames[trait++] = "probKernI_F"; + traitnames[trait++] = "probKernI_M"; + } + else { + traitnames[trait++] = "meanDistI_F"; + traitnames[trait++] = "meanDistI_M"; + } + } + else { + traitnames[trait++] = "meanDistI"; + if (twinKern) + { + traitnames[trait++] = "meanDistII"; + traitnames[trait++] = "probKernI"; + } } } } -} -if (indVarSett) { - if (sexDepSett) { - traitnames[trait++] = "s0_F"; - traitnames[trait++] = "s0_M"; - traitnames[trait++] = "alphaS_F"; - traitnames[trait++] = "alphaS_M"; - traitnames[trait++] = "betaS_F"; - traitnames[trait++] = "betaS_M"; - } - else { - traitnames[trait++] = "s0"; - traitnames[trait++] = "alphaS"; - traitnames[trait++] = "betaS"; + if (indVarSett) { + if (sexDepSett) { + traitnames[trait++] = "s0_F"; + traitnames[trait++] = "s0_M"; + traitnames[trait++] = "alphaS_F"; + traitnames[trait++] = "alphaS_M"; + traitnames[trait++] = "betaS_F"; + traitnames[trait++] = "betaS_M"; + } + else { + traitnames[trait++] = "s0"; + traitnames[trait++] = "alphaS"; + traitnames[trait++] = "betaS"; + } } } -} void Species::deleteTraitNames(void) { -if (traitnames != NULL) { + if (traitnames != NULL) { #if RSDEBUG -//DebugGUI("Species::deleteTraitNames(): traitnames=" + Int2Str((int)traitnames) -// ); + //DebugGUI("Species::deleteTraitNames(): traitnames=" + Int2Str((int)traitnames) + // ); #endif - delete[] traitnames; - traitnames = NULL; -} + delete[] traitnames; + traitnames = NULL; + } } string Species::getTraitName(const int trait) { -string name = "not used"; -if (traitnames != NULL) { - if (trait >= 0 && trait < nTraits) { - name = traitnames[trait]; + string name = "not used"; + if (traitnames != NULL) { + if (trait >= 0 && trait < nTraits) { + name = traitnames[trait]; + } } -} -return name; + return name; } int Species::getNTraits(void) { return nTraits; } void Species::setTraitData(const int ntraits) { #if RSDEBUG -//DebugGUI(("Species::setTraitData(): traitdata=" + Int2Str((int)traitdata) -// + " ntraits=" + Int2Str(ntraits) -// ).c_str()); + //DebugGUI(("Species::setTraitData(): traitdata=" + Int2Str((int)traitdata) + // + " ntraits=" + Int2Str(ntraits) + // ).c_str()); #endif -deleteTraitData(); -traitdata = new traitData; -if (ntraits > 0) { - traitdata->nTraitMaps = ntraits; - traitdata->traitmaps = new traitMap *[ntraits]; - for (int i = 0; i < ntraits; i++) { - traitdata->traitmaps[i] = new traitMap; + deleteTraitData(); + traitdata = new traitData; + if (ntraits > 0) { + traitdata->nTraitMaps = ntraits; + traitdata->traitmaps = new traitMap * [ntraits]; + for (int i = 0; i < ntraits; i++) { + traitdata->traitmaps[i] = new traitMap; + } } -} -else { // neutral markers only - traitdata->nTraitMaps = 0; -} -traitdata->neutralloci = new traitMap; -traitdata->neutralloci->nAlleles = 0; + else { // neutral markers only + traitdata->nTraitMaps = 0; + } + traitdata->neutralloci = new traitMap; + traitdata->neutralloci->nAlleles = 0; #if RSDEBUG -//DebugGUI(("Species::setTraitData(): traitdata=" + Int2Str((int)traitdata) -// + " nTraitMaps=" + Int2Str(traitdata->nTraitMaps) -// ).c_str()); + //DebugGUI(("Species::setTraitData(): traitdata=" + Int2Str((int)traitdata) + // + " nTraitMaps=" + Int2Str(traitdata->nTraitMaps) + // ).c_str()); #endif } void Species::deleteTraitData(void) { -if (traitdata != NULL) { + if (traitdata != NULL) { #if RSDEBUG -//DebugGUI(("Species::deleteTraitData(): traitdata=" + Int2Str((int)traitdata) -// + " nTraitMaps=" + Int2Str(traitdata->nTraitMaps) -// ).c_str()); + //DebugGUI(("Species::deleteTraitData(): traitdata=" + Int2Str((int)traitdata) + // + " nTraitMaps=" + Int2Str(traitdata->nTraitMaps) + // ).c_str()); #endif - for (int i = 0; i < traitdata->nTraitMaps; i++) { - if (traitdata->traitmaps[i]->traitalleles != 0) { - for (int j = 0; j < traitdata->traitmaps[i]->nAlleles; j++) { - delete traitdata->traitmaps[i]->traitalleles[j]; + for (int i = 0; i < traitdata->nTraitMaps; i++) { + if (traitdata->traitmaps[i]->traitalleles != 0) { + for (int j = 0; j < traitdata->traitmaps[i]->nAlleles; j++) { + delete traitdata->traitmaps[i]->traitalleles[j]; + } } + delete[] traitdata->traitmaps[i]; } - delete[] traitdata->traitmaps[i]; + deleteNeutralLoci(); + delete traitdata; + traitdata = NULL; } - deleteNeutralLoci(); - delete traitdata; - traitdata = NULL; -} } int Species::getNTraitMaps(void) { -if (traitdata == NULL) return 0; -else return traitdata->nTraitMaps; + if (traitdata == NULL) return 0; + else return traitdata->nTraitMaps; } -void Species::setTraitMap(const short trait,const short nalleles) { -traitdata->traitmaps[trait]->nAlleles = nalleles; -traitdata->traitmaps[trait]->traitalleles = new traitAllele *[nalleles]; -for (int i = 0; i < nalleles; i++) { - traitdata->traitmaps[trait]->traitalleles[i] = new traitAllele; -} +void Species::setTraitMap(const short trait, const short nalleles) { + traitdata->traitmaps[trait]->nAlleles = nalleles; + traitdata->traitmaps[trait]->traitalleles = new traitAllele * [nalleles]; + for (int i = 0; i < nalleles; i++) { + traitdata->traitmaps[trait]->traitalleles[i] = new traitAllele; + } } int Species::getNTraitAlleles(const int trait) { -int nalleles = 0; -if (traitdata != NULL) { - if (trait >= 0 && trait < traitdata->nTraitMaps) { - nalleles = traitdata->traitmaps[trait]->nAlleles; + int nalleles = 0; + if (traitdata != NULL) { + if (trait >= 0 && trait < traitdata->nTraitMaps) { + nalleles = traitdata->traitmaps[trait]->nAlleles; + } } -} -return nalleles; + return nalleles; } -void Species::setTraitAllele(const short trait,const short allele, - const short chr,const short loc) +void Species::setTraitAllele(const short trait, const short allele, + const short chr, const short loc) { -traitdata->traitmaps[trait]->traitalleles[allele] = new traitAllele; -if (chr >= 0 && loc >= 0) { - traitdata->traitmaps[trait]->traitalleles[allele]->chromo = chr; - traitdata->traitmaps[trait]->traitalleles[allele]->locus = loc; -} -else { - traitdata->traitmaps[trait]->traitalleles[allele]->chromo = 0; - traitdata->traitmaps[trait]->traitalleles[allele]->locus = 0; -} + traitdata->traitmaps[trait]->traitalleles[allele] = new traitAllele; + if (chr >= 0 && loc >= 0) { + traitdata->traitmaps[trait]->traitalleles[allele]->chromo = chr; + traitdata->traitmaps[trait]->traitalleles[allele]->locus = loc; + } + else { + traitdata->traitmaps[trait]->traitalleles[allele]->chromo = 0; + traitdata->traitmaps[trait]->traitalleles[allele]->locus = 0; + } } -traitAllele Species::getTraitAllele(const short trait,const short allele) { -traitAllele a; a.chromo = 0; a.locus = 0; -if (traitdata != NULL) { - if (trait >= 0 && trait < traitdata->nTraitMaps) { - if (allele >= 0 && allele < traitdata->traitmaps[trait]->nAlleles) { - a = *traitdata->traitmaps[trait]->traitalleles[allele]; +traitAllele Species::getTraitAllele(const short trait, const short allele) { + traitAllele a; a.chromo = 0; a.locus = 0; + if (traitdata != NULL) { + if (trait >= 0 && trait < traitdata->nTraitMaps) { + if (allele >= 0 && allele < traitdata->traitmaps[trait]->nAlleles) { + a = *traitdata->traitmaps[trait]->traitalleles[allele]; + } } } -} -return a; + return a; } // Neutral loci functions // Identify neutral loci and determine whether there is pleiotropy void Species::setNeutralLoci(bool neutralMarkersOnly) { -bool neutral; -int nneutral = 0; -// find minimum of no. of defined / applied traits -int ntraits; -if (traitdata == 0 ) ntraits = 0; -else ntraits = traitdata->nTraitMaps; -if (ntraits > nTraits) ntraits = nTraits; + bool neutral; + int nneutral = 0; + // find minimum of no. of defined / applied traits + int ntraits; + if (traitdata == 0) ntraits = 0; + else ntraits = traitdata->nTraitMaps; + if (ntraits > nTraits) ntraits = nTraits; #if RSDEBUG -//DebugGUI("Species::setNeutralLoci(): neutralMarkersOnly=" + Int2Str((int)neutralMarkersOnly) -// + " nNLoci=" + Int2Str(nNLoci) -// + " nTraits=" + Int2Str(nTraits) + " ntraits=" + Int2Str(ntraits) -//); + //DebugGUI("Species::setNeutralLoci(): neutralMarkersOnly=" + Int2Str((int)neutralMarkersOnly) + // + " nNLoci=" + Int2Str(nNLoci) + // + " nTraits=" + Int2Str(nTraits) + " ntraits=" + Int2Str(ntraits) + //); #endif // determine no. of neutral loci -deleteNeutralLoci(); -for (int i = 0; i < nNLoci; i++) { // each chromosome - for (int j = 0; j < nLoci[i]; j++) { // each locus - neutral = true; - for (int t = 0; t < ntraits; t++) { // each trait - for (int a = 0; a < traitdata->traitmaps[t]->nAlleles; a++) { + deleteNeutralLoci(); + for (int i = 0; i < nNLoci; i++) { // each chromosome + for (int j = 0; j < nLoci[i]; j++) { // each locus + neutral = true; + for (int t = 0; t < ntraits; t++) { // each trait + for (int a = 0; a < traitdata->traitmaps[t]->nAlleles; a++) { #if RSDEBUG -//DebugGUI("Species::setNeutralLoci(): i=" + Int2Str(i) -// + " j=" + Int2Str(j) + " t=" + Int2Str(t) + " a=" + Int2Str(a) -// + " chromo=" + Int2Str(traitdata->traitmaps[t]->traitalleles[a]->chromo) -// + " locus=" + Int2Str(traitdata->traitmaps[t]->traitalleles[a]->locus) -//); + //DebugGUI("Species::setNeutralLoci(): i=" + Int2Str(i) + // + " j=" + Int2Str(j) + " t=" + Int2Str(t) + " a=" + Int2Str(a) + // + " chromo=" + Int2Str(traitdata->traitmaps[t]->traitalleles[a]->chromo) + // + " locus=" + Int2Str(traitdata->traitmaps[t]->traitalleles[a]->locus) + //); #endif - if (i == traitdata->traitmaps[t]->traitalleles[a]->chromo - && j == traitdata->traitmaps[t]->traitalleles[a]->locus) { + if (i == traitdata->traitmaps[t]->traitalleles[a]->chromo + && j == traitdata->traitmaps[t]->traitalleles[a]->locus) { #if RSDEBUG -//DebugGUI("Species::setNeutralLoci(): FALSE"); + //DebugGUI("Species::setNeutralLoci(): FALSE"); #endif - neutral = false; // as locus contributes to a trait - a = 999999; + neutral = false; // as locus contributes to a trait + a = 999999; + } } + if (!neutral) t = 999999; } - if (!neutral) t = 999999; + if (neutral) nneutral++; } - if (neutral) nneutral++; - } -} - -traitdata->neutralloci = new traitMap; -traitdata->neutralloci->nAlleles = nneutral; -if (nneutral < 1) return; - -// record neutral markers -traitdata->neutralloci->traitalleles = new traitAllele *[nneutral]; -nneutral = 0; -for (int i = 0; i < nNLoci; i++) { // each chromosome - for (int j = 0; j < nLoci[i]; j++) { // each locus - neutral = true; - for (int t = 0; t < ntraits; t++) { // each trait - for (int a = 0; a < traitdata->traitmaps[t]->nAlleles; a++) { - if (i == traitdata->traitmaps[t]->traitalleles[a]->chromo - && j == traitdata->traitmaps[t]->traitalleles[a]->locus) { - neutral = false; // as locus contributes to a trait - a = 999999; + } + + traitdata->neutralloci = new traitMap; + traitdata->neutralloci->nAlleles = nneutral; + if (nneutral < 1) return; + + // record neutral markers + traitdata->neutralloci->traitalleles = new traitAllele * [nneutral]; + nneutral = 0; + for (int i = 0; i < nNLoci; i++) { // each chromosome + for (int j = 0; j < nLoci[i]; j++) { // each locus + neutral = true; + for (int t = 0; t < ntraits; t++) { // each trait + for (int a = 0; a < traitdata->traitmaps[t]->nAlleles; a++) { + if (i == traitdata->traitmaps[t]->traitalleles[a]->chromo + && j == traitdata->traitmaps[t]->traitalleles[a]->locus) { + neutral = false; // as locus contributes to a trait + a = 999999; + } } + if (!neutral) t = 999999; + } + if (neutral) { + traitdata->neutralloci->traitalleles[nneutral] = new traitAllele; + traitdata->neutralloci->traitalleles[nneutral]->chromo = i; + traitdata->neutralloci->traitalleles[nneutral]->locus = j; + nneutral++; } - if (!neutral) t = 999999; - } - if (neutral) { - traitdata->neutralloci->traitalleles[nneutral] = new traitAllele; - traitdata->neutralloci->traitalleles[nneutral]->chromo = i; - traitdata->neutralloci->traitalleles[nneutral]->locus = j; - nneutral++; } } -} -pleiotropic = false; -if (neutralMarkersOnly) return; // pleiotropy cannot apply + pleiotropic = false; + if (neutralMarkersOnly) return; // pleiotropy cannot apply -// determine whether there is pleiotropy -int chr,loc; -int nloci = 0; // maximum no. of loci on any one chromosome -for (int i = 0; i < nNLoci; i++) { - if (nloci < nLoci[i]) nloci = nLoci[i]; -} -int ***locfreq; -locfreq = new int **[nNLoci]; -for (int i = 0; i < nNLoci; i++) { - locfreq[i] = new int *[nloci]; - for (int j = 0; j < nloci; j++) { - locfreq[i][j] = new int[ntraits]; - for (int t = 0; t < ntraits; t++) locfreq[i][j][t] = 0; + // determine whether there is pleiotropy + int chr, loc; + int nloci = 0; // maximum no. of loci on any one chromosome + for (int i = 0; i < nNLoci; i++) { + if (nloci < nLoci[i]) nloci = nLoci[i]; } -} -for (int t = 0; t < ntraits; t++) { // each trait - for (int a = 0; a < traitdata->traitmaps[t]->nAlleles; a++) { - chr = traitdata->traitmaps[t]->traitalleles[a]->chromo; - loc = traitdata->traitmaps[t]->traitalleles[a]->locus; - locfreq[chr][loc][t]++; + int*** locfreq; + locfreq = new int** [nNLoci]; + for (int i = 0; i < nNLoci; i++) { + locfreq[i] = new int* [nloci]; + for (int j = 0; j < nloci; j++) { + locfreq[i][j] = new int[ntraits]; + for (int t = 0; t < ntraits; t++) locfreq[i][j][t] = 0; + } + } + for (int t = 0; t < ntraits; t++) { // each trait + for (int a = 0; a < traitdata->traitmaps[t]->nAlleles; a++) { + chr = traitdata->traitmaps[t]->traitalleles[a]->chromo; + loc = traitdata->traitmaps[t]->traitalleles[a]->locus; + locfreq[chr][loc][t]++; + } } -} #if RSDEBUG -//for (int i = 0; i < nNLoci; i++) { -// for (int j = 0; j < nloci; j++) -// for (int t = 0; t < ntraits; t++) -// DebugGUI("locfreq[" + Int2Str(i) + "][" + Int2Str(j) + "][" + Int2Str(t) -// + "]=" + Int2Str(locfreq[i][j][t])); -//} + //for (int i = 0; i < nNLoci; i++) { + // for (int j = 0; j < nloci; j++) + // for (int t = 0; t < ntraits; t++) + // DebugGUI("locfreq[" + Int2Str(i) + "][" + Int2Str(j) + "][" + Int2Str(t) + // + "]=" + Int2Str(locfreq[i][j][t])); + //} #endif -for (int i = 0; i < nNLoci; i++) { - for (int j = 0; j < nloci; j++) { - // remove multiple contributions of a locus to a particular trait - // (i.e. prevent recording of pseudo-pleiotropy) - for (int t = 0; t < ntraits; t++) { - if (locfreq[i][j][t] > 0) locfreq[i][j][t] = 1; - } - // sum at level of chromosome/locus - for (int t = 1; t < ntraits; t++) { - locfreq[i][j][0] += locfreq[i][j][t]; + for (int i = 0; i < nNLoci; i++) { + for (int j = 0; j < nloci; j++) { + // remove multiple contributions of a locus to a particular trait + // (i.e. prevent recording of pseudo-pleiotropy) + for (int t = 0; t < ntraits; t++) { + if (locfreq[i][j][t] > 0) locfreq[i][j][t] = 1; + } + // sum at level of chromosome/locus + for (int t = 1; t < ntraits; t++) { + locfreq[i][j][0] += locfreq[i][j][t]; + } + if (locfreq[i][j][0] > 1) pleiotropic = true; } - if (locfreq[i][j][0] > 1) pleiotropic = true; } -} -for (int i = 0; i < nNLoci; i++) { - for (int j = 0; j < nloci; j++) { - delete[] locfreq[i][j]; + for (int i = 0; i < nNLoci; i++) { + for (int j = 0; j < nloci; j++) { + delete[] locfreq[i][j]; + } + delete[] locfreq[i]; } - delete[] locfreq[i]; -} -delete[] locfreq; + delete[] locfreq; } void Species::deleteNeutralLoci(void) { -if (traitdata->neutralloci != NULL) { - for (int i = 0; i < traitdata->neutralloci->nAlleles; i++) { - delete traitdata->neutralloci->traitalleles[i]; + if (traitdata->neutralloci != NULL) { + for (int i = 0; i < traitdata->neutralloci->nAlleles; i++) { + delete traitdata->neutralloci->traitalleles[i]; + } + delete[] traitdata->neutralloci; } - delete[] traitdata->neutralloci; -} -traitdata->neutralloci = NULL; + traitdata->neutralloci = NULL; } int Species::getNNeutralLoci(void) { -int nn = 0; -if (traitdata != NULL) { - if (traitdata->neutralloci != NULL) { - nn = traitdata->neutralloci->nAlleles; + int nn = 0; + if (traitdata != NULL) { + if (traitdata->neutralloci != NULL) { + nn = traitdata->neutralloci->nAlleles; + } } -} -return nn; + return nn; } traitAllele Species::getNeutralAllele(const short allele) { -traitAllele a; a.chromo = 0; a.locus = 0; -if (traitdata != NULL) { - if (allele >= 0 && allele < traitdata->neutralloci->nAlleles) { - a = *traitdata->neutralloci->traitalleles[allele]; + traitAllele a; a.chromo = 0; a.locus = 0; + if (traitdata != NULL) { + if (allele >= 0 && allele < traitdata->neutralloci->nAlleles) { + a = *traitdata->neutralloci->traitalleles[allele]; + } } -} -return a; + return a; } //--------------------------------------------------------------------------- @@ -957,96 +957,96 @@ return a; void Species::setEmig(const emigRules e) { #if RSDEBUG -//DebugGUI("Species::setEmig(): e.indVar=" + Int2Str((int)e.indVar)); + //DebugGUI("Species::setEmig(): e.indVar=" + Int2Str((int)e.indVar)); #endif -densDepEmig = e.densDep; stgDepEmig = e.stgDep; sexDepEmig = e.sexDep; -indVarEmig = e.indVar; -if (e.emigStage >= 0) emigStage = e.emigStage; -//setGenome(); + densDepEmig = e.densDep; stgDepEmig = e.stgDep; sexDepEmig = e.sexDep; + indVarEmig = e.indVar; + if (e.emigStage >= 0) emigStage = e.emigStage; + //setGenome(); } emigRules Species::getEmig(void) { -emigRules e; -e.densDep = densDepEmig; e.stgDep = stgDepEmig; e.sexDep = sexDepEmig; -e.indVar = indVarEmig; e.emigStage = emigStage; -e.emigTrait[0] = emigTrait[0]; e.emigTrait[1] = emigTrait[1]; -return e; + emigRules e; + e.densDep = densDepEmig; e.stgDep = stgDepEmig; e.sexDep = sexDepEmig; + e.indVar = indVarEmig; e.emigStage = emigStage; + e.emigTrait[0] = emigTrait[0]; e.emigTrait[1] = emigTrait[1]; + return e; } -void Species::setEmigTraits(const short stg,const short sex,const emigTraits e) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - if (e.d0 >= 0.0 && e.d0 <= 1.0) d0[stg][sex] = e.d0; - alphaEmig[stg][sex] = e.alpha; betaEmig[stg][sex] = e.beta; -} +void Species::setEmigTraits(const short stg, const short sex, const emigTraits e) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (e.d0 >= 0.0 && e.d0 <= 1.0) d0[stg][sex] = e.d0; + alphaEmig[stg][sex] = e.alpha; betaEmig[stg][sex] = e.beta; + } } -emigTraits Species::getEmigTraits(short stg,short sex) { -emigTraits e; -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - e.d0 = d0[stg][sex]; e.alpha = alphaEmig[stg][sex]; e.beta = betaEmig[stg][sex]; -} -else { - e.d0 = e.alpha = e.beta = 0.0; -} -return e; +emigTraits Species::getEmigTraits(short stg, short sex) { + emigTraits e; + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + e.d0 = d0[stg][sex]; e.alpha = alphaEmig[stg][sex]; e.beta = betaEmig[stg][sex]; + } + else { + e.d0 = e.alpha = e.beta = 0.0; + } + return e; } -float Species::getEmigD0(short stg,short sex) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - return d0[stg][sex]; -} -else { - return 0.0; -} +float Species::getEmigD0(short stg, short sex) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + return d0[stg][sex]; + } + else { + return 0.0; + } } -void Species::setEmigParams(const short stg,const short sex,const emigParams e) { -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only -{ - if (e.d0Mean >= 0.0 && e.d0Mean < 1.0) d0Mean[stg][sex] = e.d0Mean; - if (e.d0SD > 0.0 && e.d0SD < 1.0) d0SD[stg][sex] = e.d0SD; -// if (e.d0MutnSize > 0.0 && e.d0MutnSize < 1.0) d0MutnSize = e.d0MutnSize; - alphaMean[stg][sex] = e.alphaMean; - if (e.alphaSD > 0.0) alphaSD[stg][sex] = e.alphaSD; -// if (e.alphaMutnSize > 0.0) alphaMutnSize = e.alphaMutnSize; - betaMean[stg][sex] = e.betaMean; - if (e.betaSD > 0.0) betaSD[stg][sex] = e.betaSD; -// if (e.betaMutnSize > 0.0) betaMutnSize = e.betaMutnSize; -} -} - -emigParams Species::getEmigParams(short stg,short sex) { -emigParams e; -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only -{ - e.d0Mean = d0Mean[stg][sex]; e.d0SD = d0SD[stg][sex]; - e.d0Scale = d0Scale; - e.alphaMean = alphaMean[stg][sex]; e.alphaSD = alphaSD[stg][sex]; - e.alphaScale = alphaScale; - e.betaMean = betaMean[stg][sex]; e.betaSD = betaSD[stg][sex]; - e.betaScale = betaScale; -} -else { - e.d0Mean = e.alphaMean = e.betaMean = e.d0SD = e.alphaSD = e.betaSD = 0.0; - e.d0Scale = d0Scale; - e.alphaScale = alphaScale; - e.betaScale = betaScale; +void Species::setEmigParams(const short stg, const short sex, const emigParams e) { + //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only + { + if (e.d0Mean >= 0.0 && e.d0Mean < 1.0) d0Mean[stg][sex] = e.d0Mean; + if (e.d0SD > 0.0 && e.d0SD < 1.0) d0SD[stg][sex] = e.d0SD; + // if (e.d0MutnSize > 0.0 && e.d0MutnSize < 1.0) d0MutnSize = e.d0MutnSize; + alphaMean[stg][sex] = e.alphaMean; + if (e.alphaSD > 0.0) alphaSD[stg][sex] = e.alphaSD; + // if (e.alphaMutnSize > 0.0) alphaMutnSize = e.alphaMutnSize; + betaMean[stg][sex] = e.betaMean; + if (e.betaSD > 0.0) betaSD[stg][sex] = e.betaSD; + // if (e.betaMutnSize > 0.0) betaMutnSize = e.betaMutnSize; + } } -return e; + +emigParams Species::getEmigParams(short stg, short sex) { + emigParams e; + //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only + { + e.d0Mean = d0Mean[stg][sex]; e.d0SD = d0SD[stg][sex]; + e.d0Scale = d0Scale; + e.alphaMean = alphaMean[stg][sex]; e.alphaSD = alphaSD[stg][sex]; + e.alphaScale = alphaScale; + e.betaMean = betaMean[stg][sex]; e.betaSD = betaSD[stg][sex]; + e.betaScale = betaScale; + } + else { + e.d0Mean = e.alphaMean = e.betaMean = e.d0SD = e.alphaSD = e.betaSD = 0.0; + e.d0Scale = d0Scale; + e.alphaScale = alphaScale; + e.betaScale = betaScale; + } + return e; } void Species::setEmigScales(const emigScales s) { -if (s.d0Scale >= 0.0 && s.d0Scale < 1.0 ) d0Scale = s.d0Scale; -if (s.alphaScale >= 0.0) alphaScale = s.alphaScale; -if (s.betaScale >= 0.0) betaScale = s.betaScale; + if (s.d0Scale >= 0.0 && s.d0Scale < 1.0) d0Scale = s.d0Scale; + if (s.alphaScale >= 0.0) alphaScale = s.alphaScale; + if (s.betaScale >= 0.0) betaScale = s.betaScale; } emigScales Species::getEmigScales(void) { -emigScales s; -s.d0Scale = d0Scale; s.alphaScale = alphaScale; s.betaScale = betaScale; -return s; + emigScales s; + s.d0Scale = d0Scale; s.alphaScale = alphaScale; s.betaScale = betaScale; + return s; } //--------------------------------------------------------------------------- @@ -1055,277 +1055,277 @@ return s; void Species::setTrfr(const trfrRules t) { #if RSDEBUG -//DebugGUI("Species::setTrfr(): t.indVar=" + Int2Str((int)t.indVar)); + //DebugGUI("Species::setTrfr(): t.indVar=" + Int2Str((int)t.indVar)); #endif -moveModel = t.moveModel; stgDepTrfr = t.stgDep; sexDepTrfr = t.sexDep; -distMort = t.distMort; indVarTrfr = t.indVar; -twinKern = t.twinKern; -habMort = t.habMort; -moveType = t.moveType; costMap = t.costMap; -//setGenome(); + moveModel = t.moveModel; stgDepTrfr = t.stgDep; sexDepTrfr = t.sexDep; + distMort = t.distMort; indVarTrfr = t.indVar; + twinKern = t.twinKern; + habMort = t.habMort; + moveType = t.moveType; costMap = t.costMap; + //setGenome(); } trfrRules Species::getTrfr(void) { -trfrRules t; -t.moveModel = moveModel; t.stgDep = stgDepTrfr; t.sexDep = sexDepTrfr; -t.distMort = distMort; t.indVar = indVarTrfr; -t.twinKern = twinKern; -t.habMort = habMort; -t.moveType = moveType; t.costMap = costMap; -t.movtTrait[0] = movtTrait[0]; t.movtTrait[1] = movtTrait[1]; -return t; + trfrRules t; + t.moveModel = moveModel; t.stgDep = stgDepTrfr; t.sexDep = sexDepTrfr; + t.distMort = distMort; t.indVar = indVarTrfr; + t.twinKern = twinKern; + t.habMort = habMort; + t.moveType = moveType; t.costMap = costMap; + t.movtTrait[0] = movtTrait[0]; t.movtTrait[1] = movtTrait[1]; + return t; } void Species::setFullKernel(bool k) { -fullKernel = k; + fullKernel = k; } bool Species::useFullKernel(void) { return fullKernel; } -void Species::setKernTraits(const short stg,const short sex, - const trfrKernTraits k,const int resol) +void Species::setKernTraits(const short stg, const short sex, + const trfrKernTraits k, const int resol) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - if (k.meanDist1 > 0.0 && k.meanDist1 >= (float)resol) meanDist1[stg][sex] = k.meanDist1; - if (k.meanDist2 >= (float)resol) meanDist2[stg][sex] = k.meanDist2; - if (k.probKern1 > 0.0 && k.probKern1 < 1.0) probKern1[stg][sex] = k.probKern1; -} + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (k.meanDist1 > 0.0 && k.meanDist1 >= (float)resol) meanDist1[stg][sex] = k.meanDist1; + if (k.meanDist2 >= (float)resol) meanDist2[stg][sex] = k.meanDist2; + if (k.probKern1 > 0.0 && k.probKern1 < 1.0) probKern1[stg][sex] = k.probKern1; + } } -trfrKernTraits Species::getKernTraits(short stg,short sex) { -trfrKernTraits k; -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - k.meanDist1 = meanDist1[stg][sex]; - k.meanDist2 = meanDist2[stg][sex]; - k.probKern1 = probKern1[stg][sex]; -} -else { - k.meanDist1 = 0.0; k.meanDist2 = 0.0; k.probKern1 = 1.0; -} -return k; +trfrKernTraits Species::getKernTraits(short stg, short sex) { + trfrKernTraits k; + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + k.meanDist1 = meanDist1[stg][sex]; + k.meanDist2 = meanDist2[stg][sex]; + k.probKern1 = probKern1[stg][sex]; + } + else { + k.meanDist1 = 0.0; k.meanDist2 = 0.0; k.probKern1 = 1.0; + } + return k; } void Species::setMortParams(const trfrMortParams m) { -if (m.fixedMort >= 0.0 && m.fixedMort < 1.0) fixedMort = m.fixedMort; -mortAlpha = m.mortAlpha; -mortBeta = m.mortBeta; + if (m.fixedMort >= 0.0 && m.fixedMort < 1.0) fixedMort = m.fixedMort; + mortAlpha = m.mortAlpha; + mortBeta = m.mortBeta; } trfrMortParams Species::getMortParams(void) { -trfrMortParams m; -m.fixedMort = fixedMort; m.mortAlpha = mortAlpha; m.mortBeta = mortBeta; -return m; + trfrMortParams m; + m.fixedMort = fixedMort; m.mortAlpha = mortAlpha; m.mortBeta = mortBeta; + return m; } void Species::setMovtTraits(const trfrMovtTraits m) { -if (m.pr >= 1) pr = m.pr; -if (m.prMethod >= 1 && m.prMethod <= 3) prMethod = m.prMethod; -if (m.memSize >= 1 && m.memSize <= 14) memSize = m.memSize; -if (m.goalType >= 0 && m.goalType <= 2) goalType = m.goalType; -if (m.dp >= 1.0) dp = m.dp; -if (m.gb >= 1.0) gb = m.gb; -if (m.alphaDB > 0.0) alphaDB = m.alphaDB; -if (m.betaDB > 0) betaDB = m.betaDB; -if (m.stepMort >= 0.0 && m.stepMort < 1.0) stepMort = m.stepMort; -if (m.stepLength > 0.0) stepLength = m.stepLength; -if (m.rho > 0.0 && m.rho < 1.0) rho = m.rho; -straigtenPath = m.straigtenPath; + if (m.pr >= 1) pr = m.pr; + if (m.prMethod >= 1 && m.prMethod <= 3) prMethod = m.prMethod; + if (m.memSize >= 1 && m.memSize <= 14) memSize = m.memSize; + if (m.goalType >= 0 && m.goalType <= 2) goalType = m.goalType; + if (m.dp >= 1.0) dp = m.dp; + if (m.gb >= 1.0) gb = m.gb; + if (m.alphaDB > 0.0) alphaDB = m.alphaDB; + if (m.betaDB > 0) betaDB = m.betaDB; + if (m.stepMort >= 0.0 && m.stepMort < 1.0) stepMort = m.stepMort; + if (m.stepLength > 0.0) stepLength = m.stepLength; + if (m.rho > 0.0 && m.rho < 1.0) rho = m.rho; + straigtenPath = m.straigtenPath; } trfrMovtTraits Species::getMovtTraits(void) { -trfrMovtTraits m; -m.pr = pr; m.prMethod = prMethod; m.memSize = memSize; m.goalType = goalType; -m.dp = dp; m.gb = gb; m.alphaDB = alphaDB; m.betaDB = betaDB; -m.stepMort = stepMort; m.stepLength = stepLength; m.rho = rho; -return m; + trfrMovtTraits m; + m.pr = pr; m.prMethod = prMethod; m.memSize = memSize; m.goalType = goalType; + m.dp = dp; m.gb = gb; m.alphaDB = alphaDB; m.betaDB = betaDB; + m.stepMort = stepMort; m.stepLength = stepLength; m.rho = rho; + return m; } trfrCRWTraits Species::getCRWTraits(void) { -trfrCRWTraits m; -m.stepMort = stepMort; m.stepLength = stepLength; m.rho = rho; -m.straigtenPath = straigtenPath; -return m; + trfrCRWTraits m; + m.stepMort = stepMort; m.stepLength = stepLength; m.rho = rho; + m.straigtenPath = straigtenPath; + return m; } trfrSMSTraits Species::getSMSTraits(void) { -trfrSMSTraits m; -m.pr = pr; m.prMethod = prMethod; m.memSize = memSize; m.goalType = goalType; -m.dp = dp; m.gb = gb; m.alphaDB = alphaDB; m.betaDB = betaDB; m.stepMort = stepMort; -m.straigtenPath = straigtenPath; -return m; + trfrSMSTraits m; + m.pr = pr; m.prMethod = prMethod; m.memSize = memSize; m.goalType = goalType; + m.dp = dp; m.gb = gb; m.alphaDB = alphaDB; m.betaDB = betaDB; m.stepMort = stepMort; + m.straigtenPath = straigtenPath; + return m; } -void Species::setKernParams(const short stg,const short sex, - const trfrKernParams k,const double resol) +void Species::setKernParams(const short stg, const short sex, + const trfrKernParams k, const double resol) { -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only -{ - if (k.dist1Mean > 0.0 && k.dist1Mean >= resol && k.dist1SD > 0.0) { - dist1Mean[stg][sex] = k.dist1Mean; dist1SD[stg][sex] = k.dist1SD; + //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only + { + if (k.dist1Mean > 0.0 && k.dist1Mean >= resol && k.dist1SD > 0.0) { + dist1Mean[stg][sex] = k.dist1Mean; dist1SD[stg][sex] = k.dist1SD; + } + if (k.dist2Mean > 0.0 && k.dist2Mean >= resol && k.dist2SD > 0.0) { + dist2Mean[stg][sex] = k.dist2Mean; dist2SD[stg][sex] = k.dist2SD; + } + if (k.PKern1Mean > 0.0 && k.PKern1Mean < 1.0 && k.PKern1SD > 0.0 && k.PKern1SD < 1.0) { + PKern1Mean[stg][sex] = k.PKern1Mean; PKern1SD[stg][sex] = k.PKern1SD; + } } - if (k.dist2Mean > 0.0 && k.dist2Mean >= resol && k.dist2SD > 0.0) { - dist2Mean[stg][sex] = k.dist2Mean; dist2SD[stg][sex] = k.dist2SD; +} + +trfrKernParams Species::getKernParams(short stg, short sex) { + trfrKernParams k; + //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only + { + k.dist1Mean = dist1Mean[stg][sex]; k.dist1SD = dist1SD[stg][sex]; + k.dist2Mean = dist2Mean[stg][sex]; k.dist2SD = dist2SD[stg][sex]; + k.PKern1Mean = PKern1Mean[stg][sex]; k.PKern1SD = PKern1SD[stg][sex]; + k.dist1Scale = dist1Scale; k.dist2Scale = dist2Scale; k.PKern1Scale = PKern1Scale; } - if (k.PKern1Mean > 0.0 && k.PKern1Mean < 1.0 && k.PKern1SD > 0.0 && k.PKern1SD < 1.0 ) { - PKern1Mean[stg][sex] = k.PKern1Mean; PKern1SD[stg][sex] = k.PKern1SD; + else { + k.dist1Mean = 100000.0; k.dist1SD = 0.001f; k.dist1Scale = 1.0; + k.dist2Mean = 100000.0; k.dist2SD = 0.001f; k.dist2Scale = 1.0; + k.PKern1Mean = 0.5; k.PKern1SD = 0.1f; k.PKern1Scale = 0.1f; } -} + return k; } -trfrKernParams Species::getKernParams(short stg,short sex) { -trfrKernParams k; -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only -{ - k.dist1Mean = dist1Mean[stg][sex]; k.dist1SD = dist1SD[stg][sex]; - k.dist2Mean = dist2Mean[stg][sex]; k.dist2SD = dist2SD[stg][sex]; - k.PKern1Mean = PKern1Mean[stg][sex]; k.PKern1SD = PKern1SD[stg][sex]; - k.dist1Scale = dist1Scale; k.dist2Scale = dist2Scale; k.PKern1Scale = PKern1Scale; -} -else { - k.dist1Mean = 100000.0; k.dist1SD = 0.001f; k.dist1Scale = 1.0; - k.dist2Mean = 100000.0; k.dist2SD = 0.001f; k.dist2Scale = 1.0; - k.PKern1Mean = 0.5; k.PKern1SD = 0.1f; k.PKern1Scale = 0.1f; -} -return k; +void Species::setSMSParams(const short stg, const short sex, const trfrSMSParams s) { + //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only + { + if (s.dpMean >= 1.0 && s.dpSD > 0.0) { + dpMean[stg][sex] = s.dpMean; dpSD[stg][sex] = s.dpSD; + } + if (s.gbMean >= 1.0 && s.gbSD > 0.0) { + gbMean[stg][sex] = s.gbMean; gbSD[stg][sex] = s.gbSD; + } + if (s.alphaDBMean > 0.0 && s.alphaDBSD > 0.0) { + alphaDBMean[stg][sex] = s.alphaDBMean; alphaDBSD[stg][sex] = s.alphaDBSD; + } + if (s.betaDBMean >= 1.0 && s.betaDBSD > 0.0) { + betaDBMean[stg][sex] = s.betaDBMean; betaDBSD[stg][sex] = s.betaDBSD; + } + } } -void Species::setSMSParams(const short stg,const short sex,const trfrSMSParams s) { -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only -{ - if (s.dpMean >= 1.0 && s.dpSD > 0.0) { - dpMean[stg][sex] = s.dpMean; dpSD[stg][sex] = s.dpSD; +trfrSMSParams Species::getSMSParams(short stg, short sex) { + trfrSMSParams s; + //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only + { + s.dpMean = dpMean[stg][sex]; s.dpSD = dpSD[stg][sex]; + s.gbMean = gbMean[stg][sex]; s.gbSD = gbSD[stg][sex]; + s.alphaDBMean = alphaDBMean[stg][sex]; s.alphaDBSD = alphaDBSD[stg][sex]; + s.betaDBMean = betaDBMean[stg][sex]; s.betaDBSD = betaDBSD[stg][sex]; + s.dpScale = dpScale; s.gbScale = gbScale; + s.alphaDBScale = alphaDBScale; s.betaDBScale = betaDBScale; } - if (s.gbMean >= 1.0 && s.gbSD > 0.0) { - gbMean[stg][sex] = s.gbMean; gbSD[stg][sex] = s.gbSD; - } - if (s.alphaDBMean > 0.0 && s.alphaDBSD > 0.0) { - alphaDBMean[stg][sex] = s.alphaDBMean; alphaDBSD[stg][sex] = s.alphaDBSD; - } - if (s.betaDBMean >= 1.0 && s.betaDBSD > 0.0) { - betaDBMean[stg][sex] = s.betaDBMean; betaDBSD[stg][sex] = s.betaDBSD; + else { + s.dpMean = 1.0; s.dpSD = 0.1f; s.dpScale = 0.1f; + s.gbMean = 1.0; s.gbSD = 0.1f; s.gbScale = 0.1f; + s.alphaDBMean = 1.0; s.alphaDBSD = 0.1f; s.alphaDBScale = 0.1f; + s.betaDBMean = 10.0; s.betaDBSD = 1.0; s.betaDBScale = 1.0; } -} + return s; } -trfrSMSParams Species::getSMSParams(short stg,short sex) { -trfrSMSParams s; -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only -{ - s.dpMean = dpMean[stg][sex]; s.dpSD = dpSD[stg][sex]; - s.gbMean = gbMean[stg][sex]; s.gbSD = gbSD[stg][sex]; - s.alphaDBMean = alphaDBMean[stg][sex]; s.alphaDBSD = alphaDBSD[stg][sex]; - s.betaDBMean = betaDBMean[stg][sex]; s.betaDBSD = betaDBSD[stg][sex]; - s.dpScale = dpScale; s.gbScale = gbScale; - s.alphaDBScale = alphaDBScale; s.betaDBScale = betaDBScale; -} -else { - s.dpMean = 1.0; s.dpSD = 0.1f; s.dpScale = 0.1f; - s.gbMean = 1.0; s.gbSD = 0.1f; s.gbScale = 0.1f; - s.alphaDBMean = 1.0; s.alphaDBSD = 0.1f; s.alphaDBScale = 0.1f; - s.betaDBMean = 10.0; s.betaDBSD = 1.0; s.betaDBScale = 1.0; -} -return s; +void Species::setCRWParams(const short stg, const short sex, const trfrCRWParams m) { + //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only + { + if (m.stepLgthMean > 0.0 && m.stepLgthSD > 0.0) { + stepLgthMean[stg][sex] = m.stepLgthMean; stepLgthSD[stg][sex] = m.stepLgthSD; + } + if (m.rhoMean > 0.0 && m.rhoMean < 1.0 && m.rhoSD > 0.0 && m.rhoSD < 1.0) { + rhoMean[stg][sex] = m.rhoMean; rhoSD[stg][sex] = m.rhoSD; + } + } } -void Species::setCRWParams(const short stg,const short sex,const trfrCRWParams m) { -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only -{ - if (m.stepLgthMean > 0.0 && m.stepLgthSD > 0.0) { - stepLgthMean[stg][sex] = m.stepLgthMean; stepLgthSD[stg][sex] = m.stepLgthSD; +trfrCRWParams Species::getCRWParams(short stg, short sex) { + trfrCRWParams m; + //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only + { + m.stepLgthMean = stepLgthMean[stg][sex]; m.stepLgthSD = stepLgthSD[stg][sex]; + m.rhoMean = rhoMean[stg][sex]; m.rhoSD = rhoSD[stg][sex]; + m.stepLScale = stepLScale; m.rhoScale = rhoScale; } - if (m.rhoMean > 0.0 && m.rhoMean < 1.0 && m.rhoSD > 0.0 && m.rhoSD < 1.0 ) { - rhoMean[stg][sex] = m.rhoMean; rhoSD[stg][sex] = m.rhoSD; + else { + m.stepLgthMean = 1.0; m.stepLgthSD = 0.1f; m.stepLScale = 0.1f; + m.rhoMean = 0.5; m.rhoSD = 0.1f; m.rhoScale = 0.1f; } -} -} - -trfrCRWParams Species::getCRWParams(short stg,short sex) { -trfrCRWParams m; -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only -{ - m.stepLgthMean = stepLgthMean[stg][sex]; m.stepLgthSD = stepLgthSD[stg][sex]; - m.rhoMean = rhoMean[stg][sex]; m.rhoSD = rhoSD[stg][sex]; - m.stepLScale = stepLScale; m.rhoScale = rhoScale; -} -else { - m.stepLgthMean = 1.0; m.stepLgthSD = 0.1f; m.stepLScale = 0.1f; - m.rhoMean = 0.5; m.rhoSD = 0.1f; m.rhoScale = 0.1f; -} -return m; + return m; } void Species::setTrfrScales(const trfrScales s) { -if (s.dist1Scale >= 0.0) dist1Scale = s.dist1Scale; -if (s.dist2Scale >= 0.0) dist2Scale = s.dist2Scale; -if (s.PKern1Scale > 0.0 && s.PKern1Scale < 1.0) PKern1Scale = s.PKern1Scale; -if (s.dpScale > 0.0) dpScale = s.dpScale; -if (s.gbScale > 0.0) gbScale = s.gbScale; -if (s.alphaDBScale > 0.0) alphaDBScale = s.alphaDBScale; -if (s.betaDBScale > 0.0) betaDBScale = s.betaDBScale; -if (s.stepLScale > 0.0) stepLScale = s.stepLScale; -if (s.rhoScale > 0.0 && s.rhoScale < 1.0) rhoScale = s.rhoScale; + if (s.dist1Scale >= 0.0) dist1Scale = s.dist1Scale; + if (s.dist2Scale >= 0.0) dist2Scale = s.dist2Scale; + if (s.PKern1Scale > 0.0 && s.PKern1Scale < 1.0) PKern1Scale = s.PKern1Scale; + if (s.dpScale > 0.0) dpScale = s.dpScale; + if (s.gbScale > 0.0) gbScale = s.gbScale; + if (s.alphaDBScale > 0.0) alphaDBScale = s.alphaDBScale; + if (s.betaDBScale > 0.0) betaDBScale = s.betaDBScale; + if (s.stepLScale > 0.0) stepLScale = s.stepLScale; + if (s.rhoScale > 0.0 && s.rhoScale < 1.0) rhoScale = s.rhoScale; } trfrScales Species::getTrfrScales(void) { -trfrScales s; -s.dist1Scale = dist1Scale; s.dist2Scale = dist2Scale; s.PKern1Scale = PKern1Scale; -s.dpScale = dpScale; s.gbScale = gbScale; -s.alphaDBScale = alphaDBScale; s.betaDBScale = betaDBScale; -s.stepLScale = stepLScale; s.rhoScale = rhoScale; -return s; + trfrScales s; + s.dist1Scale = dist1Scale; s.dist2Scale = dist2Scale; s.PKern1Scale = PKern1Scale; + s.dpScale = dpScale; s.gbScale = gbScale; + s.alphaDBScale = alphaDBScale; s.betaDBScale = betaDBScale; + s.stepLScale = stepLScale; s.rhoScale = rhoScale; + return s; } short Species::getMovtHabDim() { return habDimTrfr; } void Species::createHabCostMort(short nhab) { -if (nhab >= 0) { - habDimTrfr = nhab; - if (habCost != 0 || habStepMort != 0) deleteHabCostMort(); - habCost = new int[nhab]; - habStepMort = new double[nhab]; - for (int i = 0; i < nhab; i++) { - habCost[i] = 1; habStepMort[i] = 0.0; + if (nhab >= 0) { + habDimTrfr = nhab; + if (habCost != 0 || habStepMort != 0) deleteHabCostMort(); + habCost = new int[nhab]; + habStepMort = new double[nhab]; + for (int i = 0; i < nhab; i++) { + habCost[i] = 1; habStepMort[i] = 0.0; + } } } -} -void Species::setHabCost(short hab,int cost) { -if (hab >= 0 && hab < habDimTrfr) { - if (cost >= 1) habCost[hab] = cost; -} +void Species::setHabCost(short hab, int cost) { + if (hab >= 0 && hab < habDimTrfr) { + if (cost >= 1) habCost[hab] = cost; + } } -void Species::setHabMort(short hab,double mort) { -if (hab >= 0 && hab < habDimTrfr) { - if (mort >= 0.0 && mort < 1.0) habStepMort[hab] = mort; -} +void Species::setHabMort(short hab, double mort) { + if (hab >= 0 && hab < habDimTrfr) { + if (mort >= 0.0 && mort < 1.0) habStepMort[hab] = mort; + } } int Species::getHabCost(short hab) { -int cost = 0; -if (hab >= 0 && hab < habDimTrfr) cost = habCost[hab]; -return cost; + int cost = 0; + if (hab >= 0 && hab < habDimTrfr) cost = habCost[hab]; + return cost; } double Species::getHabMort(short hab) { -double pmort = 0.0; -if (hab >= 0 && hab < habDimTrfr) pmort = habStepMort[hab]; -return pmort; + double pmort = 0.0; + if (hab >= 0 && hab < habDimTrfr) pmort = habStepMort[hab]; + return pmort; } void Species::deleteHabCostMort(void) { -if (habCost != 0) { - delete[] habCost; habCost = 0; -} -if (habStepMort != 0) { - delete[] habStepMort; habStepMort = 0; -} + if (habCost != 0) { + delete[] habCost; habCost = 0; + } + if (habStepMort != 0) { + delete[] habStepMort; habStepMort = 0; + } } //--------------------------------------------------------------------------- @@ -1333,120 +1333,120 @@ if (habStepMort != 0) { // Settlement functions void Species::setSettle(const settleType s) { -stgDepSett = s.stgDep; sexDepSett = s.sexDep; indVarSett = s.indVar; + stgDepSett = s.stgDep; sexDepSett = s.sexDep; indVarSett = s.indVar; } settleType Species::getSettle(void) { -settleType s; -s.stgDep = stgDepSett; s.sexDep = sexDepSett; s.indVar = indVarSett; -s.settTrait[0] = settTrait[0]; s.settTrait[1] = settTrait[1]; -return s; + settleType s; + s.stgDep = stgDepSett; s.sexDep = sexDepSett; s.indVar = indVarSett; + s.settTrait[0] = settTrait[0]; s.settTrait[1] = settTrait[1]; + return s; } -void Species::setSettRules(const short stg,const short sex,const settleRules s) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - densDepSett[stg][sex] = s.densDep; wait[stg][sex] = s.wait; - go2nbrLocn[stg][sex] = s.go2nbrLocn; findMate[stg][sex] = s.findMate; -} +void Species::setSettRules(const short stg, const short sex, const settleRules s) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + densDepSett[stg][sex] = s.densDep; wait[stg][sex] = s.wait; + go2nbrLocn[stg][sex] = s.go2nbrLocn; findMate[stg][sex] = s.findMate; + } } -settleRules Species::getSettRules(short stg,short sex) { -settleRules s; -s.densDep = false; -s.findMate = false; -s.go2nbrLocn = false; -s.wait = false; -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - s.densDep = densDepSett[stg][sex]; s.wait = wait[stg][sex]; - s.go2nbrLocn = go2nbrLocn[stg][sex]; s.findMate = findMate[stg][sex]; -} -return s; +settleRules Species::getSettRules(short stg, short sex) { + settleRules s; + s.densDep = false; + s.findMate = false; + s.go2nbrLocn = false; + s.wait = false; + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + s.densDep = densDepSett[stg][sex]; s.wait = wait[stg][sex]; + s.go2nbrLocn = go2nbrLocn[stg][sex]; s.findMate = findMate[stg][sex]; + } + return s; } -void Species::setSteps(const short stg,const short sex,const settleSteps s) { -if (stg == 0 && sex == 0) { - if (s.minSteps >= 0) minSteps = s.minSteps; - else minSteps = 0; - if (s.maxSteps >= 1) maxSteps = s.maxSteps; - else maxSteps = 99999999; -} -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - if (s.maxStepsYr >= 1) maxStepsYr[stg][sex] = s.maxStepsYr; - else maxStepsYr[stg][sex] = 99999999; -} +void Species::setSteps(const short stg, const short sex, const settleSteps s) { + if (stg == 0 && sex == 0) { + if (s.minSteps >= 0) minSteps = s.minSteps; + else minSteps = 0; + if (s.maxSteps >= 1) maxSteps = s.maxSteps; + else maxSteps = 99999999; + } + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (s.maxStepsYr >= 1) maxStepsYr[stg][sex] = s.maxStepsYr; + else maxStepsYr[stg][sex] = 99999999; + } } -settleSteps Species::getSteps(short stg,short sex) { -settleSteps s; -s.minSteps = minSteps; -s.maxSteps = maxSteps; -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) s.maxStepsYr = maxStepsYr[stg][sex]; -else s.maxStepsYr = 99999999; -return s; +settleSteps Species::getSteps(short stg, short sex) { + settleSteps s; + s.minSteps = minSteps; + s.maxSteps = maxSteps; + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) s.maxStepsYr = maxStepsYr[stg][sex]; + else s.maxStepsYr = 99999999; + return s; } -void Species::setSettTraits(const short stg,const short sex,const settleTraits dd) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - if (dd.s0 > 0.0 && dd.s0 <= 1.0 ) s0[stg][sex] = dd.s0; - alphaS[stg][sex] = dd.alpha; betaS[stg][sex] = dd.beta; -} +void Species::setSettTraits(const short stg, const short sex, const settleTraits dd) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (dd.s0 > 0.0 && dd.s0 <= 1.0) s0[stg][sex] = dd.s0; + alphaS[stg][sex] = dd.alpha; betaS[stg][sex] = dd.beta; + } } -settleTraits Species::getSettTraits(short stg,short sex) { -settleTraits dd; -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - dd.s0 = s0[stg][sex]; dd.alpha = alphaS[stg][sex]; dd.beta = betaS[stg][sex]; -} -else { dd.s0 = 1.0; dd.alpha = dd.beta = 0.0; } -return dd; +settleTraits Species::getSettTraits(short stg, short sex) { + settleTraits dd; + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + dd.s0 = s0[stg][sex]; dd.alpha = alphaS[stg][sex]; dd.beta = betaS[stg][sex]; + } + else { dd.s0 = 1.0; dd.alpha = dd.beta = 0.0; } + return dd; +} + +void Species::setSettParams(const short stg, const short sex, const settParams s) { + //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only + { + if (s.s0Mean >= 0.0 && s.s0Mean < 1.0) s0Mean[stg][sex] = s.s0Mean; + if (s.s0SD > 0.0 && s.s0SD < 1.0) s0SD[stg][sex] = s.s0SD; + alphaSMean[stg][sex] = s.alphaSMean; + if (s.alphaSSD > 0.0) alphaSSD[stg][sex] = s.alphaSSD; + betaSMean[stg][sex] = s.betaSMean; + if (s.betaSSD > 0.0) betaSSD[stg][sex] = s.betaSSD; + if (sex == 0) { + if (s.s0Scale > 0.0 && s.s0Scale < 1.0) s0Scale = s.s0Scale; + if (s.alphaSScale > 0.0) alphaSScale = s.alphaSScale; + if (s.betaSScale > 0.0) betaSScale = s.betaSScale; + } + } } -void Species::setSettParams(const short stg,const short sex,const settParams s) { -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only -{ - if (s.s0Mean >= 0.0 && s.s0Mean < 1.0) s0Mean[stg][sex] = s.s0Mean; - if (s.s0SD > 0.0 && s.s0SD < 1.0) s0SD[stg][sex] = s.s0SD; - alphaSMean[stg][sex] = s.alphaSMean; - if (s.alphaSSD > 0.0) alphaSSD[stg][sex] = s.alphaSSD; - betaSMean[stg][sex] = s.betaSMean; - if (s.betaSSD > 0.0) betaSSD[stg][sex] = s.betaSSD; - if (sex == 0) { - if (s.s0Scale > 0.0 && s.s0Scale < 1.0) s0Scale = s.s0Scale; - if (s.alphaSScale > 0.0) alphaSScale = s.alphaSScale; - if (s.betaSScale > 0.0) betaSScale = s.betaSScale; - } -} -} - -settParams Species::getSettParams(short stg,short sex) { -settParams s; -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only -{ - s.s0Mean = s0Mean[stg][sex]; s.s0SD = s0SD[stg][sex]; - s.alphaSMean = alphaSMean[stg][sex]; s.alphaSSD = alphaSSD[stg][sex]; - s.betaSMean = betaSMean[stg][sex]; s.betaSSD = betaSSD[stg][sex]; -} -else { - s.s0Mean = s.alphaSMean = s.betaSMean = s.s0SD = s.alphaSSD = s.betaSSD = 0.0; -} -s.s0Scale = s0Scale; -s.alphaSScale = alphaSScale; -s.betaSScale = betaSScale; -return s; +settParams Species::getSettParams(short stg, short sex) { + settParams s; + //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only + { + s.s0Mean = s0Mean[stg][sex]; s.s0SD = s0SD[stg][sex]; + s.alphaSMean = alphaSMean[stg][sex]; s.alphaSSD = alphaSSD[stg][sex]; + s.betaSMean = betaSMean[stg][sex]; s.betaSSD = betaSSD[stg][sex]; + } + else { + s.s0Mean = s.alphaSMean = s.betaSMean = s.s0SD = s.alphaSSD = s.betaSSD = 0.0; + } + s.s0Scale = s0Scale; + s.alphaSScale = alphaSScale; + s.betaSScale = betaSScale; + return s; } void Species::setSettScales(const settScales s) { -if (s.s0Scale >= 0.0 && s.s0Scale < 1.0 ) s0Scale = s.s0Scale; -if (s.alphaSScale >= 0.0) alphaSScale = s.alphaSScale; -if (s.betaSScale >= 0.0) betaSScale = s.betaSScale; + if (s.s0Scale >= 0.0 && s.s0Scale < 1.0) s0Scale = s.s0Scale; + if (s.alphaSScale >= 0.0) alphaSScale = s.alphaSScale; + if (s.betaSScale >= 0.0) betaSScale = s.betaSScale; } settScales Species::getSettScales(void) { -settScales s; -s.s0Scale = s0Scale; s.alphaSScale = alphaSScale; s.betaSScale = betaSScale; -return s; + settScales s; + s.s0Scale = s0Scale; s.alphaSScale = alphaSScale; s.betaSScale = betaSScale; + return s; } //--------------------------------------------------------------------------- diff --git a/Species.h b/Species.h index a6d0ee9..7cf3613 100644 --- a/Species.h +++ b/Species.h @@ -1,51 +1,51 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ -RangeShifter v2.0 Species -Implements the Species class + /*------------------------------------------------------------------------------ -There is ONE instance of a Species for each species within the Community -AND THIS IS CURRENTLY LIMITED TO A SINGLE SPECIES. -The class holds all the demographic and dispersal parameters of the species. + RangeShifter v2.0 Species -For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. -and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. -Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 + Implements the Species class -Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + There is ONE instance of a Species for each species within the Community + AND THIS IS CURRENTLY LIMITED TO A SINGLE SPECIES. + The class holds all the demographic and dispersal parameters of the species. -Last updated: 28 July 2021 by Greta Bocedi + For full details of RangeShifter, please see: + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. + and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial + eco-evolutionary dynamics and species’ responses to environmental changes. + Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 -------------------------------------------------------------------------------*/ + Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + + Last updated: 28 July 2021 by Greta Bocedi + + ------------------------------------------------------------------------------*/ #ifndef SpeciesH #define SpeciesH -//#if RS_RCPP && !R_CMD + //#if RS_RCPP && !R_CMD #include "../Version.h" //#endif @@ -57,7 +57,7 @@ Last updated: 28 July 2021 by Greta Bocedi // structures for demographic parameters struct demogrParams { - short repType; + short repType; short repSeasons; float propMales; float harem; float bc; float lambda; bool stageStruct; @@ -77,23 +77,23 @@ struct densDepParams { struct genomeData { int nLoci; bool diploid; bool neutralMarkers; bool pleiotropic; bool trait1Chromosome; - double probMutn,probCrossover,alleleSD,mutationSD; -} ; + double probMutn, probCrossover, alleleSD, mutationSD; +}; struct traitAllele { short chromo; short locus; -} ; +}; struct traitMap { short nAlleles; - traitAllele **traitalleles; -} ; + traitAllele** traitalleles; +}; struct traitData { short nTraitMaps; - traitMap **traitmaps; - traitMap *neutralloci; -} ; + traitMap** traitmaps; + traitMap* neutralloci; +}; // structures for emigration parameters @@ -117,10 +117,10 @@ struct emigScales { // structures for transfer parameters struct trfrRules { - bool moveModel; bool stgDep; bool sexDep; + bool moveModel; bool stgDep; bool sexDep; bool distMort; bool indVar; - bool twinKern; - bool habMort; + bool twinKern; + bool habMort; short moveType; bool costMap; short movtTrait[2]; }; @@ -171,7 +171,7 @@ struct settleType { short settTrait[2]; }; struct settleRules { - bool densDep; bool wait; bool go2nbrLocn; bool findMate; + bool densDep; bool wait; bool go2nbrLocn; bool findMate; }; struct settleSteps { int minSteps; int maxSteps; int maxStepsYr; @@ -227,7 +227,7 @@ class Species { float // survival coefficient ); densDepParams getDensDep(void); // Get development and survival coefficients - + void setFec( // Set fecundity short, // stage (must be > 0) short, // sex @@ -255,7 +255,7 @@ class Species { short, // stage short // sex ); - + float getMaxFec(void); // Get highest fecundity of any stage void setMinAge( // Set minimum age short, // stage @@ -561,14 +561,14 @@ class Species { bool survDens; bool survStageDens; bool disperseOnLoss; // individuals disperse on complete loss of patch - // (otherwise they die) + // (otherwise they die) short habDimK; // dimension of carrying capacities matrix - float *habK; // habitat-specific carrying capacities (inds/cell) + float* habK; // habitat-specific carrying capacities (inds/cell) float devCoeff; // density-dependent development coefficient float survCoeff; // density-dependent survival coefficient - float **ddwtFec; // density-dependent weights matrix for fecundity - float **ddwtDev; // density-dependent weights matrix for development - float **ddwtSurv; // density-dependent weights matrix for survival + float** ddwtFec; // density-dependent weights matrix for fecundity + float** ddwtDev; // density-dependent weights matrix for development + float** ddwtSurv; // density-dependent weights matrix for survival // NB for the following arrays, sex 0 is females, sex 1 is males float fec[NSTAGES][NSEXES]; // fecundities float dev[NSTAGES][NSEXES]; // development probabilities @@ -599,10 +599,10 @@ class Species { double alleleSD; // s.d. of initial allelic values around phenotypic value double mutationSD; // s.d. of mutation magnitude short nNLoci; // no. of nLoci set - short *nLoci; // no. of loci per chromosome + short* nLoci; // no. of loci per chromosome short nTraitNames; // no. of trait names set - traitData *traitdata; // for mapping of chromosome loci to traits - string *traitnames; // trait names for parameter output + traitData* traitdata; // for mapping of chromosome loci to traits + string* traitnames; // trait names for parameter output // emigration parameters @@ -611,8 +611,8 @@ class Species { bool sexDepEmig; // sex-dependent emigration bool indVarEmig; // individual variation in emigration short emigStage; // stage which emigrates (used for stage-strucutred population - // having individual variability in emigration probability) - // NB for the following arrays, sex 0 is females, sex 1 is males + // having individual variability in emigration probability) +// NB for the following arrays, sex 0 is females, sex 1 is males float d0[NSTAGES][NSEXES]; // maximum emigration probability float alphaEmig[NSTAGES][NSEXES]; // slope of density-dependent reaction norm float betaEmig[NSTAGES][NSEXES]; // inflection point of reaction norm (in terms of N/K) @@ -662,7 +662,7 @@ class Species { short moveType; // 1 = SMS, 2 = CRW short pr; // SMS perceptual range (cells) short prMethod; // SMS perceptual range evaluation method: - // 1 = arith. mean, 2 = harmonic mean, 3 = inverse weighted arith. mean + // 1 = arith. mean, 2 = harmonic mean, 3 = inverse weighted arith. mean short memSize; // SMS memory size (1-14 steps) short goalType; // SMS goal bias type: 0 = none, 1 = towards goal, 2 = dispersal bias float dp; // SMS directional persistence @@ -670,7 +670,7 @@ class Species { float alphaDB; // SMS dispersal bias decay rate int betaDB; // SMS dispersal bias decay inflection point (no. of steps) float stepMort; // constant per-step mortality probability for movement models - double *habStepMort; // habitat-dependent per-step mortality probability + double* habStepMort; // habitat-dependent per-step mortality probability float stepLength; // CRW step length (m) float rho; // CRW correlation coefficient double dpMean[1][NSEXES]; // mean of initial SMS directional persistence @@ -692,14 +692,14 @@ class Species { float stepLScale; // scaling factor for step length (m) float rhoScale; // scaling factor for correlation coefficient short habDimTrfr; // dimension of habitat-dependent step mortality and costs matrices - int *habCost; // habitat costs + int* habCost; // habitat costs bool costMap; // import cost map from file? bool straigtenPath; // straighten path after decision not to settle bool fullKernel; // used to indicate special case when density-independent emigration - // is 1.0, and kernel-based movement within the natal cell is used - // to determine philopatry + // is 1.0, and kernel-based movement within the natal cell is used + // to determine philopatry - // settlement parameters +// settlement parameters bool stgDepSett; bool sexDepSett; diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 26685e3..e09ceda 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "SubCommunity.h" //--------------------------------------------------------------------------- @@ -30,22 +30,22 @@ ofstream outtraits; //--------------------------------------------------------------------------- SubCommunity::SubCommunity(Patch* pPch, int num) { -subCommNum = num; -pPatch = pPch; -// record the new sub-community no. in the patch -pPatch->setSubComm((intptr)this); -initial = false; -occupancy = 0; + subCommNum = num; + pPatch = pPch; + // record the new sub-community no. in the patch + pPatch->setSubComm((intptr)this); + initial = false; + occupancy = 0; } SubCommunity::~SubCommunity() { -pPatch->setSubComm(0); -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - delete popns[i]; -} -popns.clear(); -if (occupancy != 0) delete[] occupancy; + pPatch->setSubComm(0); + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + delete popns[i]; + } + popns.clear(); + if (occupancy != 0) delete[] occupancy; } intptr SubCommunity::getNum(void) { return subCommNum; } @@ -53,192 +53,192 @@ intptr SubCommunity::getNum(void) { return subCommNum; } Patch* SubCommunity::getPatch(void) { return pPatch; } locn SubCommunity::getLocn(void) { -locn loc = pPatch->getCellLocn(0); -return loc; + locn loc = pPatch->getCellLocn(0); + return loc; } void SubCommunity::setInitial(bool b) { initial = b; } -void SubCommunity::initialise(Landscape *pLandscape,Species *pSpecies) +void SubCommunity::initialise(Landscape* pLandscape, Species* pSpecies) { -//patchLimits limits; -//locn loc; -int ncells; -landParams ppLand = pLandscape->getLandParams(); -initParams init = paramsInit->getInit(); + //patchLimits limits; + //locn loc; + int ncells; + landParams ppLand = pLandscape->getLandParams(); + initParams init = paramsInit->getInit(); #if RSDEBUG -//DEBUGLOG << "SubCommunity::initialise(): subCommNum=" << subCommNum -// << " seedType="<< init.seedType -// << " popns.size()="<< popns.size() -// << endl; + //DEBUGLOG << "SubCommunity::initialise(): subCommNum=" << subCommNum + // << " seedType="<< init.seedType + // << " popns.size()="<< popns.size() + // << endl; #endif // determine size of initial population //int hx,nInds; -int nInds = 0; -if (subCommNum == 0 // matrix patch -|| !initial) // not in initial region or distribution - nInds = 0; -else { - float k = pPatch->getK(); - if (k > 0.0) { // patch is currently suitable for this species - switch (init.initDens) { - case 0: // at carrying capacity - nInds = (int)k; - break; - case 1: // at half carrying capacity - nInds = (int)(k/2.0); - break; - case 2: // specified no. per cell or density - ncells = pPatch->getNCells(); - if (ppLand.patchModel) { - nInds = (int)(init.indsHa * (float)(ncells*ppLand.resol*ppLand.resol) / 10000.0); - } - else { - nInds = init.indsCell * ncells; + int nInds = 0; + if (subCommNum == 0 // matrix patch + || !initial) // not in initial region or distribution + nInds = 0; + else { + float k = pPatch->getK(); + if (k > 0.0) { // patch is currently suitable for this species + switch (init.initDens) { + case 0: // at carrying capacity + nInds = (int)k; + break; + case 1: // at half carrying capacity + nInds = (int)(k / 2.0); + break; + case 2: // specified no. per cell or density + ncells = pPatch->getNCells(); + if (ppLand.patchModel) { + nInds = (int)(init.indsHa * (float)(ncells * ppLand.resol * ppLand.resol) / 10000.0); + } + else { + nInds = init.indsCell * ncells; + } + break; } - break; } + else nInds = 0; } - else nInds = 0; -} -// create new population (even if it has no individuals) -//popns.push_back(new Population(pSpecies,pPatch,nInds)); -//newPopn(pSpecies,pPatch,nInds); + // create new population (even if it has no individuals) + //popns.push_back(new Population(pSpecies,pPatch,nInds)); + //newPopn(pSpecies,pPatch,nInds); -// create new population only if it is non-zero or the matrix popn -if (subCommNum == 0 || nInds > 0) { - newPopn(pLandscape,pSpecies,pPatch,nInds); -} + // create new population only if it is non-zero or the matrix popn + if (subCommNum == 0 || nInds > 0) { + newPopn(pLandscape, pSpecies, pPatch, nInds); + } } // initialise a specified individual -void SubCommunity::initialInd(Landscape *pLandscape,Species *pSpecies, - Patch *pPatch,Cell *pCell,int ix) +void SubCommunity::initialInd(Landscape* pLandscape, Species* pSpecies, + Patch* pPatch, Cell* pCell, int ix) { -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -genomeData gen = pSpecies->getGenomeData(); -short stg,age,repInt; -Individual *pInd; -float probmale; -// bool movt; -// short moveType; - -// create new population if not already in existence -int npopns = (int)popns.size(); -if (npopns < 1) { - newPopn(pLandscape,pSpecies,pPatch,0); -} - -// create new individual -initInd iind = paramsInit->getInitInd(ix); -if (dem.stageStruct) { - stg = iind.stage; age = iind.age; repInt = sstruct.repInterval; -} -else { - age = stg = 1; repInt = 0; -} -if (dem.repType == 0) { - probmale = 0.0; -} -else { - if (iind.sex == 1) probmale = 1.0; else probmale = 0.0; -} -//if (trfr.moveModel) { -// movt = true; -// if (trfr.moveType) { -// -// } -//} -pInd = new Individual(pCell,pPatch,stg,age,repInt,probmale,trfr.moveModel,trfr.moveType); - -// add new individual to the population -// NB THIS WILL NEED TO BE CHANGED FOR MULTIPLE SPECIES... -popns[0]->recruit(pInd); + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + genomeData gen = pSpecies->getGenomeData(); + short stg, age, repInt; + Individual* pInd; + float probmale; + // bool movt; + // short moveType; + + // create new population if not already in existence + int npopns = (int)popns.size(); + if (npopns < 1) { + newPopn(pLandscape, pSpecies, pPatch, 0); + } -if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) -{ - // individual variation - set up genetics - landData land = pLandscape->getLandData(); - pInd->setGenes(pSpecies,land.resol); -} + // create new individual + initInd iind = paramsInit->getInitInd(ix); + if (dem.stageStruct) { + stg = iind.stage; age = iind.age; repInt = sstruct.repInterval; + } + else { + age = stg = 1; repInt = 0; + } + if (dem.repType == 0) { + probmale = 0.0; + } + else { + if (iind.sex == 1) probmale = 1.0; else probmale = 0.0; + } + //if (trfr.moveModel) { + // movt = true; + // if (trfr.moveType) { + // + // } + //} + pInd = new Individual(pCell, pPatch, stg, age, repInt, probmale, trfr.moveModel, trfr.moveType); + + // add new individual to the population + // NB THIS WILL NEED TO BE CHANGED FOR MULTIPLE SPECIES... + popns[0]->recruit(pInd); + + if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) + { + // individual variation - set up genetics + landData land = pLandscape->getLandData(); + pInd->setGenes(pSpecies, land.resol); + } } // Create a new population, and return its address -Population* SubCommunity::newPopn(Landscape *pLandscape,Species *pSpecies, - Patch *pPatch,int nInds) +Population* SubCommunity::newPopn(Landscape* pLandscape, Species* pSpecies, + Patch* pPatch, int nInds) { #if RSDEBUG -//DEBUGLOG << "SubCommunity::newPopn(): subCommNum = " << subCommNum -// << " pPatch = " << pPatch << " nInds = "<< nInds << endl; + //DEBUGLOG << "SubCommunity::newPopn(): subCommNum = " << subCommNum + // << " pPatch = " << pPatch << " nInds = "<< nInds << endl; #endif -landParams land = pLandscape->getLandParams(); -int npopns = (int)popns.size(); -popns.push_back(new Population(pSpecies,pPatch,nInds,land.resol)); + landParams land = pLandscape->getLandParams(); + int npopns = (int)popns.size(); + popns.push_back(new Population(pSpecies, pPatch, nInds, land.resol)); #if RSDEBUG -//DEBUGLOG << "SubCommunity::newPopn(): subCommNum = " << subCommNum -// << " npopns = " << npopns << " popns[npopns] = " << popns[npopns] -// << endl; + //DEBUGLOG << "SubCommunity::newPopn(): subCommNum = " << subCommNum + // << " npopns = " << npopns << " popns[npopns] = " << popns[npopns] + // << endl; #endif -return popns[npopns]; + return popns[npopns]; } popStats SubCommunity::getPopStats(void) { -popStats p,pop; -p.pSpecies = 0; p.spNum = 0; p.nInds = p.nAdults = p.nNonJuvs = 0; p.breeding = false; -p.pPatch = pPatch; -// FOR SINGLE SPECIES IMPLEMENTATION, THERE IS ONLY ONE POPULATION IN THE PATCH -//p = popns[0]->getStats(); -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations + popStats p, pop; + p.pSpecies = 0; p.spNum = 0; p.nInds = p.nAdults = p.nNonJuvs = 0; p.breeding = false; + p.pPatch = pPatch; + // FOR SINGLE SPECIES IMPLEMENTATION, THERE IS ONLY ONE POPULATION IN THE PATCH + //p = popns[0]->getStats(); + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations #if RSDEBUG -//DEBUGLOG << "SubCommunity::getPopStats(): npops = " << npops -// << " i = " << i -// << " popns[i] = " << popns[i] << endl; + //DEBUGLOG << "SubCommunity::getPopStats(): npops = " << npops + // << " i = " << i + // << " popns[i] = " << popns[i] << endl; #endif - pop = popns[i]->getStats(); - p.pSpecies = pop.pSpecies; - p.spNum = pop.spNum; - p.nInds += pop.nInds; - p.nNonJuvs += pop.nNonJuvs; - p.nAdults += pop.nAdults; - p.breeding = pop.breeding; + pop = popns[i]->getStats(); + p.pSpecies = pop.pSpecies; + p.spNum = pop.spNum; + p.nInds += pop.nInds; + p.nNonJuvs += pop.nNonJuvs; + p.nAdults += pop.nAdults; + p.breeding = pop.breeding; #if RSDEBUG -//DEBUGLOG << "SubCommunity::getPopStats():" -// << " p.pSpecies = " << p.pSpecies -// << " p.pPatch = " << p.pPatch -// << " p.spNum = " << p.spNum -// << " p.nInds = " << p.nInds -// << endl; + //DEBUGLOG << "SubCommunity::getPopStats():" + // << " p.pSpecies = " << p.pSpecies + // << " p.pPatch = " << p.pPatch + // << " p.spNum = " << p.spNum + // << " p.nInds = " << p.nInds + // << endl; #endif -} -return p; + } + return p; } void SubCommunity::resetPopns(void) { -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - delete popns[i]; -} -popns.clear(); -// clear the list of populations in the corresponding patch -pPatch->resetPopn(); + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + delete popns[i]; + } + popns.clear(); + // clear the list of populations in the corresponding patch + pPatch->resetPopn(); } void SubCommunity::resetPossSettlers(void) { -if (subCommNum == 0) return; // not applicable in the matrix -//int npops = (int)popns.size(); -//for (int i = 0; i < npops; i++) { // all populations -// popns[i]->resetPossSettlers(); -//} -pPatch->resetPossSettlers(); + if (subCommNum == 0) return; // not applicable in the matrix + //int npops = (int)popns.size(); + //for (int i = 0; i < npops; i++) { // all populations + // popns[i]->resetPossSettlers(); + //} + pPatch->resetPossSettlers(); } // Extirpate all populations according to @@ -246,225 +246,225 @@ pPatch->resetPossSettlers(); // option 1 - local extinction probability gradient // NB only applied for cell-based model void SubCommunity::localExtinction(int option) { -double pExtinct = 0.0; -if (option == 0) { - envStochParams env = paramsStoch->getStoch(); - if (env.localExt) pExtinct = env.locExtProb; -} -else { - envGradParams grad = paramsGrad->getGradient(); - Cell *pCell = pPatch->getRandomCell(); // get only cell in the patch - // extinction prob is complement of cell gradient value plus any non-zero prob at the optimum - pExtinct = 1.0 - pCell->getEnvVal() + grad.extProbOpt; - if (pExtinct > 1.0) pExtinct = 1.0; -} -if (pRandom->Bernoulli(pExtinct)) { - int npops = (int)popns.size(); - for (int i = 0; i < npops; i++) { // all populations - popns[i]->extirpate(); + double pExtinct = 0.0; + if (option == 0) { + envStochParams env = paramsStoch->getStoch(); + if (env.localExt) pExtinct = env.locExtProb; + } + else { + envGradParams grad = paramsGrad->getGradient(); + Cell* pCell = pPatch->getRandomCell(); // get only cell in the patch + // extinction prob is complement of cell gradient value plus any non-zero prob at the optimum + pExtinct = 1.0 - pCell->getEnvVal() + grad.extProbOpt; + if (pExtinct > 1.0) pExtinct = 1.0; + } + if (pRandom->Bernoulli(pExtinct)) { + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + popns[i]->extirpate(); + } } -} } // Action in event of patch becoming unsuitable owing to landscape change void SubCommunity::patchChange(void) { -if (subCommNum == 0) return; // no reproduction in the matrix -Species *pSpecies; -float localK = 0.0; -int npops = (int)popns.size(); -// THE FOLLOWING MAY BE MORE EFFICIENT WHILST THERE IS ONLY ONE SPECIES ... -if (npops < 1) return; -localK = pPatch->getK(); -if (localK <= 0.0) { // patch in dynamic landscape has become unsuitable - for (int i = 0; i < npops; i++) { // all populations - pSpecies = popns[i]->getSpecies(); - demogrParams dem = pSpecies->getDemogr(); - if (dem.stageStruct) { - stageParams sstruct = pSpecies->getStage(); - if (sstruct.disperseOnLoss) popns[i]->allEmigrate(); - else popns[i]->extirpate(); - } - else { // non-stage-structured species is destroyed - popns[i]->extirpate(); + if (subCommNum == 0) return; // no reproduction in the matrix + Species* pSpecies; + float localK = 0.0; + int npops = (int)popns.size(); + // THE FOLLOWING MAY BE MORE EFFICIENT WHILST THERE IS ONLY ONE SPECIES ... + if (npops < 1) return; + localK = pPatch->getK(); + if (localK <= 0.0) { // patch in dynamic landscape has become unsuitable + for (int i = 0; i < npops; i++) { // all populations + pSpecies = popns[i]->getSpecies(); + demogrParams dem = pSpecies->getDemogr(); + if (dem.stageStruct) { + stageParams sstruct = pSpecies->getStage(); + if (sstruct.disperseOnLoss) popns[i]->allEmigrate(); + else popns[i]->extirpate(); + } + else { // non-stage-structured species is destroyed + popns[i]->extirpate(); + } } } } -} -void SubCommunity::reproduction(int resol,float epsGlobal,short rasterType,bool patchModel) +void SubCommunity::reproduction(int resol, float epsGlobal, short rasterType, bool patchModel) { -if (subCommNum == 0) return; // no reproduction in the matrix -float localK,envval; -//Species *pSpecies; -Cell *pCell; -envGradParams grad = paramsGrad->getGradient(); -envStochParams env = paramsStoch->getStoch(); - -int npops = (int)popns.size(); -// THE FOLLOWING MAY BE MORE EFFICIENT WHILST THERE IS ONLY ONE SPECIES ... -if (npops < 1) return; - -localK = pPatch->getK(); -if (localK > 0.0) { - if (patchModel) { - envval = 1.0; // environmental gradient is currently not applied for patch-based model - } - else { // cell-based model - if (grad.gradient && grad.gradType == 2) - { // gradient in fecundity - Cell *pCell = pPatch->getRandomCell(); // locate the only cell in the patch - envval = pCell->getEnvVal(); + if (subCommNum == 0) return; // no reproduction in the matrix + float localK, envval; + //Species *pSpecies; + Cell* pCell; + envGradParams grad = paramsGrad->getGradient(); + envStochParams env = paramsStoch->getStoch(); + + int npops = (int)popns.size(); + // THE FOLLOWING MAY BE MORE EFFICIENT WHILST THERE IS ONLY ONE SPECIES ... + if (npops < 1) return; + + localK = pPatch->getK(); + if (localK > 0.0) { + if (patchModel) { + envval = 1.0; // environmental gradient is currently not applied for patch-based model } - else envval = 1.0; - } - if (env.stoch && !env.inK) { // stochasticity in fecundity - if (env.local) { - if (!patchModel) { // only permitted for cell-based model - pCell = pPatch->getRandomCell(); - if (pCell != 0) envval += pCell->getEps(); + else { // cell-based model + if (grad.gradient && grad.gradType == 2) + { // gradient in fecundity + Cell* pCell = pPatch->getRandomCell(); // locate the only cell in the patch + envval = pCell->getEnvVal(); } + else envval = 1.0; } - else { // global stochasticity - envval += epsGlobal; + if (env.stoch && !env.inK) { // stochasticity in fecundity + if (env.local) { + if (!patchModel) { // only permitted for cell-based model + pCell = pPatch->getRandomCell(); + if (pCell != 0) envval += pCell->getEps(); + } + } + else { // global stochasticity + envval += epsGlobal; + } } - } - for (int i = 0; i < npops; i++) { // all populations - popns[i]->reproduction(localK,envval,resol); - popns[i]->fledge(); - } -} -/* -else { // patch in dynamic landscape has become unsuitable - // NB - THIS WILL NEED TO BE MADE SPECIES-SPECIFIC... - Species *pSpecies; - for (int i = 0; i < npops; i++) { // all populations - pSpecies = popns[i]->getSpecies(); - demogrParams dem = pSpecies->getDemogr(); - if (dem.stageStruct) { - stageParams sstruct = pSpecies->getStage(); - if (sstruct.disperseOnLoss) popns[i]->allEmigrate(); - else popns[i]->extirpate(); + for (int i = 0; i < npops; i++) { // all populations + popns[i]->reproduction(localK, envval, resol); + popns[i]->fledge(); } - else { // non-stage-structured species is destroyed - popns[i]->extirpate(); + } + /* + else { // patch in dynamic landscape has become unsuitable + // NB - THIS WILL NEED TO BE MADE SPECIES-SPECIFIC... + Species *pSpecies; + for (int i = 0; i < npops; i++) { // all populations + pSpecies = popns[i]->getSpecies(); + demogrParams dem = pSpecies->getDemogr(); + if (dem.stageStruct) { + stageParams sstruct = pSpecies->getStage(); + if (sstruct.disperseOnLoss) popns[i]->allEmigrate(); + else popns[i]->extirpate(); + } + else { // non-stage-structured species is destroyed + popns[i]->extirpate(); + } } } -} -*/ - -/* -#if RSDEBUG -//if (npops > 0) { -// DEBUGLOG << "SubCommunity::reproduction(): this = " << this -// << " npops = " << npops << endl; -//} -#endif -#if RSDEBUG -//DEBUGLOG << "SubCommunity::reproduction(): patchNum = " << pPatch->getPatchNum() -// << " nCells " << pPatch->getNCells() -// << " localK = " << localK -// << endl; -#endif -*/ -} - -void SubCommunity::emigration(void) + */ + + /* + #if RSDEBUG + //if (npops > 0) { + // DEBUGLOG << "SubCommunity::reproduction(): this = " << this + // << " npops = " << npops << endl; + //} + #endif + #if RSDEBUG + //DEBUGLOG << "SubCommunity::reproduction(): patchNum = " << pPatch->getPatchNum() + // << " nCells " << pPatch->getNCells() + // << " localK = " << localK + // << endl; + #endif + */ +} + +void SubCommunity::emigration(void) { -if (subCommNum == 0) return; // no emigration from the matrix -float localK; -int npops = (int)popns.size(); -// THE FOLLOWING MAY BE MORE EFFICIENT WHILST THERE IS ONLY ONE SPECIES ... -if (npops < 1) return; -localK = pPatch->getK(); -// NOTE that even if K is zero, it could have been >0 in previous time-step, and there -// might be emigrants if there is non-juvenile emigration -for (int i = 0; i < npops; i++) { // all populations -// localK = pPatch->getK(); - popns[i]->emigration(localK); -} + if (subCommNum == 0) return; // no emigration from the matrix + float localK; + int npops = (int)popns.size(); + // THE FOLLOWING MAY BE MORE EFFICIENT WHILST THERE IS ONLY ONE SPECIES ... + if (npops < 1) return; + localK = pPatch->getK(); + // NOTE that even if K is zero, it could have been >0 in previous time-step, and there + // might be emigrants if there is non-juvenile emigration + for (int i = 0; i < npops; i++) { // all populations + // localK = pPatch->getK(); + popns[i]->emigration(localK); + } } // Remove emigrants from their natal patch and add to patch 0 (matrix) void SubCommunity::initiateDispersal(SubCommunity* matrix) { -if (subCommNum == 0) return; // no dispersal initiation in the matrix + if (subCommNum == 0) return; // no dispersal initiation in the matrix #if RSDEBUG -//DEBUGLOG << "SubCommunity::initiateDispersal(): this=" << this -// << " subCommNum=" << subCommNum -// << endl; + //DEBUGLOG << "SubCommunity::initiateDispersal(): this=" << this + // << " subCommNum=" << subCommNum + // << endl; #endif -popStats pop; -disperser disp; + popStats pop; + disperser disp; -int npops = (int)popns.size(); + int npops = (int)popns.size(); #if RSDEBUG -//DEBUGLOG << "SubCommunity::initiateDispersal(): patchNum = " << patchNum -// << " npops " << npops -// << endl; + //DEBUGLOG << "SubCommunity::initiateDispersal(): patchNum = " << patchNum + // << " npops " << npops + // << endl; #endif -for (int i = 0; i < npops; i++) { // all populations - pop = popns[i]->getStats(); - for (int j = 0; j < pop.nInds; j++) { + for (int i = 0; i < npops; i++) { // all populations + pop = popns[i]->getStats(); + for (int j = 0; j < pop.nInds; j++) { #if RSDEBUG -//DEBUGLOG << "SubCommunity::initiateDispersal(): i = " << i -// << " j " << j -// << endl; + //DEBUGLOG << "SubCommunity::initiateDispersal(): i = " << i + // << " j " << j + // << endl; #endif - disp = popns[i]->extractDisperser(j); - if (disp.yes) { // disperser - has already been removed from natal population - // add to matrix population - matrix->recruit(disp.pInd,pop.pSpecies); + disp = popns[i]->extractDisperser(j); + if (disp.yes) { // disperser - has already been removed from natal population + // add to matrix population + matrix->recruit(disp.pInd, pop.pSpecies); + } } + // remove pointers to emigrants + popns[i]->clean(); } - // remove pointers to emigrants - popns[i]->clean(); -} } // Add an individual into the local population of its species in the patch -void SubCommunity::recruit(Individual *pInd,Species *pSpecies) { +void SubCommunity::recruit(Individual* pInd, Species* pSpecies) { #if RSDEBUG -//DEBUGLOG << "SubCommunity::recruit(): this=" << this -// << endl; + //DEBUGLOG << "SubCommunity::recruit(): this=" << this + // << endl; #endif -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - if (pSpecies == popns[i]->getSpecies()) { - popns[i]->recruit(pInd); + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + if (pSpecies == popns[i]->getSpecies()) { + popns[i]->recruit(pInd); + } } } -} // Transfer through the matrix - run for the matrix sub-community only #if RS_RCPP // included also SEASONAL -int SubCommunity::transfer(Landscape *pLandscape,short landIx,short nextseason) +int SubCommunity::transfer(Landscape* pLandscape, short landIx, short nextseason) #else -int SubCommunity::transfer(Landscape *pLandscape,short landIx) +int SubCommunity::transfer(Landscape* pLandscape, short landIx) #endif // SEASONAL || RS_RCPP { #if RSDEBUG -//DEBUGLOG << "SubCommunity::transfer(): this=" << this -// << endl; + //DEBUGLOG << "SubCommunity::transfer(): this=" << this + // << endl; #endif -int ndispersers = 0; -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations + int ndispersers = 0; + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations #if RS_RCPP // included also SEASONAL - ndispersers += popns[i]->transfer(pLandscape,landIx,nextseason); + ndispersers += popns[i]->transfer(pLandscape, landIx, nextseason); #else - ndispersers += popns[i]->transfer(pLandscape,landIx); + ndispersers += popns[i]->transfer(pLandscape, landIx); #endif // SEASONAL || RS_RCPP #if RSDEBUG -//DEBUGLOG << "SubCommunity::transfer(): i = " << i -// << " this = " << this -// << " subCommNum = " << subCommNum -// << " npops = " << npops -// << " popns[i] = " << popns[i] -// << " ndispersers = " << ndispersers -// << endl; + //DEBUGLOG << "SubCommunity::transfer(): i = " << i + // << " this = " << this + // << " subCommNum = " << subCommNum + // << " npops = " << npops + // << " popns[i] = " << popns[i] + // << " ndispersers = " << ndispersers + // << endl; #endif -} -return ndispersers; + } + return ndispersers; } //--------------------------------------------------------------------------- @@ -473,43 +473,43 @@ return ndispersers; // in which their destination co-ordinates fall // This function is executed for the matrix patch only -void SubCommunity::completeDispersal(Landscape *pLandscape,bool connect) +void SubCommunity::completeDispersal(Landscape* pLandscape, bool connect) { #if RSDEBUG -//DEBUGLOG << "SubCommunity::completeDispersal(): this=" << this -// << endl; + //DEBUGLOG << "SubCommunity::completeDispersal(): this=" << this + // << endl; #endif //popStats pop; //int popsize,subcomm; -int popsize; -disperser settler; -Species *pSpecies; -Population *pPop; -Patch *pPrevPatch; -Patch *pNewPatch; -Cell *pPrevCell; -SubCommunity *pSubComm; - -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - pSpecies = popns[i]->getSpecies(); - popsize = popns[i]->getNInds(); + int popsize; + disperser settler; + Species* pSpecies; + Population* pPop; + Patch* pPrevPatch; + Patch* pNewPatch; + Cell* pPrevCell; + SubCommunity* pSubComm; + + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + pSpecies = popns[i]->getSpecies(); + popsize = popns[i]->getNInds(); #if RSDEBUG -//DEBUGLOG << "SubCommunity::completeDispersal(): i=" << i -// << " subCommNum=" << subCommNum -// << " pPatch=" << pPatch << " patchNum=" << pPatch->getPatchNum() -// << " npops=" << npops -// << " popns[i]=" << popns[i] -// << " popsize=" << popsize -// << endl; + //DEBUGLOG << "SubCommunity::completeDispersal(): i=" << i + // << " subCommNum=" << subCommNum + // << " pPatch=" << pPatch << " patchNum=" << pPatch->getPatchNum() + // << " npops=" << npops + // << " popns[i]=" << popns[i] + // << " popsize=" << popsize + // << endl; #endif - for (int j = 0; j < popsize; j++) { - bool settled; - settler = popns[i]->extractSettler(j); - settled = settler.yes; - if (settled) { - // settler - has already been removed from matrix population - // in popns[i]->extractSettler() + for (int j = 0; j < popsize; j++) { + bool settled; + settler = popns[i]->extractSettler(j); + settled = settler.yes; + if (settled) { + // settler - has already been removed from matrix population + // in popns[i]->extractSettler() #if RSDEBUG //locn loc = pNewCell->getLocn(); //DEBUGLOG << "SubCommunity::completeDispersal(): j=" << j << " settled=" << settled; @@ -528,139 +528,139 @@ for (int i = 0; i < npops; i++) { // all populations //DEBUGLOG << " loc.x=" << loc.x << " loc.y=" << loc.y << endl; #endif // RSDEBUG // find new patch - pNewPatch = (Patch*)settler.pCell->getPatch(); - // find population within the patch (if there is one) -// subcomm = ppatch->getSubComm(); -// if (subcomm == 0) { // no sub-community has yet been set up -// // CANNOT SET UP A NEW ONE FROM WITHIN AN EXISTING ONE!!!!! -// } - pPop = (Population*)pNewPatch->getPopn((intptr)pSpecies); + pNewPatch = (Patch*)settler.pCell->getPatch(); + // find population within the patch (if there is one) + // subcomm = ppatch->getSubComm(); + // if (subcomm == 0) { // no sub-community has yet been set up + // // CANNOT SET UP A NEW ONE FROM WITHIN AN EXISTING ONE!!!!! + // } + pPop = (Population*)pNewPatch->getPopn((intptr)pSpecies); #if RSDEBUG -//DEBUGLOG << "SubCommunity::completeDispersal(): j = " << j -// << " pCell = " << pCell << " ppatch = " << ppatch << " pPop = " << pPop -// << endl; + //DEBUGLOG << "SubCommunity::completeDispersal(): j = " << j + // << " pCell = " << pCell << " ppatch = " << ppatch << " pPop = " << pPop + // << endl; #endif - if (pPop == 0) { // settler is the first in a previously uninhabited patch - // create a new population in the corresponding sub-community - pSubComm = (SubCommunity*)pNewPatch->getSubComm(); + if (pPop == 0) { // settler is the first in a previously uninhabited patch + // create a new population in the corresponding sub-community + pSubComm = (SubCommunity*)pNewPatch->getSubComm(); #if RSDEBUG -//DEBUGLOG << "SubCommunity::completeDispersal(): j = " << j -// << " pSubComm = " << pSubComm << endl; + //DEBUGLOG << "SubCommunity::completeDispersal(): j = " << j + // << " pSubComm = " << pSubComm << endl; #endif - pPop = pSubComm->newPopn(pLandscape,pSpecies,pNewPatch,0); + pPop = pSubComm->newPopn(pLandscape, pSpecies, pNewPatch, 0); #if RSDEBUG -//DEBUGLOG << "SubCommunity::completeDispersal(): j=" << j -// << " pPop=" << pPop << endl; + //DEBUGLOG << "SubCommunity::completeDispersal(): j=" << j + // << " pPop=" << pPop << endl; #endif - } - pPop->recruit(settler.pInd); - if (connect) { // increment connectivity totals - int newpatch = pNewPatch->getSeqNum(); - pPrevCell = settler.pInd->getLocn(0); // previous cell - intptr patch = pPrevCell->getPatch(); - if (patch != 0) { - pPrevPatch = (Patch*)patch; - int prevpatch = pPrevPatch->getSeqNum(); - pLandscape->incrConnectMatrix(prevpatch,newpatch); + } + pPop->recruit(settler.pInd); + if (connect) { // increment connectivity totals + int newpatch = pNewPatch->getSeqNum(); + pPrevCell = settler.pInd->getLocn(0); // previous cell + intptr patch = pPrevCell->getPatch(); + if (patch != 0) { + pPrevPatch = (Patch*)patch; + int prevpatch = pPrevPatch->getSeqNum(); + pLandscape->incrConnectMatrix(prevpatch, newpatch); + } } } + else { // for group dispersal only + } } - else { // for group dispersal only - } - } - // remove pointers in the matrix popn to settlers - popns[i]->clean(); + // remove pointers in the matrix popn to settlers + popns[i]->clean(); #if RSDEBUG -//pop = popns[i]->getStats(); -popsize = popns[i]->getNInds(); -//DEBUGLOG << "SubCommunity::completeDispersal(): i=" << i -// << " popns[i]=" << popns[i] -//// << " pop.pPatch = " << pop.pPatch -//// << " pop.nInds = " << pop.nInds -// << " popsize=" << popsize -// << endl; + //pop = popns[i]->getStats(); + popsize = popns[i]->getNInds(); + //DEBUGLOG << "SubCommunity::completeDispersal(): i=" << i + // << " popns[i]=" << popns[i] + //// << " pop.pPatch = " << pop.pPatch + //// << " pop.nInds = " << pop.nInds + // << " popsize=" << popsize + // << endl; #endif -} + } } //--------------------------------------------------------------------------- -void SubCommunity::survival(short part,short option0,short option1) +void SubCommunity::survival(short part, short option0, short option1) { -int npops = (int)popns.size(); -if (npops < 1) return; -if (part == 0) { - float localK = pPatch->getK(); - for (int i = 0; i < npops; i++) { // all populations - popns[i]->survival0(localK,option0,option1); + int npops = (int)popns.size(); + if (npops < 1) return; + if (part == 0) { + float localK = pPatch->getK(); + for (int i = 0; i < npops; i++) { // all populations + popns[i]->survival0(localK, option0, option1); + } } -} -else { - for (int i = 0; i < npops; i++) { // all populations - popns[i]->survival1(); + else { + for (int i = 0; i < npops; i++) { // all populations + popns[i]->survival1(); + } } } -} void SubCommunity::ageIncrement(void) { -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - popns[i]->ageIncrement(); -} + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + popns[i]->ageIncrement(); + } } // Find the population of a given species in a given patch -Population* SubCommunity::findPop(Species *pSp,Patch *pPch) { +Population* SubCommunity::findPop(Species* pSp, Patch* pPch) { #if RSDEBUG -DEBUGLOG << "SubCommunity::findPop(): this=" << this - << endl; + DEBUGLOG << "SubCommunity::findPop(): this=" << this + << endl; #endif -Population *pPop = 0; -popStats pop; -int npops = (int)popns.size(); + Population* pPop = 0; + popStats pop; + int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - pop = popns[i]->getStats(); - if (pop.pSpecies == pSp && pop.pPatch == pPch) { // population located - pPop = popns[i]; - break; + for (int i = 0; i < npops; i++) { // all populations + pop = popns[i]->getStats(); + if (pop.pSpecies == pSp && pop.pPatch == pPch) { // population located + pPop = popns[i]; + break; + } + else pPop = 0; } - else pPop = 0; -} -return pPop; + return pPop; } //--------------------------------------------------------------------------- void SubCommunity::createOccupancy(int nrows) { -if (occupancy != 0) deleteOccupancy(); -if (nrows > 0) { - occupancy = new int[nrows]; - for (int i = 0; i < nrows; i++) occupancy[i] = 0; -} + if (occupancy != 0) deleteOccupancy(); + if (nrows > 0) { + occupancy = new int[nrows]; + for (int i = 0; i < nrows; i++) occupancy[i] = 0; + } } void SubCommunity::updateOccupancy(int row) { #if RSDEBUG -//DEBUGLOG << "SubCommunity::updateOccupancy(): this=" << this -// << endl; + //DEBUGLOG << "SubCommunity::updateOccupancy(): this=" << this + // << endl; #endif -popStats pop; -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { - pop = popns[i]->getStats(); - if (pop.nInds > 0 && pop.breeding) { - occupancy[row]++; - i = npops; + popStats pop; + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { + pop = popns[i]->getStats(); + if (pop.nInds > 0 && pop.breeding) { + occupancy[row]++; + i = npops; + } } } -} int SubCommunity::getOccupancy(int row) { -if (row >= 0) return occupancy[row]; -else return 0; + if (row >= 0) return occupancy[row]; + else return 0; } void SubCommunity::deleteOccupancy(void) { @@ -670,529 +670,529 @@ void SubCommunity::deleteOccupancy(void) { //--------------------------------------------------------------------------- // Open population file and write header record -bool SubCommunity::outPopHeaders(Landscape *pLandscape,Species *pSpecies,int option) +bool SubCommunity::outPopHeaders(Landscape* pLandscape, Species* pSpecies, int option) { -bool fileOK; -Population *pPop; -landParams land = pLandscape->getLandParams(); - -if (option == -999) { // close the file - // as all populations may have been deleted, set up a dummy one - // species is not necessary - pPop = new Population(); - fileOK = pPop->outPopHeaders(-999,land.patchModel); - delete pPop; -} -else { // open the file - // as no population has yet been created, set up a dummy one - // species is necessary, as columns depend on stage and sex structure - pPop = new Population(pSpecies,pPatch,0,land.resol); - fileOK = pPop->outPopHeaders(land.landNum,land.patchModel); - delete pPop; -} -return fileOK; + bool fileOK; + Population* pPop; + landParams land = pLandscape->getLandParams(); + + if (option == -999) { // close the file + // as all populations may have been deleted, set up a dummy one + // species is not necessary + pPop = new Population(); + fileOK = pPop->outPopHeaders(-999, land.patchModel); + delete pPop; + } + else { // open the file + // as no population has yet been created, set up a dummy one + // species is necessary, as columns depend on stage and sex structure + pPop = new Population(pSpecies, pPatch, 0, land.resol); + fileOK = pPop->outPopHeaders(land.landNum, land.patchModel); + delete pPop; + } + return fileOK; } // Write records to population file -void SubCommunity::outPop(Landscape *pLandscape,int rep,int yr,int gen) +void SubCommunity::outPop(Landscape* pLandscape, int rep, int yr, int gen) { -landParams land = pLandscape->getLandParams(); -envGradParams grad = paramsGrad->getGradient(); -envStochParams env = paramsStoch->getStoch(); -bool writeEnv = false; -bool gradK = false; -if (grad.gradient) { - writeEnv = true; - if (grad.gradType == 1) gradK = true; // ... carrying capacity -} -if (env.stoch) writeEnv = true; - -// generate output for each population within the sub-community (patch) -// provided that the patch is suitable (i.e. non-zero carrying capacity) -// or the population is above zero (possible if there is stochasticity or a moving gradient) -// or it is the matrix patch in a patch-based model -int npops = (int)popns.size(); -int patchnum; -//Species* pSpecies; -Cell *pCell; -float localK; -float eps = 0.0; -if (env.stoch) { - if (env.local) { - pCell = pPatch->getRandomCell(); - if (pCell != 0) eps = pCell->getEps(); - } - else { - eps = pLandscape->getGlobalStoch(yr); + landParams land = pLandscape->getLandParams(); + envGradParams grad = paramsGrad->getGradient(); + envStochParams env = paramsStoch->getStoch(); + bool writeEnv = false; + bool gradK = false; + if (grad.gradient) { + writeEnv = true; + if (grad.gradType == 1) gradK = true; // ... carrying capacity } -} + if (env.stoch) writeEnv = true; -patchnum = pPatch->getPatchNum(); -for (int i = 0; i < npops; i++) { // all populations -// pSpecies = popns[i]->getSpecies(); - localK = pPatch->getK(); - if (localK > 0.0 || (land.patchModel && patchnum == 0)) { - popns[i]->outPopulation(rep,yr,gen,eps,land.patchModel,writeEnv,gradK); + // generate output for each population within the sub-community (patch) + // provided that the patch is suitable (i.e. non-zero carrying capacity) + // or the population is above zero (possible if there is stochasticity or a moving gradient) + // or it is the matrix patch in a patch-based model + int npops = (int)popns.size(); + int patchnum; + //Species* pSpecies; + Cell* pCell; + float localK; + float eps = 0.0; + if (env.stoch) { + if (env.local) { + pCell = pPatch->getRandomCell(); + if (pCell != 0) eps = pCell->getEps(); + } + else { + eps = pLandscape->getGlobalStoch(yr); + } } - else { - if (popns[i]->totalPop() > 0) { - popns[i]->outPopulation(rep,yr,gen,eps,land.patchModel,writeEnv,gradK); + + patchnum = pPatch->getPatchNum(); + for (int i = 0; i < npops; i++) { // all populations + // pSpecies = popns[i]->getSpecies(); + localK = pPatch->getK(); + if (localK > 0.0 || (land.patchModel && patchnum == 0)) { + popns[i]->outPopulation(rep, yr, gen, eps, land.patchModel, writeEnv, gradK); + } + else { + if (popns[i]->totalPop() > 0) { + popns[i]->outPopulation(rep, yr, gen, eps, land.patchModel, writeEnv, gradK); + } } } } -} // Write records to individuals file -void SubCommunity::outInds(Landscape *pLandscape,int rep,int yr,int gen,int landNr) { -landParams ppLand = pLandscape->getLandParams(); -if (landNr >= 0) { // open the file - popns[0]->outIndsHeaders(rep,landNr,ppLand.patchModel); - return; -} -if (landNr == -999) { // close the file - popns[0]->outIndsHeaders(rep,-999,ppLand.patchModel); - return; -} -// generate output for each population within the sub-community (patch) -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - popns[i]->outIndividual(pLandscape,rep,yr,gen,pPatch->getPatchNum()); -} +void SubCommunity::outInds(Landscape* pLandscape, int rep, int yr, int gen, int landNr) { + landParams ppLand = pLandscape->getLandParams(); + if (landNr >= 0) { // open the file + popns[0]->outIndsHeaders(rep, landNr, ppLand.patchModel); + return; + } + if (landNr == -999) { // close the file + popns[0]->outIndsHeaders(rep, -999, ppLand.patchModel); + return; + } + // generate output for each population within the sub-community (patch) + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + popns[i]->outIndividual(pLandscape, rep, yr, gen, pPatch->getPatchNum()); + } } // Write records to individuals file -void SubCommunity::outGenetics(int rep,int yr,int gen,int landNr) +void SubCommunity::outGenetics(int rep, int yr, int gen, int landNr) { -//landParams ppLand = pLandscape->getLandParams(); -if (landNr >= 0) { // open the file - popns[0]->outGenetics(rep,yr,landNr); - return; -} -if (landNr == -999) { // close the file - popns[0]->outGenetics(rep,yr,landNr); - return; -} -// generate output for each population within the sub-community (patch) -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - popns[i]->outGenetics(rep,yr,landNr); -} + //landParams ppLand = pLandscape->getLandParams(); + if (landNr >= 0) { // open the file + popns[0]->outGenetics(rep, yr, landNr); + return; + } + if (landNr == -999) { // close the file + popns[0]->outGenetics(rep, yr, landNr); + return; + } + // generate output for each population within the sub-community (patch) + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + popns[i]->outGenetics(rep, yr, landNr); + } } // Population size of a specified stage int SubCommunity::stagePop(int stage) { -int popsize = 0; -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - popsize += popns[i]->stagePop(stage); -} -return popsize; + int popsize = 0; + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + popsize += popns[i]->stagePop(stage); + } + return popsize; } // Open traits file and write header record -bool SubCommunity::outTraitsHeaders(Landscape *pLandscape,Species *pSpecies,int landNr) +bool SubCommunity::outTraitsHeaders(Landscape* pLandscape, Species* pSpecies, int landNr) { -//Population *pPop; -landParams land = pLandscape->getLandParams(); -if (landNr == -999) { // close file - if (outtraits.is_open()) outtraits.close(); - outtraits.clear(); - return true; -} - -string name; -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -simParams sim = paramsSim->getSim(); - -string DirOut = paramsSim->getDir(2); -if (sim.batchMode) { - if (land.patchModel){ - name = DirOut - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) - + "_TraitsXpatch.txt"; + //Population *pPop; + landParams land = pLandscape->getLandParams(); + if (landNr == -999) { // close file + if (outtraits.is_open()) outtraits.close(); + outtraits.clear(); + return true; } - else{ - name = DirOut - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) - + "_TraitsXcell.txt"; - } -} -else { - if (land.patchModel){ - name = DirOut + "Sim" + Int2Str(sim.simulation) + "_TraitsXpatch.txt"; - } - else{ - name = DirOut + "Sim" + Int2Str(sim.simulation) + "_TraitsXcell.txt"; - } -} -outtraits.open(name.c_str()); - -outtraits << "Rep\tYear\tRepSeason"; -if (land.patchModel) outtraits << "\tPatchID"; -else - outtraits << "\tx\ty"; - -if (emig.indVar) { - if (emig.sexDep) { - if (emig.densDep) { - outtraits << "\tF_meanD0\tF_stdD0\tM_meanD0\tM_stdD0"; - outtraits << "\tF_meanAlpha\tF_stdAlpha\tM_meanAlpha\tM_stdAlpha"; - outtraits << "\tF_meanBeta\tF_stdBeta\tM_meanBeta\tM_stdBeta"; + + string name; + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + simParams sim = paramsSim->getSim(); + + string DirOut = paramsSim->getDir(2); + if (sim.batchMode) { + if (land.patchModel) { + name = DirOut + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) + + "_TraitsXpatch.txt"; } else { - outtraits << "\tF_meanEP\tF_stdEP\tM_meanEP\tM_stdEP"; + name = DirOut + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) + + "_TraitsXcell.txt"; } } else { - if (emig.densDep) { - outtraits << "\tmeanD0\tstdD0\tmeanAlpha\tstdAlpha"; - outtraits << "\tmeanBeta\tstdBeta"; + if (land.patchModel) { + name = DirOut + "Sim" + Int2Str(sim.simulation) + "_TraitsXpatch.txt"; } else { - outtraits << "\tmeanEP\tstdEP"; + name = DirOut + "Sim" + Int2Str(sim.simulation) + "_TraitsXcell.txt"; } } -} -if (trfr.indVar) { - if (trfr.moveModel) { - if (trfr.moveType == 1) { - outtraits << "\tmeanDP\tstdDP\tmeanGB\tstdGB"; - outtraits << "\tmeanAlphaDB\tstdAlphaDB\tmeanBetaDB\tstdBetaDB"; + outtraits.open(name.c_str()); + + outtraits << "Rep\tYear\tRepSeason"; + if (land.patchModel) outtraits << "\tPatchID"; + else + outtraits << "\tx\ty"; + + if (emig.indVar) { + if (emig.sexDep) { + if (emig.densDep) { + outtraits << "\tF_meanD0\tF_stdD0\tM_meanD0\tM_stdD0"; + outtraits << "\tF_meanAlpha\tF_stdAlpha\tM_meanAlpha\tM_stdAlpha"; + outtraits << "\tF_meanBeta\tF_stdBeta\tM_meanBeta\tM_stdBeta"; + } + else { + outtraits << "\tF_meanEP\tF_stdEP\tM_meanEP\tM_stdEP"; + } } - if (trfr.moveType == 2) { - outtraits << "\tmeanStepLength\tstdStepLength\tmeanRho\tstdRho"; + else { + if (emig.densDep) { + outtraits << "\tmeanD0\tstdD0\tmeanAlpha\tstdAlpha"; + outtraits << "\tmeanBeta\tstdBeta"; + } + else { + outtraits << "\tmeanEP\tstdEP"; + } } } - else { - if (trfr.sexDep) { - outtraits << "\tF_mean_distI\tF_std_distI\tM_mean_distI\tM_std_distI"; - if (trfr.twinKern) - outtraits << "\tF_mean_distII\tF_std_distII\tM_mean_distII\tM_std_distII" + if (trfr.indVar) { + if (trfr.moveModel) { + if (trfr.moveType == 1) { + outtraits << "\tmeanDP\tstdDP\tmeanGB\tstdGB"; + outtraits << "\tmeanAlphaDB\tstdAlphaDB\tmeanBetaDB\tstdBetaDB"; + } + if (trfr.moveType == 2) { + outtraits << "\tmeanStepLength\tstdStepLength\tmeanRho\tstdRho"; + } + } + else { + if (trfr.sexDep) { + outtraits << "\tF_mean_distI\tF_std_distI\tM_mean_distI\tM_std_distI"; + if (trfr.twinKern) + outtraits << "\tF_mean_distII\tF_std_distII\tM_mean_distII\tM_std_distII" << "\tF_meanPfirstKernel\tF_stdPfirstKernel" << "\tM_meanPfirstKernel\tM_stdPfirstKernel"; + } + else { + outtraits << "\tmean_distI\tstd_distI"; + if (trfr.twinKern) + outtraits << "\tmean_distII\tstd_distII\tmeanPfirstKernel\tstdPfirstKernel"; + } + } + } + if (sett.indVar) { + if (sett.sexDep) { + outtraits << "\tF_meanS0\tF_stdS0\tM_meanS0\tM_stdS0"; + outtraits << "\tF_meanAlphaS\tF_stdAlphaS\tM_meanAlphaS\tM_stdAlphaS"; + outtraits << "\tF_meanBetaS\tF_stdBetaS\tM_meanBetaS\tM_stdBetaS"; } else { - outtraits << "\tmean_distI\tstd_distI"; - if (trfr.twinKern) - outtraits << "\tmean_distII\tstd_distII\tmeanPfirstKernel\tstdPfirstKernel"; + outtraits << "\tmeanS0\tstdS0"; + outtraits << "\tmeanAlphaS\tstdAlphaS"; + outtraits << "\tmeanBetaS\tstdBetaS"; } } -} -if (sett.indVar) { - if (sett.sexDep) { - outtraits << "\tF_meanS0\tF_stdS0\tM_meanS0\tM_stdS0"; - outtraits << "\tF_meanAlphaS\tF_stdAlphaS\tM_meanAlphaS\tM_stdAlphaS"; - outtraits << "\tF_meanBetaS\tF_stdBetaS\tM_meanBetaS\tM_stdBetaS"; - } - else { - outtraits << "\tmeanS0\tstdS0"; - outtraits << "\tmeanAlphaS\tstdAlphaS"; - outtraits << "\tmeanBetaS\tstdBetaS"; - } -} -outtraits << endl; + outtraits << endl; -return outtraits.is_open(); + return outtraits.is_open(); } // Write records to traits file and return aggregated sums traitsums SubCommunity::outTraits(traitCanvas tcanv, - Landscape *pLandscape,int rep,int yr,int gen,bool commlevel) + Landscape* pLandscape, int rep, int yr, int gen, bool commlevel) { -int popsize,ngenes; -landParams land = pLandscape->getLandParams(); -simParams sim = paramsSim->getSim(); -bool writefile = false; -if (sim.outTraitsCells && yr%sim.outIntTraitCell == 0 && !commlevel) - writefile = true; -traitsums ts,poptraits; -for (int i = 0; i < NSEXES; i++) { - ts.ninds[i] = 0; - ts.sumD0[i] = ts.ssqD0[i] = 0.0; - ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; - ts.sumDist1[i] = ts.ssqDist1[i] = 0.0; ts.sumDist2[i] = ts.ssqDist2[i] = 0.0; - ts.sumProp1[i] = ts.ssqProp1[i] = 0.0; - ts.sumDP[i] = ts.ssqDP[i] = 0.0; - ts.sumGB[i] = ts.ssqGB[i] = 0.0; - ts.sumAlphaDB[i] = ts.ssqAlphaDB[i] = 0.0; - ts.sumBetaDB[i] = ts.ssqBetaDB[i] = 0.0; - ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; - ts.sumS0[i] = ts.ssqS0[i] = 0.0; - ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; -} + int popsize, ngenes; + landParams land = pLandscape->getLandParams(); + simParams sim = paramsSim->getSim(); + bool writefile = false; + if (sim.outTraitsCells && yr % sim.outIntTraitCell == 0 && !commlevel) + writefile = true; + traitsums ts, poptraits; + for (int i = 0; i < NSEXES; i++) { + ts.ninds[i] = 0; + ts.sumD0[i] = ts.ssqD0[i] = 0.0; + ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; + ts.sumDist1[i] = ts.ssqDist1[i] = 0.0; ts.sumDist2[i] = ts.ssqDist2[i] = 0.0; + ts.sumProp1[i] = ts.ssqProp1[i] = 0.0; + ts.sumDP[i] = ts.ssqDP[i] = 0.0; + ts.sumGB[i] = ts.ssqGB[i] = 0.0; + ts.sumAlphaDB[i] = ts.ssqAlphaDB[i] = 0.0; + ts.sumBetaDB[i] = ts.ssqBetaDB[i] = 0.0; + ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; + ts.sumS0[i] = ts.ssqS0[i] = 0.0; + ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; + } -// generate output for each population within the sub-community (patch) -// provided that the patch is suitable (i.e. non-zero carrying capacity) -int npops = (int)popns.size(); -Species* pSpecies; -float localK; + // generate output for each population within the sub-community (patch) + // provided that the patch is suitable (i.e. non-zero carrying capacity) + int npops = (int)popns.size(); + Species* pSpecies; + float localK; -for (int i = 0; i < npops; i++) { // all populations - localK = pPatch->getK(); - if (localK > 0.0 && popns[i]->getNInds() > 0) { - pSpecies = popns[i]->getSpecies(); - demogrParams dem = pSpecies->getDemogr(); - emigRules emig = pSpecies->getEmig(); - trfrRules trfr = pSpecies->getTrfr(); - settleType sett = pSpecies->getSettle(); - poptraits = popns[i]->getTraits(pSpecies); - - if (writefile) { - outtraits << rep << "\t" << yr << "\t" << gen; - if (land.patchModel) { - outtraits << "\t" << pPatch->getPatchNum(); - } - else { - locn loc = pPatch->getCellLocn(0); - outtraits << "\t" << loc.x << "\t" << loc.y; - } - } + for (int i = 0; i < npops; i++) { // all populations + localK = pPatch->getK(); + if (localK > 0.0 && popns[i]->getNInds() > 0) { + pSpecies = popns[i]->getSpecies(); + demogrParams dem = pSpecies->getDemogr(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + poptraits = popns[i]->getTraits(pSpecies); - if (emig.indVar) { - if (emig.sexDep) { // must be a sexual species - ngenes = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction - ngenes = 1; + if (writefile) { + outtraits << rep << "\t" << yr << "\t" << gen; + if (land.patchModel) { + outtraits << "\t" << pPatch->getPatchNum(); } - else { // sexual reproduction - ngenes = 1; + else { + locn loc = pPatch->getCellLocn(0); + outtraits << "\t" << loc.x << "\t" << loc.y; } } - double mnD0[2],mnAlpha[2],mnBeta[2],sdD0[2],sdAlpha[2],sdBeta[2]; - for (int g = 0; g < ngenes; g++) { - mnD0[g] = mnAlpha[g] = mnBeta[g] = sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - if (ngenes == 2) popsize = poptraits.ninds[g]; - else popsize = poptraits.ninds[0] + poptraits.ninds[1]; - if (popsize > 0) { - mnD0[g] = poptraits.sumD0[g] / (double)popsize; - mnAlpha[g] = poptraits.sumAlpha[g] / (double)popsize; - mnBeta[g] = poptraits.sumBeta[g] / (double)popsize; - if (popsize > 1) { - sdD0[g] = poptraits.ssqD0[g]/(double)popsize - mnD0[g]*mnD0[g]; - if (sdD0[g] > 0.0) sdD0[g] = sqrt(sdD0[g]); else sdD0[g] = 0.0; - sdAlpha[g] = poptraits.ssqAlpha[g]/(double)popsize - mnAlpha[g]*mnAlpha[g]; - if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; - sdBeta[g] = poptraits.ssqBeta[g]/(double)popsize - mnBeta[g]*mnBeta[g]; - if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + + if (emig.indVar) { + if (emig.sexDep) { // must be a sexual species + ngenes = 2; + } + else { + if (dem.repType == 0) { // asexual reproduction + ngenes = 1; } - else { - sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + else { // sexual reproduction + ngenes = 1; } } - } - if (writefile) { - if (emig.sexDep) { - outtraits << "\t" << mnD0[0] << "\t" << sdD0[0]; - outtraits << "\t" << mnD0[1] << "\t" << sdD0[1]; - if (emig.densDep) { - outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outtraits << "\t" << mnAlpha[1] << "\t" << sdAlpha[1]; - outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; - outtraits << "\t" << mnBeta[1] << "\t" << sdBeta[1]; + double mnD0[2], mnAlpha[2], mnBeta[2], sdD0[2], sdAlpha[2], sdBeta[2]; + for (int g = 0; g < ngenes; g++) { + mnD0[g] = mnAlpha[g] = mnBeta[g] = sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + // individuals may have been counted by sex if there was + // sex dependency in another dispersal phase + if (ngenes == 2) popsize = poptraits.ninds[g]; + else popsize = poptraits.ninds[0] + poptraits.ninds[1]; + if (popsize > 0) { + mnD0[g] = poptraits.sumD0[g] / (double)popsize; + mnAlpha[g] = poptraits.sumAlpha[g] / (double)popsize; + mnBeta[g] = poptraits.sumBeta[g] / (double)popsize; + if (popsize > 1) { + sdD0[g] = poptraits.ssqD0[g] / (double)popsize - mnD0[g] * mnD0[g]; + if (sdD0[g] > 0.0) sdD0[g] = sqrt(sdD0[g]); else sdD0[g] = 0.0; + sdAlpha[g] = poptraits.ssqAlpha[g] / (double)popsize - mnAlpha[g] * mnAlpha[g]; + if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; + sdBeta[g] = poptraits.ssqBeta[g] / (double)popsize - mnBeta[g] * mnBeta[g]; + if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + } + else { + sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + } } } - else { // sex-independent - outtraits << "\t" << mnD0[0] << "\t" << sdD0[0]; - if (emig.densDep) { - outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + if (writefile) { + if (emig.sexDep) { + outtraits << "\t" << mnD0[0] << "\t" << sdD0[0]; + outtraits << "\t" << mnD0[1] << "\t" << sdD0[1]; + if (emig.densDep) { + outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; + outtraits << "\t" << mnAlpha[1] << "\t" << sdAlpha[1]; + outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + outtraits << "\t" << mnBeta[1] << "\t" << sdBeta[1]; + } + } + else { // sex-independent + outtraits << "\t" << mnD0[0] << "\t" << sdD0[0]; + if (emig.densDep) { + outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; + outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + } } } } - } - if (trfr.indVar) { - if (trfr.moveModel) { - // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ngenes = 1; - } - else { - if (trfr.sexDep) { // must be a sexual species - ngenes = 2; - } - else { + if (trfr.indVar) { + if (trfr.moveModel) { + // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT ngenes = 1; } - } - double mnDist1[2], mnDist2[2], mnProp1[2], mnStepL[2], mnRho[2]; - double sdDist1[2],sdDist2[2],sdProp1[2],sdStepL[2],sdRho[2]; - double mnDP[2], mnGB[2], mnAlphaDB[2], mnBetaDB[2]; - double sdDP[2],sdGB[2],sdAlphaDB[2],sdBetaDB[2]; - for (int g = 0; g < ngenes; g++) { - mnDist1[g] = mnDist2[g] = mnProp1[g] = mnStepL[g] = mnRho[g] = 0.0; - sdDist1[g] = sdDist2[g] = sdProp1[g] = sdStepL[g] = sdRho[g] = 0.0; - mnDP[g] = mnGB[g] = mnAlphaDB[g] = mnBetaDB[g] = 0.0; - sdDP[g] = sdGB[g] = sdAlphaDB[g] = sdBetaDB[g] = 0.0; - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - if (ngenes == 2) popsize = poptraits.ninds[g]; - else popsize = poptraits.ninds[0] + poptraits.ninds[1]; - if (popsize > 0) { - mnDist1[g] = poptraits.sumDist1[g] / (double)popsize; - mnDist2[g] = poptraits.sumDist2[g] / (double)popsize; - mnProp1[g] = poptraits.sumProp1[g] / (double)popsize; - mnStepL[g] = poptraits.sumStepL[g] / (double)popsize; - mnRho[g] = poptraits.sumRho[g] / (double)popsize; - mnDP[g] = poptraits.sumDP[g] / (double)popsize; - mnGB[g] = poptraits.sumGB[g] / (double)popsize; - mnAlphaDB[g] = poptraits.sumAlphaDB[g] / (double)popsize; - mnBetaDB[g] = poptraits.sumBetaDB[g] / (double)popsize; - if (popsize > 1) { - sdDist1[g] = poptraits.ssqDist1[g]/(double)popsize - mnDist1[g]*mnDist1[g]; - if (sdDist1[g] > 0.0) sdDist1[g] = sqrt(sdDist1[g]); else sdDist1[g] = 0.0; - sdDist2[g] = poptraits.ssqDist2[g]/(double)popsize - mnDist2[g]*mnDist2[g]; - if (sdDist2[g] > 0.0) sdDist2[g] = sqrt(sdDist2[g]); else sdDist2[g] = 0.0; - sdProp1[g] = poptraits.ssqProp1[g]/(double)popsize - mnProp1[g]*mnProp1[g]; - if (sdProp1[g] > 0.0) sdProp1[g] = sqrt(sdProp1[g]); else sdProp1[g] = 0.0; - sdStepL[g] = poptraits.ssqStepL[g]/(double)popsize - mnStepL[g]*mnStepL[g]; - if (sdStepL[g] > 0.0) sdStepL[g] = sqrt(sdStepL[g]); else sdStepL[g] = 0.0; - sdRho[g] = poptraits.ssqRho[g]/(double)popsize - mnRho[g]*mnRho[g]; - if (sdRho[g] > 0.0) sdRho[g] = sqrt(sdRho[g]); else sdRho[g] = 0.0; - sdDP[g] = poptraits.ssqDP[g]/(double)popsize - mnDP[g]*mnDP[g]; - if (sdDP[g] > 0.0) sdDP[g] = sqrt(sdDP[g]); else sdDP[g] = 0.0; - sdGB[g] = poptraits.ssqGB[g]/(double)popsize - mnGB[g]*mnGB[g]; - if (sdGB[g] > 0.0) sdGB[g] = sqrt(sdGB[g]); else sdGB[g] = 0.0; - sdAlphaDB[g] = poptraits.ssqAlphaDB[g]/(double)popsize - mnAlphaDB[g]*mnAlphaDB[g]; - if (sdAlphaDB[g] > 0.0) sdAlphaDB[g] = sqrt(sdAlphaDB[g]); else sdAlphaDB[g] = 0.0; - sdBetaDB[g] = poptraits.ssqBetaDB[g]/(double)popsize - mnBetaDB[g]*mnBetaDB[g]; - if (sdBetaDB[g] > 0.0) sdBetaDB[g] = sqrt(sdBetaDB[g]); else sdBetaDB[g] = 0.0; + else { + if (trfr.sexDep) { // must be a sexual species + ngenes = 2; } - } - } - if (writefile) { - if (trfr.moveModel) { - if (trfr.moveType == 1) { - outtraits << "\t" << mnDP[0] << "\t" << sdDP[0]; - outtraits << "\t" << mnGB[0] << "\t" << sdGB[0]; - outtraits << "\t" << mnAlphaDB[0] << "\t" << sdAlphaDB[0]; - outtraits << "\t" << mnBetaDB[0] << "\t" << sdBetaDB[0]; + else { + ngenes = 1; } - if (trfr.moveType == 2) { - outtraits << "\t" << mnStepL[0] << "\t" << sdStepL[0]; - outtraits << "\t" << mnRho[0] << "\t" << sdRho[0]; + } + double mnDist1[2], mnDist2[2], mnProp1[2], mnStepL[2], mnRho[2]; + double sdDist1[2], sdDist2[2], sdProp1[2], sdStepL[2], sdRho[2]; + double mnDP[2], mnGB[2], mnAlphaDB[2], mnBetaDB[2]; + double sdDP[2], sdGB[2], sdAlphaDB[2], sdBetaDB[2]; + for (int g = 0; g < ngenes; g++) { + mnDist1[g] = mnDist2[g] = mnProp1[g] = mnStepL[g] = mnRho[g] = 0.0; + sdDist1[g] = sdDist2[g] = sdProp1[g] = sdStepL[g] = sdRho[g] = 0.0; + mnDP[g] = mnGB[g] = mnAlphaDB[g] = mnBetaDB[g] = 0.0; + sdDP[g] = sdGB[g] = sdAlphaDB[g] = sdBetaDB[g] = 0.0; + // individuals may have been counted by sex if there was + // sex dependency in another dispersal phase + if (ngenes == 2) popsize = poptraits.ninds[g]; + else popsize = poptraits.ninds[0] + poptraits.ninds[1]; + if (popsize > 0) { + mnDist1[g] = poptraits.sumDist1[g] / (double)popsize; + mnDist2[g] = poptraits.sumDist2[g] / (double)popsize; + mnProp1[g] = poptraits.sumProp1[g] / (double)popsize; + mnStepL[g] = poptraits.sumStepL[g] / (double)popsize; + mnRho[g] = poptraits.sumRho[g] / (double)popsize; + mnDP[g] = poptraits.sumDP[g] / (double)popsize; + mnGB[g] = poptraits.sumGB[g] / (double)popsize; + mnAlphaDB[g] = poptraits.sumAlphaDB[g] / (double)popsize; + mnBetaDB[g] = poptraits.sumBetaDB[g] / (double)popsize; + if (popsize > 1) { + sdDist1[g] = poptraits.ssqDist1[g] / (double)popsize - mnDist1[g] * mnDist1[g]; + if (sdDist1[g] > 0.0) sdDist1[g] = sqrt(sdDist1[g]); else sdDist1[g] = 0.0; + sdDist2[g] = poptraits.ssqDist2[g] / (double)popsize - mnDist2[g] * mnDist2[g]; + if (sdDist2[g] > 0.0) sdDist2[g] = sqrt(sdDist2[g]); else sdDist2[g] = 0.0; + sdProp1[g] = poptraits.ssqProp1[g] / (double)popsize - mnProp1[g] * mnProp1[g]; + if (sdProp1[g] > 0.0) sdProp1[g] = sqrt(sdProp1[g]); else sdProp1[g] = 0.0; + sdStepL[g] = poptraits.ssqStepL[g] / (double)popsize - mnStepL[g] * mnStepL[g]; + if (sdStepL[g] > 0.0) sdStepL[g] = sqrt(sdStepL[g]); else sdStepL[g] = 0.0; + sdRho[g] = poptraits.ssqRho[g] / (double)popsize - mnRho[g] * mnRho[g]; + if (sdRho[g] > 0.0) sdRho[g] = sqrt(sdRho[g]); else sdRho[g] = 0.0; + sdDP[g] = poptraits.ssqDP[g] / (double)popsize - mnDP[g] * mnDP[g]; + if (sdDP[g] > 0.0) sdDP[g] = sqrt(sdDP[g]); else sdDP[g] = 0.0; + sdGB[g] = poptraits.ssqGB[g] / (double)popsize - mnGB[g] * mnGB[g]; + if (sdGB[g] > 0.0) sdGB[g] = sqrt(sdGB[g]); else sdGB[g] = 0.0; + sdAlphaDB[g] = poptraits.ssqAlphaDB[g] / (double)popsize - mnAlphaDB[g] * mnAlphaDB[g]; + if (sdAlphaDB[g] > 0.0) sdAlphaDB[g] = sqrt(sdAlphaDB[g]); else sdAlphaDB[g] = 0.0; + sdBetaDB[g] = poptraits.ssqBetaDB[g] / (double)popsize - mnBetaDB[g] * mnBetaDB[g]; + if (sdBetaDB[g] > 0.0) sdBetaDB[g] = sqrt(sdBetaDB[g]); else sdBetaDB[g] = 0.0; + } } } - else { - if (trfr.sexDep) { - outtraits << "\t" << mnDist1[0] << "\t" << sdDist1[0]; - outtraits << "\t" << mnDist1[1] << "\t" << sdDist1[1]; - if (trfr.twinKern) - { - outtraits << "\t" << mnDist2[0] << "\t" << sdDist2[0]; - outtraits << "\t" << mnDist2[1] << "\t" << sdDist2[1]; - outtraits << "\t" << mnProp1[0] << "\t" << sdProp1[0]; - outtraits << "\t" << mnProp1[1] << "\t" << sdProp1[1]; + if (writefile) { + if (trfr.moveModel) { + if (trfr.moveType == 1) { + outtraits << "\t" << mnDP[0] << "\t" << sdDP[0]; + outtraits << "\t" << mnGB[0] << "\t" << sdGB[0]; + outtraits << "\t" << mnAlphaDB[0] << "\t" << sdAlphaDB[0]; + outtraits << "\t" << mnBetaDB[0] << "\t" << sdBetaDB[0]; + } + if (trfr.moveType == 2) { + outtraits << "\t" << mnStepL[0] << "\t" << sdStepL[0]; + outtraits << "\t" << mnRho[0] << "\t" << sdRho[0]; } } - else { // sex-independent - outtraits << "\t" << mnDist1[0] << "\t" << sdDist1[0]; - if (trfr.twinKern) - { - outtraits << "\t" << mnDist2[0] << "\t" << sdDist2[0]; - outtraits << "\t" << mnProp1[0] << "\t" << sdProp1[0]; + else { + if (trfr.sexDep) { + outtraits << "\t" << mnDist1[0] << "\t" << sdDist1[0]; + outtraits << "\t" << mnDist1[1] << "\t" << sdDist1[1]; + if (trfr.twinKern) + { + outtraits << "\t" << mnDist2[0] << "\t" << sdDist2[0]; + outtraits << "\t" << mnDist2[1] << "\t" << sdDist2[1]; + outtraits << "\t" << mnProp1[0] << "\t" << sdProp1[0]; + outtraits << "\t" << mnProp1[1] << "\t" << sdProp1[1]; + } + } + else { // sex-independent + outtraits << "\t" << mnDist1[0] << "\t" << sdDist1[0]; + if (trfr.twinKern) + { + outtraits << "\t" << mnDist2[0] << "\t" << sdDist2[0]; + outtraits << "\t" << mnProp1[0] << "\t" << sdProp1[0]; + } } } } } - } - if (sett.indVar) { - if (sett.sexDep) { // must be a sexual species - ngenes = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction - ngenes = 1; - } - else { // sexual reproduction - ngenes = 1; + if (sett.indVar) { + if (sett.sexDep) { // must be a sexual species + ngenes = 2; } - } - // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT -// ngenes = 1; - double mnS0[2],mnAlpha[2],mnBeta[2],sdS0[2],sdAlpha[2],sdBeta[2]; - for (int g = 0; g < ngenes; g++) { - mnS0[g] = mnAlpha[g] = mnBeta[g] = sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - if (ngenes == 2) popsize = poptraits.ninds[g]; - else popsize = poptraits.ninds[0] + poptraits.ninds[1]; - if (popsize > 0) { - mnS0[g] = poptraits.sumS0[g] / (double)popsize; - mnAlpha[g] = poptraits.sumAlphaS[g] / (double)popsize; - mnBeta[g] = poptraits.sumBetaS[g] / (double)popsize; - if (popsize > 1) { - sdS0[g] = poptraits.ssqS0[g]/(double)popsize - mnS0[g]*mnS0[g]; - if (sdS0[g] > 0.0) sdS0[g] = sqrt(sdS0[g]); else sdS0[g] = 0.0; - sdAlpha[g] = poptraits.ssqAlphaS[g]/(double)popsize - mnAlpha[g]*mnAlpha[g]; - if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; - sdBeta[g] = poptraits.ssqBetaS[g]/(double)popsize - mnBeta[g]*mnBeta[g]; - if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + else { + if (dem.repType == 0) { // asexual reproduction + ngenes = 1; } - else { - sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + else { // sexual reproduction + ngenes = 1; } } - } - if (writefile) { - if (sett.sexDep) { - outtraits << "\t" << mnS0[0] << "\t" << sdS0[0]; - outtraits << "\t" << mnS0[1] << "\t" << sdS0[1]; - outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outtraits << "\t" << mnAlpha[1] << "\t" << sdAlpha[1]; - outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; - outtraits << "\t" << mnBeta[1] << "\t" << sdBeta[1]; + // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT + // ngenes = 1; + double mnS0[2], mnAlpha[2], mnBeta[2], sdS0[2], sdAlpha[2], sdBeta[2]; + for (int g = 0; g < ngenes; g++) { + mnS0[g] = mnAlpha[g] = mnBeta[g] = sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + // individuals may have been counted by sex if there was + // sex dependency in another dispersal phase + if (ngenes == 2) popsize = poptraits.ninds[g]; + else popsize = poptraits.ninds[0] + poptraits.ninds[1]; + if (popsize > 0) { + mnS0[g] = poptraits.sumS0[g] / (double)popsize; + mnAlpha[g] = poptraits.sumAlphaS[g] / (double)popsize; + mnBeta[g] = poptraits.sumBetaS[g] / (double)popsize; + if (popsize > 1) { + sdS0[g] = poptraits.ssqS0[g] / (double)popsize - mnS0[g] * mnS0[g]; + if (sdS0[g] > 0.0) sdS0[g] = sqrt(sdS0[g]); else sdS0[g] = 0.0; + sdAlpha[g] = poptraits.ssqAlphaS[g] / (double)popsize - mnAlpha[g] * mnAlpha[g]; + if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; + sdBeta[g] = poptraits.ssqBetaS[g] / (double)popsize - mnBeta[g] * mnBeta[g]; + if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + } + else { + sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + } + } } - else { // sex-independent - outtraits << "\t" << mnS0[0] << "\t" << sdS0[0]; - outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + if (writefile) { + if (sett.sexDep) { + outtraits << "\t" << mnS0[0] << "\t" << sdS0[0]; + outtraits << "\t" << mnS0[1] << "\t" << sdS0[1]; + outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; + outtraits << "\t" << mnAlpha[1] << "\t" << sdAlpha[1]; + outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + outtraits << "\t" << mnBeta[1] << "\t" << sdBeta[1]; + } + else { // sex-independent + outtraits << "\t" << mnS0[0] << "\t" << sdS0[0]; + outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; + outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + } } } - } - if (writefile) outtraits << endl; - - for (int s = 0; s < NSEXES; s++) { - ts.ninds[s] += poptraits.ninds[s]; - ts.sumD0[s] += poptraits.sumD0[s]; ts.ssqD0[s] += poptraits.ssqD0[s]; - ts.sumAlpha[s] += poptraits.sumAlpha[s]; ts.ssqAlpha[s] += poptraits.ssqAlpha[s]; - ts.sumBeta[s] += poptraits.sumBeta[s]; ts.ssqBeta[s] += poptraits.ssqBeta[s]; - ts.sumDist1[s] += poptraits.sumDist1[s]; ts.ssqDist1[s] += poptraits.ssqDist1[s]; - ts.sumDist2[s] += poptraits.sumDist2[s]; ts.ssqDist2[s] += poptraits.ssqDist2[s]; - ts.sumProp1[s] += poptraits.sumProp1[s]; ts.ssqProp1[s] += poptraits.ssqProp1[s]; - ts.sumDP[s] += poptraits.sumDP[s]; ts.ssqDP[s] += poptraits.ssqDP[s]; - ts.sumGB[s] += poptraits.sumGB[s]; ts.ssqGB[s] += poptraits.ssqGB[s]; - ts.sumAlphaDB[s] += poptraits.sumAlphaDB[s]; ts.ssqAlphaDB[s] += poptraits.ssqAlphaDB[s]; - ts.sumBetaDB[s] += poptraits.sumBetaDB[s]; ts.ssqBetaDB[s] += poptraits.ssqBetaDB[s]; - ts.sumStepL[s] += poptraits.sumStepL[s]; ts.ssqStepL[s] += poptraits.ssqStepL[s]; - ts.sumRho[s] += poptraits.sumRho[s]; ts.ssqRho[s] += poptraits.ssqRho[s]; - ts.sumS0[s] += poptraits.sumS0[s]; ts.ssqS0[s] += poptraits.ssqS0[s]; - ts.sumAlphaS[s] += poptraits.sumAlphaS[s]; ts.ssqAlphaS[s] += poptraits.ssqAlphaS[s]; - ts.sumBetaS[s] += poptraits.sumBetaS[s]; ts.ssqBetaS[s] += poptraits.ssqBetaS[s]; + if (writefile) outtraits << endl; + + for (int s = 0; s < NSEXES; s++) { + ts.ninds[s] += poptraits.ninds[s]; + ts.sumD0[s] += poptraits.sumD0[s]; ts.ssqD0[s] += poptraits.ssqD0[s]; + ts.sumAlpha[s] += poptraits.sumAlpha[s]; ts.ssqAlpha[s] += poptraits.ssqAlpha[s]; + ts.sumBeta[s] += poptraits.sumBeta[s]; ts.ssqBeta[s] += poptraits.ssqBeta[s]; + ts.sumDist1[s] += poptraits.sumDist1[s]; ts.ssqDist1[s] += poptraits.ssqDist1[s]; + ts.sumDist2[s] += poptraits.sumDist2[s]; ts.ssqDist2[s] += poptraits.ssqDist2[s]; + ts.sumProp1[s] += poptraits.sumProp1[s]; ts.ssqProp1[s] += poptraits.ssqProp1[s]; + ts.sumDP[s] += poptraits.sumDP[s]; ts.ssqDP[s] += poptraits.ssqDP[s]; + ts.sumGB[s] += poptraits.sumGB[s]; ts.ssqGB[s] += poptraits.ssqGB[s]; + ts.sumAlphaDB[s] += poptraits.sumAlphaDB[s]; ts.ssqAlphaDB[s] += poptraits.ssqAlphaDB[s]; + ts.sumBetaDB[s] += poptraits.sumBetaDB[s]; ts.ssqBetaDB[s] += poptraits.ssqBetaDB[s]; + ts.sumStepL[s] += poptraits.sumStepL[s]; ts.ssqStepL[s] += poptraits.ssqStepL[s]; + ts.sumRho[s] += poptraits.sumRho[s]; ts.ssqRho[s] += poptraits.ssqRho[s]; + ts.sumS0[s] += poptraits.sumS0[s]; ts.ssqS0[s] += poptraits.ssqS0[s]; + ts.sumAlphaS[s] += poptraits.sumAlphaS[s]; ts.ssqAlphaS[s] += poptraits.ssqAlphaS[s]; + ts.sumBetaS[s] += poptraits.sumBetaS[s]; ts.ssqBetaS[s] += poptraits.ssqBetaS[s]; #if RSDEBUG -//DEBUGLOG << "SubCommunity::outTraits(): i=" << i << " popns[i]=" << popns[i] -// << " s=" << s -//// << " poptraits.sumRho[s]= " << poptraits.sumRho[s] -//// << " ts.sumRho[s]= " << ts.sumRho[s] -// << " poptraits.sumDP[s]= " << poptraits.sumDP[s] << " poptraits.ssqDP[s]= " << poptraits.ssqDP[s] -// << " ts.sumDP[s]= " << ts.sumDP[s] << " ts.ssqDP[s]= " << ts.ssqDP[s] -// << " poptraits.sumGB[s]= " << poptraits.sumGB[s] << " poptraits.ssqGB[s]= " << poptraits.ssqGB[s] -// << " ts.sumGB[s]= " << ts.sumGB[s] << " ts.ssqGB[s]= " << ts.ssqGB[s] -// << endl; + //DEBUGLOG << "SubCommunity::outTraits(): i=" << i << " popns[i]=" << popns[i] + // << " s=" << s + //// << " poptraits.sumRho[s]= " << poptraits.sumRho[s] + //// << " ts.sumRho[s]= " << ts.sumRho[s] + // << " poptraits.sumDP[s]= " << poptraits.sumDP[s] << " poptraits.ssqDP[s]= " << poptraits.ssqDP[s] + // << " ts.sumDP[s]= " << ts.sumDP[s] << " ts.ssqDP[s]= " << ts.ssqDP[s] + // << " poptraits.sumGB[s]= " << poptraits.sumGB[s] << " poptraits.ssqGB[s]= " << poptraits.ssqGB[s] + // << " ts.sumGB[s]= " << ts.sumGB[s] << " ts.ssqGB[s]= " << ts.ssqGB[s] + // << endl; #endif + } } } -} -return ts; + return ts; } //--------------------------------------------------------------------------- diff --git a/SubCommunity.h b/SubCommunity.h index 3f1266f..e818284 100644 --- a/SubCommunity.h +++ b/SubCommunity.h @@ -1,47 +1,47 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ -RangeShifter v2.0 SubCommunity -Implements the SubCommunity class + /*------------------------------------------------------------------------------ -There is ONE instance of a SubCommunity for each Patch in the Landscape -(including the matrix). The SubCommunity holds a number of Populations, one for -each Species represented in the simulation. -CURRENTLY the number of Populations withn a SubCommunity is LIMITED TO ONE. + RangeShifter v2.0 SubCommunity -For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. -and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. -Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 + Implements the SubCommunity class -Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + There is ONE instance of a SubCommunity for each Patch in the Landscape + (including the matrix). The SubCommunity holds a number of Populations, one for + each Species represented in the simulation. + CURRENTLY the number of Populations withn a SubCommunity is LIMITED TO ONE. -Last updated: 26 October 2021 by Steve Palmer + For full details of RangeShifter, please see: + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. + and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial + eco-evolutionary dynamics and species’ responses to environmental changes. + Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 -------------------------------------------------------------------------------*/ + Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + + Last updated: 26 October 2021 by Steve Palmer + + ------------------------------------------------------------------------------*/ #ifndef SubCommunityH #define SubCommunityH @@ -65,13 +65,13 @@ using namespace std; //--------------------------------------------------------------------------- struct traitCanvas { // canvases for drawing variable traits - int *pcanvas[NTRAITS]; // dummy variables for batch version + int* pcanvas[NTRAITS]; // dummy variables for batch version }; class SubCommunity { public: - SubCommunity(Patch*,int); + SubCommunity(Patch*, int); ~SubCommunity(void); intptr getNum(void); Patch* getPatch(void); @@ -80,8 +80,8 @@ class SubCommunity { // functions to manage populations occurring in the SubCommunity popStats getPopStats(void); void setInitial(bool); - void initialise(Landscape*,Species*); - void initialInd(Landscape*,Species*,Patch*,Cell*,int); + void initialise(Landscape*, Species*); + void initialInd(Landscape*, Species*, Patch*, Cell*, int); Population* newPopn( // Create a new population, and return its address Landscape*, // pointer to Landscape Species*, // pointer to Species @@ -106,7 +106,7 @@ class SubCommunity { void initiateDispersal( SubCommunity* // pointer to matrix SubCommunity ); -// Add an individual into the local population of its species in the patch + // Add an individual into the local population of its species in the patch void recruit( Individual*, // pointer to Individual Species* // pointer to Species @@ -131,16 +131,16 @@ class SubCommunity { ); void survival( short, // part: 0 = determine survival & development, - // 1 = apply survival changes to the population + // 1 = apply survival changes to the population short, // option0: 0 = stage 0 (juveniles) only ) - // 1 = all stages ) used by part 0 only - // 2 = stage 1 and above (all non-juvs) ) + // 1 = all stages ) used by part 0 only + // 2 = stage 1 and above (all non-juvs) ) short // option1: 0 - development only (when survival is annual) // 1 - development and survival ); void ageIncrement(void); // Find the population of a given species in a given patch - Population* findPop(Species*,Patch*); + Population* findPop(Species*, Patch*); void createOccupancy( int // no. of rows = (no. of years / interval) + 1 ); @@ -186,7 +186,7 @@ class SubCommunity { ); traitsums outTraits( // Write records to traits file and return aggregated sums traitCanvas, // pointers to canvases for drawing variable traits - // in the batch version, these are replaced by integers set to zero + // in the batch version, these are replaced by integers set to zero Landscape*, // pointer to Landscape int, // replicate int, // year @@ -199,18 +199,18 @@ class SubCommunity { private: intptr subCommNum; // SubCommunity number - // 0 is reserved for the SubCommunity in the inter-patch matrix + // 0 is reserved for the SubCommunity in the inter-patch matrix // intptr *occupancy; // pointer to occupancy array - Patch *pPatch; - int *occupancy; // pointer to occupancy array + Patch* pPatch; + int* occupancy; // pointer to occupancy array std::vector popns; bool initial; // WILL NEED TO BE CHANGED FOR MULTIPLE SPECIES ... }; -extern paramGrad *paramsGrad; -extern paramStoch *paramsStoch; -extern paramInit *paramsInit; +extern paramGrad* paramsGrad; +extern paramStoch* paramsStoch; +extern paramInit* paramsInit; //--------------------------------------------------------------------------- #endif From 1207241d8fa6dd721238a4ce5109bdfee5acfc43 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 15 Jan 2024 17:52:11 +0000 Subject: [PATCH 010/332] resolution should never be 0 --- Landscape.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index 970f2ba..2380243 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -40,7 +40,7 @@ ofstream outMovePaths; InitDist::InitDist(Species* pSp) { pSpecies = pSp; - resol = 0; + resol = 1; maxX = 0; maxY = 0; minEast = 0.0; @@ -250,7 +250,7 @@ if (!dfile.eof()) EOFerrorR(distfile); Landscape::Landscape(void) { patchModel = false; spDist = false; generated = false; fractal = false; continuous = false; dynamic = false; habIndexed = false; - resol = spResol = landNum = 0; + resol = spResol = 1; landNum = 0; rasterType = 0; nHab = nHabMax = 0; dimX = dimY = 100; @@ -336,7 +336,9 @@ void Landscape::resetLand(void) { void Landscape::setLandParams(landParams ppp, bool batchMode) { - generated = ppp.generated; patchModel = ppp.patchModel; spDist = ppp.spDist; + generated = ppp.generated; + patchModel = ppp.patchModel; + spDist = ppp.spDist; dynamic = ppp.dynamic; landNum = ppp.landNum; if (ppp.resol > 0) resol = ppp.resol; From f05cb181f6856254877ec7cb9daf27347026fe48 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 15 Jan 2024 17:52:52 +0000 Subject: [PATCH 011/332] unit tests for basic moveKernel, should have committed more often --- Individual.cpp | 132 ++++++++++++++++++++++++++++++++++++------------- Main.cpp | 9 ++++ 2 files changed, 106 insertions(+), 35 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 2b0108c..2efbcf0 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -866,7 +866,6 @@ void Individual::moveto(Cell* newCell) { // Returns 1 if still dispersing (including having found a potential patch), otherwise 0 int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, const bool absorbing) { - intptr patch; int patchNum = 0; int newX = 0, newY = 0; @@ -975,6 +974,7 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, const bool if (loopsteps < 1000) { if (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY) { // beyond absorbing boundary + // this cannot be reached if not absorbing? pCell = 0; patch = 0; patchNum = -1; @@ -1007,7 +1007,7 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, const bool if (loopsteps < 1000) { if (pCell == 0) { // beyond absorbing boundary or in no-data cell - // this should never be true?? + // only if absorbing=true and out of bounddaries pCurrCell = 0; status = 6; dispersing = 0; @@ -1020,6 +1020,7 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, const bool status = 2; // record as potential settler } else { + // unsuitable patch dispersing = 0; // can wait in matrix if population is stage structured ... if (pSpecies->stageStructured()) { @@ -1030,8 +1031,7 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, const bool else // ... it is not status = 6; // dies (unless there is a suitable neighbouring cell) } - else - status = 6; // dies (unless there is a suitable neighbouring cell) + else status = 6; // dies (unless there is a suitable neighbouring cell) } } } @@ -1846,60 +1846,122 @@ void testIndividual() { // depending on the stage // depending on the trait inheritance - // Disperses // Emigrates // Transfers - // Kernel transfer + // Kernel-based transfer { // Simple cell-based landscape layout - // oo - // oo landParams ls_params; - ls_params.dimX = ls_params.dimY = 2; - vector cells{ new Cell(0, 0, 0, 0), new Cell(1, 1, 0, 0) }; - // Set up species for habitat codes + ls_params.dimX = ls_params.dimY = 5; + ls_params.minX = ls_params.minY = 0; + ls_params.maxX = ls_params.maxY = ls_params.dimX - 1; + ls_params.resol = 1; + + // Two suitable cells in opposite corners + Cell* init_cell = new Cell(0, 0, 0, 0); + Cell* final_cell = new Cell(ls_params.dimX - 1, ls_params.dimY - 1, 0, 0); + // Set up species Species sp; + // Habitat codes sp.createHabK(1); sp.setHabK(0, 100.0); // one habitat with K = 100 + // Demography + demogrParams d; + d.stageStruct = false; + sp.setDemogr(d); + // Transfer rules + trfrRules trfr; + trfr.indVar = trfr.sexDep = trfr.stgDep = false; + trfr.twinKern = trfr.distMort = false; + sp.setTrfr(trfr); + sp.setFullKernel(false); + // Transfer traits + trfrKernTraits kern; + kern.meanDist1 = static_cast(ls_params.dimX); // can reach destination cell reasonably often + sp.setKernTraits(0, 0, kern, ls_params.resol); + // Transfer mortality params + trfrMortParams mort; + mort.fixedMort = 0.0; + sp.setMortParams(mort); + // Settlement + settleRules sett; + sett.wait = false; + sp.setSettRules(0, 0, sett); // Landscape ls = createLandscapeFromCells(cells, ls_params, sp); Landscape ls; ls.setLandParams(ls_params, true); // Add cells ls.setCellArray(); - for (auto c : cells) { - ls.addCellToLand(c); - } + ls.addCellToLand(init_cell); + ls.addCellToLand(final_cell); ls.allocatePatches(&sp); + ls.updateCarryingCapacity(&sp, 0, 0); - Patch* p = (Patch*)cells[0]->getPatch(); - Individual ind(cells[0], p, 1, 0, 0, 0.0, false, 0); - Cell* init_cell = ind.getCurrCell(); + Patch* init_patch = (Patch*)init_cell->getPatch(); - // ind.status - // land.resol - // species.trfrKernTraits.meanDist1 - // species.useFullKernel + // Create and set up individual + Individual starting_ind(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + + // Set aside original individual and test on a copy + Individual ind = starting_ind; // pathData *path; ? - // land.minX etc. dimX dimY - // patch.localK - // bool species.stageStruct - // species trfrMortParams m; m.fixedMort = fixedMort; m.mortAlpha = mortAlpha; m.mortBeta = mortBeta; - int isDispersing = ind.moveKernel(&ls, &sp, false); - // After movement, individual should be... - // in a different cell + // After moving, individual should be in the only available cell Cell* curr_cell = ind.getCurrCell(); - // not in a no-data cell - assert(curr_cell != 0); assert(curr_cell != init_cell); - // (non-absorbing) still within landscape boundaries - - - - // Arrival cell + assert(curr_cell == final_cell); + assert(ind.getStatus() == 2); // potential settler + + // If no cell within reasonable dispersal reach, individual does not move and dies + kern.meanDist1 = 1.0; + sp.setKernTraits(0, 0, kern, ls_params.resol); + ind = starting_ind; // reset individual + isDispersing = ind.moveKernel(&ls, &sp, false); + curr_cell = ind.getCurrCell(); + assert(ind.getStatus() == 6); // RIP in peace + assert(curr_cell == init_cell); + + /* Boundaries: dispersal distance overshoots + Only adjacent cells are available + ----- + -ooo- + -oio- + -ooo- + ----- + */ + ls.setCellArray(); // reset cells + vector cells; + // Set central cell and all adjacent + for (int x = ls_params.minX + 1; x < ls_params.maxX; ++x) { + for (int y = ls_params.minY + 1; y < ls_params.maxY; ++y) { + cells.push_back(new Cell(x, y, 0, 0)); + } + } + for (auto c : cells) ls.addCellToLand(c); + ls.allocatePatches(&sp); + ls.updateCarryingCapacity(&sp, 0, 0); + init_cell = cells[4]; // that is, the center + init_patch = (Patch*)init_cell->getPatch(); + + kern.meanDist1 = 5; // overshoots *most* of the time... + sp.setKernTraits(0, 0, kern, ls_params.resol); + ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual + + // Non-absorbing boundaries + isDispersing = ind.moveKernel(&ls, &sp, false); + curr_cell = ind.getCurrCell(); + assert(curr_cell != init_cell); // ...should be able to move eventually + assert(ind.getStatus() == 2); + + // Absorbing boundaries + ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual + isDispersing = ind.moveKernel(&ls, &sp, true); + curr_cell = ind.getCurrCell(); + assert(ind.getStatus() == 6); + assert(curr_cell == 0); // out of the landscape // An individual with a small dispersal distance is unlikely to reach a distant cell diff --git a/Main.cpp b/Main.cpp index 6172b8a..b5e05b4 100644 --- a/Main.cpp +++ b/Main.cpp @@ -64,6 +64,7 @@ ofstream MUTNLOG; vector hfnames; Species* pSpecies; Community* pComm; + void DebugGUI(string msg) { // nothing } @@ -90,6 +91,14 @@ int _tmain(int argc, _TCHAR* argv[]) cout << "This code is only for running tests and not meant to run in release." << endl; return 1; # else + + // Initialise globals + paramsGrad = new paramGrad; + paramsStoch = new paramStoch; + paramsInit = new paramInit; + paramsSim = new paramSim; + pRandom = new RSrandom; + assert(0.1 > 0.0); // assert does run correctly try { run_unit_tests(); From a1eb7df9699c0c26d23da22d43e6677e7127b3a9 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 16 Jan 2024 14:01:48 +0000 Subject: [PATCH 012/332] test for distance-dep mortality in kernel transfer --- Individual.cpp | 39 ++++++++++++++++++++++++++------------- Species.cpp | 2 +- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 2efbcf0..a1939c4 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1940,6 +1940,7 @@ void testIndividual() { cells.push_back(new Cell(x, y, 0, 0)); } } + for (auto c : cells) ls.addCellToLand(c); ls.allocatePatches(&sp); ls.updateCarryingCapacity(&sp, 0, 0); @@ -1963,22 +1964,34 @@ void testIndividual() { assert(ind.getStatus() == 6); assert(curr_cell == 0); // out of the landscape - // An individual with a small dispersal distance is unlikely to reach a distant cell - - // An individual with a large dispersal distance should be able to reach a distant cell - - // If no cell is available beyond initial cell, individual should die + // Dispersal-related mortality + // Fixed mortality + mort.fixedMort = 1.0; // Individual *will* die after any step + sp.setMortParams(mort); + trfr.distMort = false; + sp.setTrfr(trfr); + ind = starting_ind; + isDispersing = ind.moveKernel(&ls, &sp, false); + assert(ind.getStatus() == 7); + // Distance-dependent mortality + trfr.distMort = true; + sp.setTrfr(trfr); + mort.mortAlpha = 1000.0; // very steep threshold + mort.mortBeta = 0.5; // very small distance + sp.setMortParams(mort); + kern.meanDist1 = 5; // very likely to go over threshold + sp.setKernTraits(0, 0, kern, ls_params.resol); + ind = starting_ind; + isDispersing = ind.moveKernel(&ls, &sp, false); + assert(ind.getStatus() == 7); + mort.mortBeta = 30; // very large distance, unlikely to draw + sp.setMortParams(mort); + ind = starting_ind; + isDispersing = ind.moveKernel(&ls, &sp, false); + assert(ind.getStatus() != 7); - // } - // Individual::moveKernel(Landscape * pLandscape, Species * pSpecies, const short repType, const bool absorbing) - // Settles - - // Survives - - // Develops - } #endif // RSDEBUG diff --git a/Species.cpp b/Species.cpp index 0be29ca..cb33f9a 100644 --- a/Species.cpp +++ b/Species.cpp @@ -1024,7 +1024,7 @@ trfrKernTraits Species::getKernTraits(short stg, short sex) { } void Species::setMortParams(const trfrMortParams m) { - if (m.fixedMort >= 0.0 && m.fixedMort < 1.0) fixedMort = m.fixedMort; + if (m.fixedMort >= 0.0 && m.fixedMort <= 1.0) fixedMort = m.fixedMort; mortAlpha = m.mortAlpha; mortBeta = m.mortBeta; } From 6d1a11679551f72681fa0ddab8c62b5e1e1b9827 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 16 Jan 2024 16:58:19 +0000 Subject: [PATCH 013/332] test twin kernels --- Individual.cpp | 36 ++++++++++++++++++++++++++++++++---- Species.cpp | 2 +- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index a1939c4..2d79eba 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1924,6 +1924,28 @@ void testIndividual() { assert(ind.getStatus() == 6); // RIP in peace assert(curr_cell == init_cell); + // Twin kernels + trfr.twinKern = true; + sp.setTrfr(trfr); + kern.meanDist1 = 1.0; // very unlikely to reach suitable cells + kern.meanDist2 = 5.0; // easily reaches suitable cells... + kern.probKern1 = 1.0; // ... but never used + sp.setKernTraits(0, 0, kern, ls_params.resol); + ind = starting_ind; + isDispersing = ind.moveKernel(&ls, &sp, false); + assert(ind.getStatus() == 6); + kern.probKern1 = 0.0; // always use second kernel + sp.setKernTraits(0, 0, kern, ls_params.resol); + ind = starting_ind; + isDispersing = ind.moveKernel(&ls, &sp, false); + assert(ind.getStatus() == 2); + + trfr.twinKern = false; + sp.setTrfr(trfr); + + // Sex-dependent dispersal distances + + /* Boundaries: dispersal distance overshoots Only adjacent cells are available ----- @@ -1947,19 +1969,21 @@ void testIndividual() { init_cell = cells[4]; // that is, the center init_patch = (Patch*)init_cell->getPatch(); - kern.meanDist1 = 5; // overshoots *most* of the time... + kern.meanDist1 = 10; // overshoots *most* of the time... sp.setKernTraits(0, 0, kern, ls_params.resol); ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual // Non-absorbing boundaries - isDispersing = ind.moveKernel(&ls, &sp, false); + bool absorbing_boundaries{ false }; + isDispersing = ind.moveKernel(&ls, &sp, absorbing_boundaries); curr_cell = ind.getCurrCell(); assert(curr_cell != init_cell); // ...should be able to move eventually assert(ind.getStatus() == 2); // Absorbing boundaries + absorbing_boundaries = true; ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual - isDispersing = ind.moveKernel(&ls, &sp, true); + isDispersing = ind.moveKernel(&ls, &sp, absorbing_boundaries); curr_cell = ind.getCurrCell(); assert(ind.getStatus() == 6); assert(curr_cell == 0); // out of the landscape @@ -1990,7 +2014,11 @@ void testIndividual() { isDispersing = ind.moveKernel(&ls, &sp, false); assert(ind.getStatus() != 7); - + // Reset mortality params + trfr.distMort = false; + mort.fixedMort = 0.0; + sp.setTrfr(trfr); + sp.setMortParams(mort); } } #endif // RSDEBUG diff --git a/Species.cpp b/Species.cpp index cb33f9a..145f6e2 100644 --- a/Species.cpp +++ b/Species.cpp @@ -1006,7 +1006,7 @@ void Species::setKernTraits(const short stg, const short sex, if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { if (k.meanDist1 > 0.0 && k.meanDist1 >= (float)resol) meanDist1[stg][sex] = k.meanDist1; if (k.meanDist2 >= (float)resol) meanDist2[stg][sex] = k.meanDist2; - if (k.probKern1 > 0.0 && k.probKern1 < 1.0) probKern1[stg][sex] = k.probKern1; + if (k.probKern1 >= 0.0 && k.probKern1 <= 1.0) probKern1[stg][sex] = k.probKern1; } } From 60238a06e12ab1735720caacd9e48f057aa75644 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 16 Jan 2024 17:37:39 +0000 Subject: [PATCH 014/332] sex- and stage-dependent dispersal --- Individual.cpp | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 2d79eba..832fc33 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1927,8 +1927,8 @@ void testIndividual() { // Twin kernels trfr.twinKern = true; sp.setTrfr(trfr); - kern.meanDist1 = 1.0; // very unlikely to reach suitable cells - kern.meanDist2 = 5.0; // easily reaches suitable cells... + kern.meanDist1 = 1.0; // very unlikely to reach suitable cell + kern.meanDist2 = 5.0; // easily reaches suitable cell... kern.probKern1 = 1.0; // ... but never used sp.setKernTraits(0, 0, kern, ls_params.resol); ind = starting_ind; @@ -1939,12 +1939,54 @@ void testIndividual() { ind = starting_ind; isDispersing = ind.moveKernel(&ls, &sp, false); assert(ind.getStatus() == 2); - + // reset trfr.twinKern = false; sp.setTrfr(trfr); + kern.probKern1 = 1.0; + sp.setKernTraits(0, 0, kern, ls_params.resol); // Sex-dependent dispersal distances + trfr.sexDep = true; + sp.setTrfr(trfr); + trfrKernTraits kern_f = kern; + kern_f.meanDist1 = 1.0; // female very unlikely to reach suitable cell + sp.setKernTraits(0, 0, kern_f, ls_params.resol); + trfrKernTraits kern_m = kern; + kern_m.meanDist1 = 5.0; // male easily reaches suitable cell + sp.setKernTraits(0, 1, kern_m, ls_params.resol); + + ind = starting_ind; // female as default + isDispersing = ind.moveKernel(&ls, &sp, false); + assert(ind.getStatus() == 6); + + ind = Individual(init_cell, init_patch, 1, 0, 0, 1.0, false, 0); // male + assert(ind.getSex() == 1); + isDispersing = ind.moveKernel(&ls, &sp, false); + assert(ind.getStatus() == 2); + // reset + trfr.sexDep = false; + sp.setTrfr(trfr); + + // Stage-dependent + trfr.stgDep = true; + sp.setTrfr(trfr); + trfrKernTraits kern_juv = kern; + kern_juv.meanDist1 = 1.0; // juveniles very unlikely to reach suitable cell + sp.setKernTraits(0, 0, kern_juv, ls_params.resol); + trfrKernTraits kern_adult = kern; + kern_adult.meanDist1 = 5.0; // adults easily reach suitable cell + sp.setKernTraits(1, 0, kern_adult, ls_params.resol); + + ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, false, 0); // juvenile + isDispersing = ind.moveKernel(&ls, &sp, false); + assert(ind.getStatus() == 6); + ind = starting_ind; // adult by default + isDispersing = ind.moveKernel(&ls, &sp, false); + assert(ind.getStatus() == 2); + // reset + trfr.stgDep = false; + sp.setTrfr(trfr); /* Boundaries: dispersal distance overshoots Only adjacent cells are available From d6cc7cddfac2b2af65bc599f7021aeb8373309c9 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 18 Jan 2024 17:31:57 +0000 Subject: [PATCH 015/332] why is RS so afraid of the number 1?? --- Individual.cpp | 134 +++++++++++++++++++++++++++++++++++++++++++------ Species.cpp | 2 +- 2 files changed, 121 insertions(+), 15 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 832fc33..cac2356 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -446,7 +446,8 @@ void Individual::setYearSteps(int t) { pathSteps Individual::getSteps(void) { pathSteps s; if (path == 0) { - s.year = 0; s.total = 0; s.out = 0; + throw logic_error("path variable is not initialised"); + //s.year = 0; s.total = 0; s.out = 0; } else { s.year = path->year; s.total = path->total; s.out = path->out; @@ -1066,7 +1067,6 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, const bool int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, const short landIx, const bool absorbing) { - if (status != 1) return 0; // not currently dispersing intptr patch; @@ -1849,6 +1849,7 @@ void testIndividual() { // Disperses // Emigrates // Transfers + // Kernel-based transfer { // Simple cell-based landscape layout @@ -1858,9 +1859,16 @@ void testIndividual() { ls_params.maxX = ls_params.maxY = ls_params.dimX - 1; ls_params.resol = 1; + Landscape ls; + ls.setLandParams(ls_params, true); + // Two suitable cells in opposite corners Cell* init_cell = new Cell(0, 0, 0, 0); Cell* final_cell = new Cell(ls_params.dimX - 1, ls_params.dimY - 1, 0, 0); + ls.setCellArray(); + ls.addCellToLand(init_cell); + ls.addCellToLand(final_cell); + // Set up species Species sp; // Habitat codes @@ -1888,22 +1896,14 @@ void testIndividual() { settleRules sett; sett.wait = false; sp.setSettRules(0, 0, sett); - - // Landscape ls = createLandscapeFromCells(cells, ls_params, sp); - Landscape ls; - ls.setLandParams(ls_params, true); - // Add cells - ls.setCellArray(); - ls.addCellToLand(init_cell); - ls.addCellToLand(final_cell); - ls.allocatePatches(&sp); - ls.updateCarryingCapacity(&sp, 0, 0); - + + // Set up patches + ls.allocatePatches(&sp); + ls.updateCarryingCapacity(&sp, 0, 0); Patch* init_patch = (Patch*)init_cell->getPatch(); // Create and set up individual Individual starting_ind(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); - // Set aside original individual and test on a copy Individual ind = starting_ind; // pathData *path; ? @@ -2062,6 +2062,112 @@ void testIndividual() { sp.setTrfr(trfr); sp.setMortParams(mort); } + + // Correlated random walk (CRW) + { + // Simple cell-based landscape layout + landParams ls_params; + ls_params.dimX = ls_params.dimY = 5; + ls_params.minX = ls_params.minY = 0; + ls_params.maxX = ls_params.maxY = ls_params.dimX - 1; + ls_params.resol = 1; + + Landscape ls; + ls.setLandParams(ls_params, true); + + // All cells are suitable + vector cell_vec; + for (int x = ls_params.minX; x < ls_params.dimX; ++x) { + for (int y = ls_params.minY; y < ls_params.dimY; ++y) { + cell_vec.push_back(new Cell(x, y, 0, 0)); + } + } + Cell* init_cell = cell_vec[12]; // central + //Cell* final_cell = new Cell(ls_params.dimX - 1, ls_params.dimY - 1, 0, 0); + ls.setCellArray(); + for (auto c : cell_vec) ls.addCellToLand(c); + + // Set up species + Species sp; + const int hab_index = 0; + + // Habitat codes + sp.createHabK(1); + sp.setHabK(hab_index, 100.0); // one habitat with K = 10 + + // Habitat-dependent mortality + sp.createHabCostMort(1); + sp.setHabMort(hab_index, 0.0); + + // Transfer rules + trfrRules trfr; + trfr.indVar = false; + trfr.habMort = false; + trfr.moveType = 2; // CRW + sp.setTrfr(trfr); + + // Transfer CRW traits + trfrMovtTraits m; + m.stepMort = 0.0; + m.stepLength = ls_params.resol; + m.rho = 1.0; + m.straigtenPath = false; + sp.setMovtTraits(m); + + // Settlement rules + settleRules sett; + sett.wait = false; + sp.setSettRules(0, 0, sett); + settleSteps steps; + steps.maxSteps = 1; + steps.minSteps = 1; + steps.maxStepsYr = 1; + sp.setSteps(0, 0, steps); + + // Set up patches + ls.allocatePatches(&sp); + ls.updateCarryingCapacity(&sp, 0, 0); + Patch* init_patch = (Patch*)init_cell->getPatch(); + + // Create and set up individual + Individual ind(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); + + // Set aside original individual and test on a copy + // ind.setYearSteps(); // if needed + // ind.getSteps(); + + // Set status + assert(ind.getStatus() == 0); // default status, not emigrating + int isDispersing = ind.moveStep(&ls, &sp, hab_index, false); + assert(ind.getStatus() == 0); // status didn't change + assert(ind.getCurrCell() == init_cell); // not emigrating so didn't move + ind.~Individual(); + + // Per-step mortality + m.stepMort = 1.0; // should die + sp.setMovtTraits(m); + Individual new_ind(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); + // new ind bc for some reason I don' t understand yet if reset ind we lose path data upon exiting constructor + // surely some pointer fun + new_ind.setStatus(1); + isDispersing = new_ind.moveStep(&ls, &sp, hab_index, false); + // Individual begins in natal patch so mortality is disabled + assert(new_ind.getStatus() != 7); + // Individual should be in a different patch + Cell* first_step_cell = new_ind.getCurrCell(); + assert(first_step_cell != init_cell); + assert((Patch*)first_step_cell->getPatch() != init_patch); + new_ind.setStatus(1); // emigrating again + + // Individual should die on second step + isDispersing = new_ind.moveStep(&ls, &sp, hab_index, false); + assert(new_ind.getCurrCell() == first_step_cell); // shouldn't have moved + assert(new_ind.getStatus() == 7); // died by transfer + + // ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); // reset + + // Habitat-dep mortality + } } #endif // RSDEBUG diff --git a/Species.cpp b/Species.cpp index 145f6e2..d55b5ed 100644 --- a/Species.cpp +++ b/Species.cpp @@ -1044,7 +1044,7 @@ void Species::setMovtTraits(const trfrMovtTraits m) { if (m.gb >= 1.0) gb = m.gb; if (m.alphaDB > 0.0) alphaDB = m.alphaDB; if (m.betaDB > 0) betaDB = m.betaDB; - if (m.stepMort >= 0.0 && m.stepMort < 1.0) stepMort = m.stepMort; + if (m.stepMort >= 0.0 && m.stepMort <= 1.0) stepMort = m.stepMort; if (m.stepLength > 0.0) stepLength = m.stepLength; if (m.rho > 0.0 && m.rho < 1.0) rho = m.rho; straigtenPath = m.straigtenPath; From 661adf054ccb083c15d46ccbe48e96ad79a40da5 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 18 Jan 2024 17:32:40 +0000 Subject: [PATCH 016/332] progress with testing CRW but memory bug I hate pointers and their fandom --- Individual.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index cac2356..6879d1b 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -446,8 +446,7 @@ void Individual::setYearSteps(int t) { pathSteps Individual::getSteps(void) { pathSteps s; if (path == 0) { - throw logic_error("path variable is not initialised"); - //s.year = 0; s.total = 0; s.out = 0; + s.year = 0; s.total = 0; s.out = 0; } else { s.year = path->year; s.total = path->total; s.out = path->out; From 601df3eb5678edb7ef02ce4d7ebffda377ed0acc Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 19 Jan 2024 13:21:02 +0000 Subject: [PATCH 017/332] fix build by forcibly setting path and crw --- Individual.cpp | 73 +++++++++++++++++++++++++++++++++----------------- Individual.h | 2 ++ Species.cpp | 2 +- 3 files changed, 51 insertions(+), 26 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 6879d1b..e84a1e2 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1813,12 +1813,23 @@ double cauchy(double location, double scale) { //--------------------------------------------------------------------------- #if RSDEBUG +// Testing utilities + Cell* Individual::getCurrCell() const { return pCurrCell; } +void Individual::setPath(pathData* pPath) { + path = pPath; +} + +void Individual::setCRW(crwParams* pCRW) { + crw = pCRW; +} + void testIndividual() { + /* Patch* pPatch = new Patch(0, 0); int cell_x = 2; int cell_y = 5; @@ -1833,6 +1844,7 @@ void testIndividual() { bool uses_movt_process = true; short moveType = 1; Individual ind(pCell, pPatch, stg, age, repInt, probmale, uses_movt_process, moveType); + */ // Gets its sex drawn from pmale @@ -1902,9 +1914,9 @@ void testIndividual() { Patch* init_patch = (Patch*)init_cell->getPatch(); // Create and set up individual - Individual starting_ind(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + //Individual starting_ind(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // Set aside original individual and test on a copy - Individual ind = starting_ind; + Individual ind(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // pathData *path; ? int isDispersing = ind.moveKernel(&ls, &sp, false); @@ -1917,7 +1929,7 @@ void testIndividual() { // If no cell within reasonable dispersal reach, individual does not move and dies kern.meanDist1 = 1.0; sp.setKernTraits(0, 0, kern, ls_params.resol); - ind = starting_ind; // reset individual + ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual isDispersing = ind.moveKernel(&ls, &sp, false); curr_cell = ind.getCurrCell(); assert(ind.getStatus() == 6); // RIP in peace @@ -1930,12 +1942,12 @@ void testIndividual() { kern.meanDist2 = 5.0; // easily reaches suitable cell... kern.probKern1 = 1.0; // ... but never used sp.setKernTraits(0, 0, kern, ls_params.resol); - ind = starting_ind; + ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind.moveKernel(&ls, &sp, false); assert(ind.getStatus() == 6); kern.probKern1 = 0.0; // always use second kernel sp.setKernTraits(0, 0, kern, ls_params.resol); - ind = starting_ind; + ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind.moveKernel(&ls, &sp, false); assert(ind.getStatus() == 2); // reset @@ -1954,7 +1966,7 @@ void testIndividual() { kern_m.meanDist1 = 5.0; // male easily reaches suitable cell sp.setKernTraits(0, 1, kern_m, ls_params.resol); - ind = starting_ind; // female as default + ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // female as default isDispersing = ind.moveKernel(&ls, &sp, false); assert(ind.getStatus() == 6); @@ -1980,7 +1992,7 @@ void testIndividual() { isDispersing = ind.moveKernel(&ls, &sp, false); assert(ind.getStatus() == 6); - ind = starting_ind; // adult by default + ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // adult by default isDispersing = ind.moveKernel(&ls, &sp, false); assert(ind.getStatus() == 2); // reset @@ -2035,7 +2047,7 @@ void testIndividual() { sp.setMortParams(mort); trfr.distMort = false; sp.setTrfr(trfr); - ind = starting_ind; + ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind.moveKernel(&ls, &sp, false); assert(ind.getStatus() == 7); // Distance-dependent mortality @@ -2046,12 +2058,12 @@ void testIndividual() { sp.setMortParams(mort); kern.meanDist1 = 5; // very likely to go over threshold sp.setKernTraits(0, 0, kern, ls_params.resol); - ind = starting_ind; + ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind.moveKernel(&ls, &sp, false); assert(ind.getStatus() == 7); mort.mortBeta = 30; // very large distance, unlikely to draw sp.setMortParams(mort); - ind = starting_ind; + ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind.moveKernel(&ls, &sp, false); assert(ind.getStatus() != 7); @@ -2060,6 +2072,8 @@ void testIndividual() { mort.fixedMort = 0.0; sp.setTrfr(trfr); sp.setMortParams(mort); + + ind.~Individual(); } // Correlated random walk (CRW) @@ -2075,10 +2089,11 @@ void testIndividual() { ls.setLandParams(ls_params, true); // All cells are suitable + const int hab_index = 0; vector cell_vec; for (int x = ls_params.minX; x < ls_params.dimX; ++x) { for (int y = ls_params.minY; y < ls_params.dimY; ++y) { - cell_vec.push_back(new Cell(x, y, 0, 0)); + cell_vec.push_back(new Cell(x, y, 0, hab_index)); } } Cell* init_cell = cell_vec[12]; // central @@ -2088,7 +2103,6 @@ void testIndividual() { // Set up species Species sp; - const int hab_index = 0; // Habitat codes sp.createHabK(1); @@ -2096,7 +2110,7 @@ void testIndividual() { // Habitat-dependent mortality sp.createHabCostMort(1); - sp.setHabMort(hab_index, 0.0); + // sp.setHabMort(hab_index, 0.0); // Transfer rules trfrRules trfr; @@ -2140,28 +2154,37 @@ void testIndividual() { int isDispersing = ind.moveStep(&ls, &sp, hab_index, false); assert(ind.getStatus() == 0); // status didn't change assert(ind.getCurrCell() == init_cell); // not emigrating so didn't move - ind.~Individual(); + //ind.~Individual(); // Per-step mortality m.stepMort = 1.0; // should die sp.setMovtTraits(m); - Individual new_ind(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); - // new ind bc for some reason I don' t understand yet if reset ind we lose path data upon exiting constructor - // surely some pointer fun - new_ind.setStatus(1); - isDispersing = new_ind.moveStep(&ls, &sp, hab_index, false); + ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); + // force set path bc for some reason path gets deallocated upon exiting constructor?? + pathData* pPath = new pathData; + pPath->out = pPath->year = pPath->total = 0; + pPath->pSettPatch = 0; pPath->settleStatus = 0; + ind.setPath(pPath); + crwParams* pCRW = new crwParams; + pCRW->prevdrn = (float)(pRandom->Random() * 2.0 * PI); + pCRW->xc = ((float)pRandom->Random() * 0.999f) + (float)init_cell->getLocn().x; + pCRW->yc = ((float)pRandom->Random() * 0.999f) + (float)init_cell->getLocn().y; + pCRW->stepL = m.stepLength; pCRW->rho = m.rho; + ind.setCRW(pCRW); + ind.setStatus(1); + isDispersing = ind.moveStep(&ls, &sp, hab_index, false); // Individual begins in natal patch so mortality is disabled - assert(new_ind.getStatus() != 7); + assert(ind.getStatus() != 7); // Individual should be in a different patch - Cell* first_step_cell = new_ind.getCurrCell(); + Cell* first_step_cell = ind.getCurrCell(); assert(first_step_cell != init_cell); assert((Patch*)first_step_cell->getPatch() != init_patch); - new_ind.setStatus(1); // emigrating again + ind.setStatus(1); // emigrating again // Individual should die on second step - isDispersing = new_ind.moveStep(&ls, &sp, hab_index, false); - assert(new_ind.getCurrCell() == first_step_cell); // shouldn't have moved - assert(new_ind.getStatus() == 7); // died by transfer + isDispersing = ind.moveStep(&ls, &sp, hab_index, false); + assert(ind.getCurrCell() == first_step_cell); // shouldn't have moved + assert(ind.getStatus() == 7); // died by transfer // ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); // reset diff --git a/Individual.h b/Individual.h index 5d2366c..edd6e8c 100644 --- a/Individual.h +++ b/Individual.h @@ -254,6 +254,8 @@ class Individual { #if RSDEBUG // Testing utilities Cell* getCurrCell() const; + void setPath(pathData* pPath); + void setCRW(crwParams* pCRW); #endif private: diff --git a/Species.cpp b/Species.cpp index d55b5ed..482aeb2 100644 --- a/Species.cpp +++ b/Species.cpp @@ -1046,7 +1046,7 @@ void Species::setMovtTraits(const trfrMovtTraits m) { if (m.betaDB > 0) betaDB = m.betaDB; if (m.stepMort >= 0.0 && m.stepMort <= 1.0) stepMort = m.stepMort; if (m.stepLength > 0.0) stepLength = m.stepLength; - if (m.rho > 0.0 && m.rho < 1.0) rho = m.rho; + if (m.rho > 0.0 && m.rho <= 1.0) rho = m.rho; straigtenPath = m.straigtenPath; } From 414782516c8ec46465356fe450365ed8484477e2 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 19 Jan 2024 13:37:25 +0000 Subject: [PATCH 018/332] rm silent reset of stepL and rho --- Individual.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index e84a1e2..2cb7d48 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1162,8 +1162,8 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, } } - steplen = movt.stepLength; if (steplen < 0.2 * land.resol) steplen = 0.2 * land.resol; - rho = movt.rho; if (rho > 0.99) rho = 0.99; + steplen = movt.stepLength; + rho = movt.rho; if (pPatch == pNatalPatch) { rho = 0.99; // to promote leaving natal patch path->out = 0; From 543b4e29156751e2a8b9af3ae679af0b5225538f Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 19 Jan 2024 15:24:20 +0000 Subject: [PATCH 019/332] test individual dies if step too short --- Individual.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++-------- Individual.h | 2 ++ 2 files changed, 69 insertions(+), 13 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 2cb7d48..8510d30 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1827,6 +1827,26 @@ void Individual::setCRW(crwParams* pCRW) { crw = pCRW; } +// Force initialisation of path as it sometimes doesn't set?? +void Individual::forceInitPath() { + pathData* pPath = new pathData; + pPath->out = pPath->year = pPath->total = 0; + pPath->pSettPatch = 0; pPath->settleStatus = 0; + setPath(pPath); +} + +// Force initialisation of crw as it sometimes doesn't set?? +void Individual::forceInitCRW(const trfrMovtTraits& m) { + crwParams* pCRW = new crwParams; + pCRW->prevdrn = (float)(pRandom->Random() * 2.0 * PI); + pCRW->xc = ((float)pRandom->Random() * 0.999f) + (float)pCurrCell->getLocn().x; + pCRW->yc = ((float)pRandom->Random() * 0.999f) + (float)pCurrCell->getLocn().y; + pCRW->stepL = m.stepLength; pCRW->rho = m.rho; + setCRW(pCRW); +} + + + void testIndividual() { /* @@ -2159,18 +2179,10 @@ void testIndividual() { // Per-step mortality m.stepMort = 1.0; // should die sp.setMovtTraits(m); - ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); + ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); // force set path bc for some reason path gets deallocated upon exiting constructor?? - pathData* pPath = new pathData; - pPath->out = pPath->year = pPath->total = 0; - pPath->pSettPatch = 0; pPath->settleStatus = 0; - ind.setPath(pPath); - crwParams* pCRW = new crwParams; - pCRW->prevdrn = (float)(pRandom->Random() * 2.0 * PI); - pCRW->xc = ((float)pRandom->Random() * 0.999f) + (float)init_cell->getLocn().x; - pCRW->yc = ((float)pRandom->Random() * 0.999f) + (float)init_cell->getLocn().y; - pCRW->stepL = m.stepLength; pCRW->rho = m.rho; - ind.setCRW(pCRW); + ind.forceInitPath(); + ind.forceInitCRW(m); ind.setStatus(1); isDispersing = ind.moveStep(&ls, &sp, hab_index, false); // Individual begins in natal patch so mortality is disabled @@ -2185,10 +2197,52 @@ void testIndividual() { isDispersing = ind.moveStep(&ls, &sp, hab_index, false); assert(ind.getCurrCell() == first_step_cell); // shouldn't have moved assert(ind.getStatus() == 7); // died by transfer - - // ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); // reset + m.stepMort = 0.0; // not dying + sp.setMovtTraits(m); // Habitat-dep mortality + + + // Step size + ls = Landscape(); + ls.setLandParams(ls_params, true); + // Only two suitable cells in opposite corners + init_cell = new Cell(0, 0, 0, 0); + Cell* final_cell = new Cell(ls_params.dimX - 1, ls_params.dimY - 1, 0, 0); + ls.setCellArray(); + ls.addCellToLand(init_cell); + ls.addCellToLand(final_cell); + ls.allocatePatches(&sp); + ls.updateCarryingCapacity(&sp, 0, 0); + init_patch = (Patch*)init_cell->getPatch(); + // Too short step length + m.stepLength = 0.1; // cannot reach final cell + m.rho = 0.0; // random angle + sp.setMovtTraits(m); + steps.minSteps = 1; + steps.maxStepsYr = 2; + steps.maxSteps = 3; + sp.setSteps(0, 0, steps); + + ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + ind.setStatus(1); // dispersing + ind.forceInitPath(); + ind.forceInitCRW(m); + // First step - individual can't reach final cell so still dispersing + isDispersing = ind.moveStep(&ls, &sp, hab_index, false); + assert(ind.getCurrCell() == init_cell); + assert(ind.getStatus() == 1); + // Second step - reaching max steps this year, wait next year + isDispersing = ind.moveStep(&ls, &sp, hab_index, false); + assert(ind.getCurrCell() == init_cell); + assert(ind.getStatus() == 3); + ind.setStatus(1); // dispersing again + // Third step - reaching max steps, dies + isDispersing = ind.moveStep(&ls, &sp, hab_index, false); + assert(ind.getCurrCell() == init_cell); + assert(ind.getStatus() == 6); + + } } #endif // RSDEBUG diff --git a/Individual.h b/Individual.h index edd6e8c..0a676c3 100644 --- a/Individual.h +++ b/Individual.h @@ -256,6 +256,8 @@ class Individual { Cell* getCurrCell() const; void setPath(pathData* pPath); void setCRW(crwParams* pCRW); + void forceInitPath(); + void forceInitCRW(const trfrMovtTraits&); #endif private: From 85b7107befb3eb79a2da91345af81aa2ba359988 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 19 Jan 2024 15:58:11 +0000 Subject: [PATCH 020/332] test crw step length and absorbing boundaries --- Individual.cpp | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 8510d30..baf0342 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -2215,7 +2215,8 @@ void testIndividual() { ls.allocatePatches(&sp); ls.updateCarryingCapacity(&sp, 0, 0); init_patch = (Patch*)init_cell->getPatch(); - // Too short step length + + // Step length too short m.stepLength = 0.1; // cannot reach final cell m.rho = 0.0; // random angle sp.setMovtTraits(m); @@ -2223,7 +2224,6 @@ void testIndividual() { steps.maxStepsYr = 2; steps.maxSteps = 3; sp.setSteps(0, 0, steps); - ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); ind.setStatus(1); // dispersing ind.forceInitPath(); @@ -2242,6 +2242,42 @@ void testIndividual() { assert(ind.getCurrCell() == init_cell); assert(ind.getStatus() == 6); + // Step length too long + m.stepLength = ls_params.dimX * SQRT2 * 1.5; // overshoots + sp.setMovtTraits(m); + ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + ind.setStatus(1); // dispersing + ind.forceInitPath(); + ind.forceInitCRW(m); + steps.minSteps = 1; + steps.maxStepsYr = 1; + steps.maxSteps = 1; // no need to test more than one step this time + sp.setSteps(0, 0, steps); + isDispersing = ind.moveStep(&ls, &sp, hab_index, false); + assert(ind.getCurrCell() == init_cell); + assert(ind.getStatus() == 6); + + // Adequate step length + m.stepLength = (ls_params.dimX - 1) * SQRT2; + sp.setMovtTraits(m); + ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + ind.setStatus(1); // dispersing + ind.forceInitPath(); + ind.forceInitCRW(m); + // Initial angle still random but should eventually reach the right cell + isDispersing = ind.moveStep(&ls, &sp, hab_index, false); + assert(ind.getStatus() == 2); + assert(ind.getCurrCell() == final_cell); + + // If boundaries are absorbing however, very likely to die + ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + ind.setStatus(1); // dispersing + ind.forceInitPath(); + ind.forceInitCRW(m); + bool absorbing_boundaries = true; + isDispersing = ind.moveStep(&ls, &sp, hab_index, absorbing_boundaries); + assert(ind.getStatus() == 6); + assert(ind.getCurrCell() == 0); // deref apparently } } From 19b361ea5112961261d62eabf13bb7447b1b3567 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 19 Jan 2024 16:29:04 +0000 Subject: [PATCH 021/332] progress towards test for crw correlation param --- Individual.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index baf0342..660b9e9 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -2165,7 +2165,6 @@ void testIndividual() { // Create and set up individual Individual ind(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); - // Set aside original individual and test on a copy // ind.setYearSteps(); // if needed // ind.getSteps(); @@ -2201,7 +2200,7 @@ void testIndividual() { sp.setMovtTraits(m); // Habitat-dep mortality - + // ... // Step size ls = Landscape(); @@ -2279,6 +2278,32 @@ void testIndividual() { assert(ind.getStatus() == 6); assert(ind.getCurrCell() == 0); // deref apparently + // Correlation parameter + // If rho = 1, should move in a straight line (after moving out of initial patch) + + // Add a central cell to get a diagonal of suitable cells + Cell* pMiddleCell = new Cell(2, 2, 0, hab_index); + ls.addCellToLand(pMiddleCell); + ls.allocatePatches(&sp); + ls.updateCarryingCapacity(&sp, 0, 0); + m.stepLength = 2 * SQRT2; // move by 1 cell diagonally + m.rho = 1; + sp.setMovtTraits(m); + steps.maxStepsYr = steps.maxSteps = 2; + sp.setSteps(0, 0, steps); + ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + ind.setStatus(1); // dispersing + ind.forceInitPath(); + ind.forceInitCRW(m); + isDispersing = ind.moveStep(&ls, &sp, hab_index, false); + assert(ind.getStatus() == 2); + assert(ind.getCurrCell() == pMiddleCell); + ind.setStatus(1); // emigrate again + isDispersing = ind.moveStep(&ls, &sp, hab_index, false); + assert(ind.getStatus() == 2); + assert(ind.getCurrCell() == final_cell); + // not a good test yet, must add other suitable cells + // and start outside of natal patch } } #endif // RSDEBUG From ad90a0cd38f23649bbe045f6e182a38a272c88fa Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 22 Jan 2024 10:28:38 +0000 Subject: [PATCH 022/332] don't start in natal patch --- Individual.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 660b9e9..9bb22c6 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -2213,8 +2213,8 @@ void testIndividual() { ls.addCellToLand(final_cell); ls.allocatePatches(&sp); ls.updateCarryingCapacity(&sp, 0, 0); - init_patch = (Patch*)init_cell->getPatch(); - + // Init cell is NOT in natal patch + Patch* natalPatch = new Patch(0, 0); // Step length too short m.stepLength = 0.1; // cannot reach final cell m.rho = 0.0; // random angle @@ -2223,7 +2223,7 @@ void testIndividual() { steps.maxStepsYr = 2; steps.maxSteps = 3; sp.setSteps(0, 0, steps); - ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + ind = Individual(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); ind.setStatus(1); // dispersing ind.forceInitPath(); ind.forceInitCRW(m); @@ -2244,7 +2244,7 @@ void testIndividual() { // Step length too long m.stepLength = ls_params.dimX * SQRT2 * 1.5; // overshoots sp.setMovtTraits(m); - ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + ind = Individual(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); ind.setStatus(1); // dispersing ind.forceInitPath(); ind.forceInitCRW(m); @@ -2259,7 +2259,7 @@ void testIndividual() { // Adequate step length m.stepLength = (ls_params.dimX - 1) * SQRT2; sp.setMovtTraits(m); - ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + ind = Individual(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); ind.setStatus(1); // dispersing ind.forceInitPath(); ind.forceInitCRW(m); @@ -2269,7 +2269,7 @@ void testIndividual() { assert(ind.getCurrCell() == final_cell); // If boundaries are absorbing however, very likely to die - ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + ind = Individual(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); ind.setStatus(1); // dispersing ind.forceInitPath(); ind.forceInitCRW(m); @@ -2291,7 +2291,7 @@ void testIndividual() { sp.setMovtTraits(m); steps.maxStepsYr = steps.maxSteps = 2; sp.setSteps(0, 0, steps); - ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + ind = Individual(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); ind.setStatus(1); // dispersing ind.forceInitPath(); ind.forceInitCRW(m); @@ -2304,6 +2304,8 @@ void testIndividual() { assert(ind.getCurrCell() == final_cell); // not a good test yet, must add other suitable cells // and start outside of natal patch + + } } #endif // RSDEBUG From 90b82921bb8e82b92e022688ea51f2a87778b461 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 31 Jan 2024 13:57:14 +0000 Subject: [PATCH 023/332] merging @RoslynHenry's new genetics module to main RS code --- Community.cpp | 394 +++++++++++++- Community.h | 127 +++-- Distributions.h | 70 +++ FractalGenerator.cpp | 6 - GeneticLoad.cpp | 440 +++++++++++++++ GeneticLoad.h | 64 +++ Genome.cpp | 861 ----------------------------- Genome.h | 251 --------- Individual.cpp | 1132 +++++++++++++-------------------------- Individual.h | 230 ++++++-- Landscape.cpp | 675 ++++++++++++----------- Landscape.h | 9 +- Model.cpp | 422 ++++----------- Model.h | 7 +- Mutation.h | 16 + NeutralStatsManager.cpp | 713 ++++++++++++++++++++++++ NeutralStatsManager.h | 177 ++++++ Parameters.cpp | 38 +- Parameters.h | 93 +++- Patch.h | 7 +- Population.cpp | 446 +++++++++------ Population.h | 39 +- ProtoTrait.cpp | 172 ++++++ ProtoTrait.h | 56 ++ QTLTrait.cpp | 452 ++++++++++++++++ QTLTrait.h | 56 ++ RSrandom.cpp | 140 +++-- RSrandom.h | 17 +- RandomCheck.cpp | 93 ---- RandomCheck.h | 47 -- SNPTrait.cpp | 326 +++++++++++ SNPTrait.h | 79 +++ Species.cpp | 864 ++++-------------------------- Species.h | 351 ++++-------- SubCommunity.cpp | 129 ++++- SubCommunity.h | 28 +- TTrait.h | 44 ++ TraitFactory.h | 27 + 38 files changed, 4992 insertions(+), 4106 deletions(-) create mode 100644 Distributions.h create mode 100644 GeneticLoad.cpp create mode 100644 GeneticLoad.h delete mode 100644 Genome.cpp delete mode 100644 Genome.h create mode 100644 Mutation.h create mode 100644 NeutralStatsManager.cpp create mode 100644 NeutralStatsManager.h create mode 100644 ProtoTrait.cpp create mode 100644 ProtoTrait.h create mode 100644 QTLTrait.cpp create mode 100644 QTLTrait.h delete mode 100644 RandomCheck.cpp delete mode 100644 RandomCheck.h create mode 100644 SNPTrait.cpp create mode 100644 SNPTrait.h create mode 100644 TTrait.h create mode 100644 TraitFactory.h diff --git a/Community.cpp b/Community.cpp index 222b97d..10cbcc0 100644 --- a/Community.cpp +++ b/Community.cpp @@ -30,12 +30,17 @@ ofstream outrange; ofstream outoccup, outsuit; ofstream outtraitsrows; +ofstream outwcfstat; +ofstream outperlocusfstat; +ofstream outpairwisefst; //--------------------------------------------------------------------------- Community::Community(Landscape* pLand) { pLandscape = pLand; indIx = 0; + pColdStorage = 0; + pNeutralStatistics = 0; } Community::~Community(void) { @@ -44,6 +49,7 @@ Community::~Community(void) { delete subComms[i]; } subComms.clear(); + delete pColdStorage; } SubCommunity* Community::addSubComm(Patch* pPch, int num) { @@ -68,6 +74,11 @@ void Community::initialise(Species* pSpecies, int year) landParams ppLand = pLandscape->getLandParams(); initParams init = paramsInit->getInit(); + if (pColdStorage != 0) + delete pColdStorage; + + pColdStorage = new Population(); + nsubcomms = (int)subComms.size(); spratio = ppLand.spResol / ppLand.resol; @@ -418,7 +429,44 @@ void Community::patchChanges(void) { } } -void Community::reproduction(int yr) +void Community::addIndividualsToColdStorage() { + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->copyIndividualsForColdStorage(pColdStorage); + } +} + +void Community::createAverageTraitIndividualAndStore(Species* pSpecies, Landscape* pLandscape) { + int nsubcomms = (int)subComms.size(); + int totalInds = 0; + Patch* pPatch = pLandscape->getPatchData(0).pPatch; + Cell* pCell = pPatch->getRandomCell(); + Individual* avgInd = new Individual(pCell, pPatch, 0, 0, 0, pSpecies->getDemogr().propMales, true, pSpecies->getTrfr().moveType); + + emigTraits avgEmigTraits = emigTraits(); + settleTraits avgSettleTraits = settleTraits(); + + + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + + totalInds += subComms[i]->addEmigrationAndSettlementTraitValues(avgEmigTraits, avgSettleTraits); + subComms[i]->addTransferDataForInd(avgInd->getTrfrData()); + + + } + //divide to get the mean + avgInd->getTrfrData()->divideTraitsBy(totalInds); + avgEmigTraits.divideTraitsBy(totalInds); + avgSettleTraits.divideTraitsBy(totalInds); + + avgInd->setEmigTraits(avgEmigTraits); + avgInd->setSettleTraits(avgSettleTraits); + + pColdStorage->recruit(avgInd); + +} + +void Community::reproduction(int yr, bool cloneFromColdStorage) { float eps = 0.0; // epsilon for environmental stochasticity landParams land = pLandscape->getLandParams(); @@ -435,7 +483,7 @@ void Community::reproduction(int yr) eps = pLandscape->getGlobalStoch(yr); } } - subComms[i]->reproduction(land.resol, eps, land.rasterType, land.patchModel); + subComms[i]->reproduction(land.resol, eps, land.rasterType, land.patchModel, cloneFromColdStorage, pColdStorage); } #if RSDEBUG DEBUGLOG << "Community::reproduction(): finished" << endl; @@ -688,23 +736,6 @@ void Community::outInds(int rep, int yr, int gen, int landNr) { } } -// Write records to genetics file -void Community::outGenetics(int rep, int yr, int gen, int landNr) { - //landParams ppLand = pLandscape->getLandParams(); - if (landNr >= 0) { // open the file - subComms[0]->outGenetics(rep, yr, gen, landNr); - return; - } - if (landNr == -999) { // close the file - subComms[0]->outGenetics(rep, yr, gen, landNr); - return; - } - // generate output for each sub-community (patch) in the community - int nsubcomms = (int)subComms.size(); - for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->outGenetics(rep, yr, gen, landNr); - } -} // Open range file and write header record bool Community::outRangeHeaders(Species* pSpecies, int landNr) @@ -737,15 +768,9 @@ bool Community::outRangeHeaders(Species* pSpecies, int landNr) if (sim.batchMode) { name = paramsSim->getDir(2) -#if RS_RCPP + "Batch" + Int2Str(sim.batchNum) + "_" + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) -#else - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" - + Int2Str(landNr) -#endif + "_Range.txt"; } else { @@ -1337,6 +1362,7 @@ void Community::outTraits(traitCanvas tcanv, Species* pSpecies, ts[y].sumS0[i] = ts[y].ssqS0[i] = 0.0; ts[y].sumAlphaS[i] = ts[y].ssqAlphaS[i] = 0.0; ts[y].sumBetaS[i] = ts[y].ssqBetaS[i] = 0.0; + ts[y].sumFitness[i] = ts[y].ssqFitness[i] = 0.0; } } } @@ -1367,6 +1393,7 @@ void Community::outTraits(traitCanvas tcanv, Species* pSpecies, ts[y].sumS0[s] += sctraits.sumS0[s]; ts[y].ssqS0[s] += sctraits.ssqS0[s]; ts[y].sumAlphaS[s] += sctraits.sumAlphaS[s]; ts[y].ssqAlphaS[s] += sctraits.ssqAlphaS[s]; ts[y].sumBetaS[s] += sctraits.sumBetaS[s]; ts[y].ssqBetaS[s] += sctraits.ssqBetaS[s]; + ts[y].sumFitness[s] += sctraits.sumFitness[s]; ts[y].ssqFitness[s] += sctraits.ssqFitness[s]; } } } @@ -1573,6 +1600,26 @@ void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int // } } + if (pSpecies->getNumberOfAdaptiveTraits() > 0) { + if (NSEXES > 1) { + if (ts.ninds[0] > 0) mn = ts.sumFitness[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqFitness[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (ts.ninds[1] > 0) mn = ts.sumFitness[1] / (double)ts.ninds[1]; else mn = 0.0; + if (ts.ninds[1] > 1) sd = ts.ssqFitness[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + } + else { + if (ts.ninds[0] > 0) mn = ts.sumFitness[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqFitness[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + } + } + + outtraitsrows << endl; } @@ -1663,6 +1710,15 @@ bool Community::outTraitsRowsHeaders(Species* pSpecies, int landNr) { outtraitsrows << "\tmeanBetaS\tstdBetaS"; // } } + + if (pSpecies->getNumberOfAdaptiveTraits() > 0) { + if (NSEXES > 1) { + outtraitsrows << "\tF_meanFitness\tF_stdFitness\tM_meanFitness\tM_stdFitness"; + } + else + outtraitsrows << "\tmeanFitness\tstdFitness"; + } + outtraitsrows << endl; return outtraitsrows.is_open(); @@ -1714,6 +1770,294 @@ Rcpp::IntegerMatrix Community::addYearToPopList(int rep, int yr) { // TODO: def } #endif +// ---------------------------------------------------------------------------------------- +// Sample individuals from sample patches +// ---------------------------------------------------------------------------------------- + + +void Community::sampleIndividuals(Species* pSpecies) { + + const set patchList = pSpecies->getSamplePatches(); + string n = pSpecies->getNIndsToSample(); + const set stages = pSpecies->getStagesToSample(); + + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + pPop->sampleIndsWithoutReplacement(n, stages); + } +} + +// ---------------------------------------------------------------------------------------- +// Open population level Fstat output file +// ---------------------------------------------------------------------------------------- + +bool Community::openWCFstatFile(Species* pSpecies, int landNr) +{ + + if (landNr == -999) { // close the file + if (outwcfstat.is_open()) outwcfstat.close(); + outwcfstat.clear(); + return true; + } + + string name; + simParams sim = paramsSim->getSim(); + + +#if RSDEBUG + DEBUGLOG << "Community::outNeutralGeneticHeaders(): simulation=" << sim.simulation + << " sim.batchMode=" << sim.batchMode + << " landNr=" << landNr << endl; +#endif + + if (sim.batchMode) { + name = paramsSim->getDir(2) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + "_Land" + + Int2Str(landNr) + + "_neutralGenetics.txt"; + } + else { + name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_neutralGenetics.txt"; + } + outwcfstat.open(name.c_str()); + outwcfstat << "Rep\tYear\tRepSeason\tnExtantPatches\tnIndividuals\tfst\tfis\tfit\tmeanAllelePerLocus\tmeanAllelePerLocusPatches\tmeanFixedLoci\tmeanFixedLociPatches\tmeanObHeterozygosity"; + + + outwcfstat << endl; + +#if RSDEBUG + DEBUGLOG << "Community::outwcfstat(): finished" << endl; +#endif + + return outwcfstat.is_open(); +} + +// ---------------------------------------------------------------------------------------- +// open per locus WC fstat using MS approach, this will output MS calculated FIS, FIT, FST +// in general population neutral genetics output file +// ---------------------------------------------------------------------------------------- + +bool Community::openWCPerLocusFstatFile(Species* pSpecies, Landscape* pLandscape, const int landNr, const int rep) +{ + + const set patchList = pSpecies->getSamplePatches(); + + if (landNr == -999) { // close the file + if (outperlocusfstat.is_open()) outperlocusfstat.close(); + outperlocusfstat.clear(); + return true; + } + + string name; + simParams sim = paramsSim->getSim(); + + +#if RSDEBUG + DEBUGLOG << "Community::outNeutralGeneticHeaders(): simulation=" << sim.simulation + << " sim.batchMode=" << sim.batchMode + << " landNr=" << landNr << endl; +#endif + + if (sim.batchMode) { + name = paramsSim->getDir(2) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + "_Land" + + Int2Str(landNr) + "_Rep" + + Int2Str(rep) + + "_perLocusNeutralGenetics.txt"; + } + else { + name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Rep" + Int2Str(rep) + "_perLocusNeutralGenetics.txt"; + } + outperlocusfstat.open(name.c_str()); + outperlocusfstat << "Year\tRepSeason\tlocus\tfst\tfis\tfit\tpopHet"; + + + + for (int patchId : patchList) { + outperlocusfstat << "\tpatch_" + Int2Str(patchId) + "_Het"; + } + + + outperlocusfstat << endl; + +#if RSDEBUG + DEBUGLOG << "Community::outperlocusfstat(): finished" << endl; +#endif + + return outperlocusfstat.is_open(); +} + +// ---------------------------------------------------------------------------------------- +// open pairwise fst file +// ---------------------------------------------------------------------------------------- + +bool Community::openPairwiseFSTFile(Species* pSpecies, Landscape* pLandscape, const int landNr, const int rep) { + + const set patchList = pSpecies->getSamplePatches(); + + if (landNr == -999) { // close the file + if (outpairwisefst.is_open()) outpairwisefst.close(); + outpairwisefst.clear(); + return true; + } + + string name; + simParams sim = paramsSim->getSim(); + + +#if RSDEBUG + DEBUGLOG << "Community::outNeutralGeneticHeaders(): simulation=" << sim.simulation + << " sim.batchMode=" << sim.batchMode + << " landNr=" << landNr << endl; +#endif + + if (sim.batchMode) { + name = paramsSim->getDir(2) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + "_Land" + + Int2Str(landNr) + "_Rep" + + Int2Str(rep) + + "_pairwisePatchNeutralGenetics.txt"; + } + else { + name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Rep" + Int2Str(rep) + "_pairwisePatchNeutralGenetics.txt"; + } + outpairwisefst.open(name.c_str()); + outpairwisefst << "Year\tRepSeason\tpatchA\tpatchB\tfst"; + + outpairwisefst << endl; + +#if RSDEBUG + DEBUGLOG << "Community::outpairwisefst(): finished" << endl; +#endif + + return outpairwisefst.is_open(); + + +} + +// ---------------------------------------------------------------------------------------- +// Write population level FST results file +// ---------------------------------------------------------------------------------------- + +void Community::writeWCFstatFile(int rep, int yr, int gen) { + + outwcfstat << rep << "\t" << yr << "\t" << gen << "\t"; + + outwcfstat << pNeutralStatistics->getNExtantPatchs() << "\t" << pNeutralStatistics->getNIndividuals() << "\t"; + + outwcfstat << pNeutralStatistics->getFstWC() << "\t" << pNeutralStatistics->getFisWC() << "\t" << pNeutralStatistics->getFitWC() << "\t"; + + outwcfstat << pNeutralStatistics->getNbAllGlobal() << "\t" << pNeutralStatistics->getNbAllLocal() << "\t" << pNeutralStatistics->getFixLocGlobal() + << "\t" << pNeutralStatistics->getFixLocLocal() << "\t" << pNeutralStatistics->getHo(); + + outwcfstat << endl; +} + +// ---------------------------------------------------------------------------------------- +// Write per locus FST results file +// ---------------------------------------------------------------------------------------- + +void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList) +{ + const set positions = pSpecies->getTrait(SNP)->getPositions(); + + int loci = 0; + for (int position : positions) { + + outperlocusfstat << yr << "\t" << gen << "\t" << position << "\t"; + outperlocusfstat << pNeutralStatistics->get_fst_WC_loc(loci) << "\t" << pNeutralStatistics->get_fis_WC_loc(loci) << + "\t" << pNeutralStatistics->get_fit_WC_loc(loci) << "\t" << pNeutralStatistics->get_ho_loc(loci); + + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + int popSize = pPop->sampleSize(); + int het = 0; + for (unsigned int a = 0; a < nAlleles; ++a) { + het += pPop->getHetero(loci, a); + } + outperlocusfstat << "\t" << het / (2.0 * popSize); + } + ++loci; + outperlocusfstat << endl; + } +} + + +// ---------------------------------------------------------------------------------------- +// Write pairwise FST results file +// ---------------------------------------------------------------------------------------- +void Community::writePairwiseFSTFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList) { + + //within patch fst (diagonal of matrix) + int i = 0; + for (int patchId : patchList) { + outpairwisefst << yr << "\t" << gen << "\t"; + outpairwisefst << patchId << "\t" << patchId << "\t" << pNeutralStatistics->getPairwiseFst(i, i) << endl; + ++i; + } + + // between patch fst + i = 0; + for (int patchIdA : patchList | std::views::take(patchList.size() - 1)) { + int j = i + 1; + for (int patchIdB : patchList | std::views::drop(j)) { + outpairwisefst << yr << "\t" << gen << "\t"; + outpairwisefst << patchIdA << "\t" << patchIdB << "\t" << pNeutralStatistics->getPairwiseFst(i, j) << endl; + ++j; + } + ++i; + } +} + + +// ---------------------------------------------------------------------------------------- +// Output and calculate neutral statistics +// ---------------------------------------------------------------------------------------- + + +void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool perLocus, bool pairwise) { + + const int nAlleles = (int)(pSpecies->getTrait(SNP)->getMutationParameters().find(MAX)->second); + const int nLoci = (int)pSpecies->getNPositionsForTrait(SNP); + const set patchList = pSpecies->getSamplePatches(); + int nInds = 0; + + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + nInds += pPop->sampleSize(); + } + + if (pNeutralStatistics == 0) + pNeutralStatistics = make_unique(patchList, nLoci); + + pNeutralStatistics->updateAlleleTables(pSpecies, pLandscape, patchList); + pNeutralStatistics->calculateHo(patchList, nInds, nLoci, pSpecies, pLandscape); + pNeutralStatistics->setLociDiversityCounter(patchList, nInds, pSpecies, pLandscape); + + if (perLocus) { + pNeutralStatistics->calculateFstatWC_MS(patchList, nInds, nLoci, nAlleles, pSpecies, pLandscape); + pNeutralStatistics->calculateHo2(patchList, nInds, nLoci, pSpecies, pLandscape); + writeWCPerLocusFstatFile(pSpecies, yr, gen, nAlleles, nLoci, patchList); + } + else { + pNeutralStatistics->calculateFstatWC(patchList, nInds, nLoci, nAlleles, pSpecies, pLandscape); + } + + if (pairwise) { + pNeutralStatistics->setFstMatrix(patchList, nInds, nLoci, pSpecies, pLandscape); + writePairwiseFSTFile(pSpecies, yr, gen, nAlleles, nLoci, patchList); + } + + // always write out the minimum stats + writeWCFstatFile(rep, yr, gen); +} + //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- diff --git a/Community.h b/Community.h index 6a07b5b..f8b35f3 100644 --- a/Community.h +++ b/Community.h @@ -1,74 +1,71 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ -RangeShifter v2.0 Community -Implements the Community class + /*------------------------------------------------------------------------------ -There is ONLY ONE instance of a Community in an individual replicate simulation. -It holds a SubCommunity for each Patch in the Landscape (including the matrix), -and is thus the highest-level entity accessed for most processing concerned with -simulated populations. + RangeShifter v2.0 Community -Optionally, the Community maintains a record of the occupancy of suitable cells -or patches during the course of simulation of multiple replicates. + Implements the Community class -For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. -and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. -Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 + There is ONLY ONE instance of a Community in an individual replicate simulation. + It holds a SubCommunity for each Patch in the Landscape (including the matrix), + and is thus the highest-level entity accessed for most processing concerned with + simulated populations. -Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + Optionally, the Community maintains a record of the occupancy of suitable cells + or patches during the course of simulation of multiple replicates. -Last updated: 25 June 2021 by Anne-Kathleen Malchow + For full details of RangeShifter, please see: + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. + and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial + eco-evolutionary dynamics and species’ responses to environmental changes. + Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 -------------------------------------------------------------------------------*/ + Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + + Last updated: 25 June 2021 by Anne-Kathleen Malchow + + ------------------------------------------------------------------------------*/ #ifndef CommunityH #define CommunityH #include #include +#include using namespace std; -//#if RS_RCPP && !R_CMD -#include "../Version.h" -//#endif -//#if !RS_RCPP && R_CMD -//#include "../../Batch/Version.h" -//#endif +#include "../Version.h" #include "SubCommunity.h" #include "Landscape.h" #include "Patch.h" #include "Cell.h" #include "Species.h" +#include "NeutralStatsManager.h" //--------------------------------------------------------------------------- struct commStats { -int ninds,nnonjuvs,suitable,occupied; -int minX,maxX,minY,maxY; + int ninds, nnonjuvs, suitable, occupied; + int minX, maxX, minY, maxY; }; class Community { @@ -76,18 +73,21 @@ class Community { public: Community(Landscape*); ~Community(void); - SubCommunity* addSubComm(Patch*,int); + SubCommunity* addSubComm(Patch*, int); // functions to manage populations occurring in the community void initialise( Species*, // pointer to Species int // year (relevent only for seedType == 2) ); void addManuallySelected(void); + void addIndividualsToColdStorage(void); + void createAverageTraitIndividualAndStore(Species* pSpecies, Landscape* pLandscape); void resetPopns(void); void localExtinction(int); void patchChanges(void); void reproduction( - int // year + int, // year + bool ); void emigration(void); #if RS_RCPP // included also SEASONAL @@ -103,10 +103,10 @@ class Community { void survival( short, // part: 0 = determine survival & development, - // 1 = apply survival changes to the population + // 1 = apply survival changes to the population short, // option0: 0 = stage 0 (juveniles) only ) - // 1 = all stages ) used by part 0 only - // 2 = stage 1 and above (all non-juvs) ) + // 1 = all stages ) used by part 0 only + // 2 = stage 1 and above (all non-juvs) ) short // option1: 0 - development only (when survival is annual) // 1 - development and survival ); @@ -156,13 +156,6 @@ class Community { int // Landscape number (>= 0 to open the file, -999 to close the file // -1 to write data records) ); - void outGenetics( // Write records to genetics file - int, // replicate - int, // year - int, // generation - int // Landscape number (>= 0 to open the file, -999 to close the file - // -1 to write data records) - ); // Open occupancy file, write header record and set up occupancy array bool outOccupancyHeaders( int // option: -999 to close the file @@ -172,7 +165,7 @@ class Community { bool // TRUE if occupancy graph is to be viewed on screen ); void viewOccSuit( // Update the occupancy graph on the screen - // NULL for the batch version + // NULL for the batch version int, // year double, // mean occupancy double // standard error of occupancy @@ -187,10 +180,10 @@ class Community { ); void outTraits( // Write records to traits file traitCanvas,// pointers to canvases for drawing variable traits -// emigCanvas, // pointers to canvases for drawing emigration traits -// trfrCanvas, // pointers to canvases for drawing emigration traits - // see SubCommunity.h - // in the batch version, these are replaced by integers set to zero + // emigCanvas, // pointers to canvases for drawing emigration traits + // trfrCanvas, // pointers to canvases for drawing emigration traits + // see SubCommunity.h + // in the batch version, these are replaced by integers set to zero Species*, // pointer to Species int, // replicate int, // year @@ -205,26 +198,46 @@ class Community { traitsums // structure holding sums of trait genes for dispersal (see Population.h) ); void draw( // Draw the Community on the landscape map and optionally save the map - // NULL for the batch version + // NULL for the batch version int, // replicate int, // year int, // generation int // Landscape number ); #if RS_RCPP && !R_CMD - Rcpp::IntegerMatrix addYearToPopList(int,int); + Rcpp::IntegerMatrix addYearToPopList(int, int); #endif + //sample individuals for genetics (or could be used for anything) + void sampleIndividuals(Species* pSpecies); + + //control neutral stat output + void outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool perLocus, bool pairwise); + + //file openers + bool openWCFstatFile(Species* pSpecies, const int landNr); + bool openWCPerLocusFstatFile(Species* pSpecies, Landscape* pLandscape, const int landNr, const int rep); + bool openPairwiseFSTFile(Species* pSpecies, Landscape* pLandscape, const int landNr, const int rep); + + //file writers + void writeWCFstatFile(int rep, int yr, int gen); + void writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList); + void writePairwiseFSTFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList); + + private: - Landscape *pLandscape; + Landscape* pLandscape; int indIx; // index used to apply initial individuals - float **occSuit; // occupancy of suitable cells / patches + float** occSuit; // occupancy of suitable cells / patches std::vector subComms; + //below won't work for multispecies + Population* pColdStorage; + unique_ptr pNeutralStatistics; }; -extern paramSim *paramsSim; -extern paramInit *paramsInit; +extern paramSim* paramsSim; +extern paramInit* paramsInit; //--------------------------------------------------------------------------- diff --git a/Distributions.h b/Distributions.h new file mode 100644 index 0000000..ef4e1cb --- /dev/null +++ b/Distributions.h @@ -0,0 +1,70 @@ +#ifndef DISTRIBUTIONSH +#define DISTRIBUTIONSH + + +#include +#include +//#include +using namespace std; + +#include +#include +#if !LINUX_CLUSTER +#include +#endif + +#include "RSRandom.h" + +struct distributionType { + + virtual ~distributionType() {} + +}; + +struct NormalDistribution : distributionType { + + // Set up standard normal distribution + std::normal_distribution<>* pNormal; + + NormalDistribution(float mean, float sd) { + pNormal = new normal_distribution(mean, sd); + } + + float sample(void) { + + + mt19937 gen = pRandom->getRNG(); + return pNormal->operator()(gen); + } + + ~NormalDistribution() { + if (pNormal != 0) delete pNormal; + } +}; + +struct NormalDistribution : distributionType { + + // Set up standard normal distribution + std::normal_distribution<>* pNormal; + + NormalDistribution(float mean, float sd) { + pNormal = new normal_distribution(mean, sd); + } + + float sample(void) { + + + mt19937 gen = pRandom->getRNG(); + return pNormal->operator()(gen); + } + + ~NormalDistribution() { + if (pNormal != 0) delete pNormal; + } +}; + + + +extern RSrandom* pRandom; + +#endif \ No newline at end of file diff --git a/FractalGenerator.cpp b/FractalGenerator.cpp index e423059..9dda608 100644 --- a/FractalGenerator.cpp +++ b/FractalGenerator.cpp @@ -39,12 +39,6 @@ bool compare(const land& z, const land& zz) //compares only the values of the ce vector& fractal_landscape(int X, int Y, double Hurst, double prop, double maxValue, double minValue) { -#if RSDEBUG - DEBUGLOG << "fractal_landscape(): X=" << X << " Y=" << Y - << " Hurst=" << Hurst << " prop=" << prop - << " maxValue=" << maxValue << " minValue=" << minValue - << endl; -#endif int ii, jj, x, y; int ix, iy; diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp new file mode 100644 index 0000000..6699a69 --- /dev/null +++ b/GeneticLoad.cpp @@ -0,0 +1,440 @@ +#include "GeneticLoad.h" + +// ---------------------------------------------------------------------------------------- +// for initialising population +// ---------------------------------------------------------------------------------------- + +GeneticLoad::GeneticLoad(ProtoTrait* P) +{ + + pProtoTrait = P; + + if (wildType.get() == nullptr) + wildType = make_shared(0.0, 0.0); + + ExpressionType expressionType = pProtoTrait->getExpressionType(); + + _inherit_func_ptr = (pProtoTrait->getPloidy() == 1) ? &GeneticLoad::inheritHaploid : &GeneticLoad::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance + + DistributionType mutationDistribution = pProtoTrait->getMutationDistribution(); + map mutationParameters = pProtoTrait->getMutationParameters(); + + switch (mutationDistribution) { + case UNIFORM: + { + if (!mutationParameters.count(MAX)) + cout << endl << ("Error:: adaptive mutation uniform distribution parameter must contain max value (e.g. max= ) \n"); + + if (!mutationParameters.count(MIN)) + cout << endl << ("Error:: adaptive mutation uniform distribution parameter must contain min value (e.g. min= ) \n"); + + break; + } + case NORMAL: + { + + if (!mutationParameters.count(MEAN)) + cout << endl << ("Error:: adaptive mutation distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); + + if (!mutationParameters.count(SDEV)) + cout << endl << ("Error:: adaptive mutation distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); + + break; + } + case GAMMA: + { + if (!mutationParameters.count(SHAPE)) + cout << endl << ("Error:: adaptive mutation distribution set to gamma so parameters must contain shape value (e.g. shape= ) \n"); + + if (!mutationParameters.count(SCALE)) + cout << endl << ("Error:: adaptive mutation distribution set to gamma so parameters must contain scale value (e.g. scale= ) \n"); + + break; + } + case NEGEXP: + { + if (!mutationParameters.count(MEAN)) + cout << endl << ("Error:: adaptive mutation distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); + + + break; + } + + default: + { + cout << endl << ("Error:: wrong parameter value for adaptive mutation model, must be uniform/normal/gamma/negExp \n"); + } + } + + DistributionType dominanceDistribution = pProtoTrait->getDominanceDistribution(); + map dominanceParameters = pProtoTrait->getDominanceParameters(); + + switch (dominanceDistribution) { + case UNIFORM: + { + if (!dominanceParameters.count(MAX)) + cout << endl << ("Error:: adaptive dominance uniform distribution parameter must contain max value (e.g. max= ) \n"); + + if (!dominanceParameters.count(MIN)) + cout << endl << ("Error:: adaptive dominance uniform distribution parameter must contain min value (e.g. min= ) \n"); + + break; + } + case NORMAL: + { + + if (!dominanceParameters.count(MEAN)) + cout << endl << ("Error:: adaptive dominance distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); + + if (!dominanceParameters.count(SDEV)) + cout << endl << ("Error:: adaptive dominance distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); + + break; + } + case GAMMA: + { + if (!dominanceParameters.count(SHAPE)) + cout << endl << ("Error:: adaptive dominance distribution set to gamma so parameters must contain shape value (e.g. shape= ) \n"); + + if (!dominanceParameters.count(SCALE)) + cout << endl << ("Error:: adaptive dominance distribution set to gamma so parameters must contain scale value (e.g. scale= ) \n"); + + break; + } + case NEGEXP: + { + if (!dominanceParameters.count(MEAN)) + cout << endl << ("Error:: adaptive dominance distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); + + break; + } + case SCALED: + { + break; + } + + default: + { + cout << endl << ("Error:: wrong parameter value for adaptive dominance model, must be uniform/normal/gamma/negExp/scaled \n"); + break; //should return false + } + } + + DistributionType initialDistribution = pProtoTrait->getInitialDistribution(); + map initialParameters = pProtoTrait->getInitialParameters(); + + //switch (expressionType) { + //case MULTIPLICATIVE: + //{ + // _express_func_ptr = &AdaptiveTrait::expressMulti; + // break; + //} + //default: + //{ + // cout << endl << ("wrong parameter value for parameter \"expression of adaptive mutations\", must be multiplicative \n"); + // break; //should return false + //} + + //} + +} + + +// ---------------------------------------------------------------------------------------- +// for creating new individuals +// ---------------------------------------------------------------------------------------- + +GeneticLoad::GeneticLoad(const GeneticLoad& T) : pProtoTrait(T.pProtoTrait), _inherit_func_ptr(T._inherit_func_ptr) +{} + +// ---------------------------------------------------------------------------------------- +// mutate uniform +// ---------------------------------------------------------------------------------------- +void GeneticLoad::mutate() +{ + const int positionsSize = pProtoTrait->getPositionsSize(); + const auto& positions = pProtoTrait->getPositions(); + const short ploidy = pProtoTrait->getPloidy(); + const float mutationRate = pProtoTrait->getMutationRate(); + + auto rng = pRandom->getRNG(); + + for (int p = 0; p < ploidy; p++) { + + // Determine nb of mutations + unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); + + if (NbMut > 0) { + vector mutationPositions; + // Draw which positions mutate + sample(positions.begin(), positions.end(), std::back_inserter(mutationPositions), + NbMut, rng); + + for (int m : mutationPositions) { + + float newSelectionCoef = drawSelectionCoef(); + float newDominanceCoef = drawDominance(newSelectionCoef); + + auto it = mutations.find(m); //find if position in map already has mutations there + + if (it == mutations.end()) { // not found so create new entry in map with wildtype as char default + vector> newAllelePair(2); + newAllelePair[p] = make_shared(newSelectionCoef, newDominanceCoef); //put new mutation value in + mutations.insert(make_pair(m, newAllelePair)); + } + else { //position found, already mutations there + it->second[p] = make_shared(newSelectionCoef, newDominanceCoef); + } + } + } + } +} +// ---------------------------------------------------------------------------------------- +// get dominance value for new mutation +// ---------------------------------------------------------------------------------------- + + +float GeneticLoad::drawDominance(float selCoef) { + + DistributionType dominanceDistribution = pProtoTrait->getDominanceDistribution(); + map dominanceParameters = pProtoTrait->getDominanceParameters(); + + float h = 1.0; //default dominance is 1 + + switch (dominanceDistribution) { + case UNIFORM: + { + float maxD = dominanceParameters.find(MAX)->second; + float minD = dominanceParameters.find(MIN)->second; + h = pRandom->FRandom(minD, maxD); + break; + } + case NORMAL: + { + const float mean = dominanceParameters.find(MEAN)->second; + const float sd = dominanceParameters.find(SDEV)->second; + h = pRandom->Normal(mean, sd); + break; + } + case GAMMA: + { + const float shape = dominanceParameters.find(SHAPE)->second; + const float scale = dominanceParameters.find(SCALE)->second; + h = pRandom->Gamma(shape, scale); + break; + } + case NEGEXP: + { + const float mean = dominanceParameters.find(MEAN)->second; + h = pRandom->NegExp(mean); + break; + } + case SCALED: + { + const float min = 0; + const float max = exp((-log(2 * 0.36) / 0.05) * selCoef); + h = pRandom->FRandom(min, max); + break; + } + + default: + { + cout << endl << ("Error:: wrong parameter value for adaptive dominance model, must be uniform/normal/gamma/negExp/scaled \n"); + break; //should return false + } + } + + return h; +} + +// ---------------------------------------------------------------------------------------- +// get selection coefficient for new mutation +// ---------------------------------------------------------------------------------------- + + +float GeneticLoad::drawSelectionCoef() { + + DistributionType mutationDistribution = pProtoTrait->getMutationDistribution(); + map mutationParameters = pProtoTrait->getMutationParameters(); + + float s = 0.0; //default selection coefficient is 0 + + switch (mutationDistribution) { + case UNIFORM: + { + float maxD = mutationParameters.find(MAX)->second; + float minD = mutationParameters.find(MIN)->second; + s = pRandom->FRandom(minD, maxD); + + break; + } + case NORMAL: + { + const float mean = mutationParameters.find(MEAN)->second; + const float sd = mutationParameters.find(SDEV)->second; + s = pRandom->Normal(mean, sd); + + break; + } + case GAMMA: + { + const float shape = mutationParameters.find(SHAPE)->second; + const float scale = mutationParameters.find(SCALE)->second; + s = pRandom->Gamma(shape, scale); + break; + } + case NEGEXP: + { + const float mean = mutationParameters.find(MEAN)->second; + s = pRandom->NegExp(mean); + break; + } + default: + { + cout << endl << ("Error:: wrong parameter value for adaptive mutation model, must be uniform/normal/gamma/negExp/scaled \n"); + break; //should return false + } + } + return s; +} + + +// ---------------------------------------------------------------------------------------- +// inheritance options +// ---------------------------------------------------------------------------------------- + + +void GeneticLoad::inherit(TTrait* parent, set const& recomPositions, sex_t whichChromosome, int startingChromosome) +{ + + auto parentCast = dynamic_cast (parent); //horrible + + const auto& parent_seq = parentCast->get_mutations(); + if (parent_seq.size() > 0) //else nothing to inherit + (this->*_inherit_func_ptr) (whichChromosome, parent_seq, recomPositions, startingChromosome); + + +} + +void GeneticLoad::inheritDiploid(sex_t whichChromosome, map>> const& parentMutations, set const& recomPositions, int parentChromosome) { + + auto it = recomPositions.lower_bound(parentMutations.begin()->first); + + unsigned int nextBreakpoint = *it; + + auto distance = std::distance(recomPositions.begin(), it); + if (distance % 2 != 0) + parentChromosome = !parentChromosome; // switch to the other one + // use 1-parentChromosome, or switch to a sex_t ? + + for (auto const& [locus, allelePair] : parentMutations) { + + while (locus > nextBreakpoint) { + std::advance(it, 1); + nextBreakpoint = *it; + parentChromosome = !parentChromosome; // switch to the other one + } + + if (locus <= nextBreakpoint) { + auto& allele = allelePair[parentChromosome]; + auto it = mutations.find(locus); + if (it == mutations.end()) { + // locus does not exist yet, initiate it + vector> newAllelePair(2); + newAllelePair[whichChromosome] = allele; + mutations.insert(make_pair(locus, newAllelePair)); + } + else { + // locus already exists + // presumably bc already inherited from other parent + // set corresponding allele + it->second[whichChromosome] = allele; + } + } + } +} + +void GeneticLoad::inheritHaploid(sex_t chromosome, map>> const& parentMutations, set const& recomPositions, int parentChromosome) +{ + mutations = parentMutations; +} + +// ---------------------------------------------------------------------------------------- +// expression options +// ---------------------------------------------------------------------------------------- + +float GeneticLoad::express() { + + float phenotype = 1.0; + + for (auto const& [locus, pAllelePair] : mutations) + { + auto pAlleleLeft = (!pAllelePair[0]) ? wildType : pAllelePair[0]; + auto pAlleleRight = (!pAllelePair[1]) ? wildType : pAllelePair[1]; + + if (pAlleleLeft.get()->getId() != pAlleleRight.get()->getId()) // heterozygote + { + phenotype *= 1 + pAlleleLeft->getSelectionCoef() * pAlleleLeft->getDominanceCoef(); + phenotype *= 1 + pAlleleRight->getSelectionCoef() * pAlleleRight->getDominanceCoef(); + } + else { // homozygote + phenotype *= 1 + pAlleleLeft->getSelectionCoef(); + phenotype *= 1 + pAlleleRight->getSelectionCoef(); + } + } + return phenotype; +} + +// ---------------------------------------------------------------------------------------- +// check if particular loci is heterozygote +// ---------------------------------------------------------------------------------------- + + +bool GeneticLoad::isHeterozygoteAtLoci(int loci) const { + + auto it = mutations.find(loci); + + if (it == mutations.end()) //not found so must be wildtype homozygous + return false; + else { + auto a = (!it->second[0]) ? wildType : it->second[0]; + auto b = (!it->second[1]) ? wildType : it->second[1]; + return a != b; + + } +} + +// ---------------------------------------------------------------------------------------- +// count heterozygote loci in genome +// ---------------------------------------------------------------------------------------- + + +int GeneticLoad::countHeterozygoteLoci() const { + + int count = 0; + + for (auto const& [key, val] : mutations) { + + auto a = (!val[0]) ? wildType : val[0]; + auto b = (!val[1]) ? wildType : val[1]; + count += a != b; + } + + return count; +} + +// ---------------------------------------------------------------------------------------- +// get allele value at loci +// ---------------------------------------------------------------------------------------- + + +float GeneticLoad::getSelectionCoefAtLoci(short chromosome, int position) const { + + auto it = mutations.find(position); + + if (it == mutations.end()) { + return wildType->getSelectionCoef(); //must still be wildtype at loci + } + else + return (!it->second[chromosome]) ? wildType->getSelectionCoef() : it->second[chromosome]->getSelectionCoef(); +} \ No newline at end of file diff --git a/GeneticLoad.h b/GeneticLoad.h new file mode 100644 index 0000000..c55b246 --- /dev/null +++ b/GeneticLoad.h @@ -0,0 +1,64 @@ +#ifndef GENETICLOADH +#define GENETICLOADH + +#include +#include + +#include "TTrait.h" + +using namespace std; + +class GeneticLoad : public TTrait { + +private: + + ProtoTrait* pProtoTrait; + + map>> mutations; // position > + + inline static shared_ptr wildType; + + // void (AdaptiveTrait::* _mutate_func_ptr) (void); + void (GeneticLoad::* _inherit_func_ptr) (sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); + //float (AdaptiveTrait::* _express_func_ptr) (void); + + void inheritDiploid(sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); + void inheritHaploid(sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); + + float drawDominance(float); + float drawSelectionCoef(); + +public: + + //this one for species held trait table, e.g. prototype table, sets static members + + GeneticLoad(ProtoTrait* P); + + //this one for individuals, static members are not reset + GeneticLoad(const GeneticLoad& T); + + virtual unique_ptr clone() const override { return std::make_unique(*this); } + + virtual void inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) override; + + virtual void mutate() override; + + virtual int getNLoci() const override { return pProtoTrait->getPositionsSize(); } + + float getMutationRate() const override { return pProtoTrait->getMutationRate(); } + + bool isInherited() const override { return pProtoTrait->isInherited(); } + + map>>& get_mutations() { return mutations; } //returning reference, reciever must be const + + virtual float getSelectionCoefAtLoci(short chromosome, int position) const override; + + virtual int countHeterozygoteLoci() const; + + virtual bool isHeterozygoteAtLoci(int loci) const override; + + virtual float express(); + + virtual ~GeneticLoad() { } +}; +#endif // GENETICLOADH diff --git a/Genome.cpp b/Genome.cpp deleted file mode 100644 index f19933f..0000000 --- a/Genome.cpp +++ /dev/null @@ -1,861 +0,0 @@ -/*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * - * This file is part of RangeShifter. - * - * RangeShifter 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 3 of the License, or - * (at your option) any later version. - * - * RangeShifter is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RangeShifter. If not, see . - * - --------------------------------------------------------------------------*/ - - - //--------------------------------------------------------------------------- - -#include "Genome.h" -//--------------------------------------------------------------------------- - -ofstream outGenetic; - -//--------------------------------------------------------------------------- - -#ifdef RSDEBUG -//std::ofstream chromdebug("chromdebug.txt"); -//std::ofstream chromdebug1("chromdebug1.txt"); -#endif - -//--------------------------------------------------------------------------- - -Chromosome::Chromosome(int nloc) -{ -#if RSDEBUG - //DEBUGLOG << "Chromosome::Chromosome(): this=" << this - // << " nloc=" << nloc - //// << " maternalLoci.size()=" << maternalLoci.size() - //// << " paternalLoci.size()=" << paternalLoci.size() - // << endl; - //DebugGUI("Chromosome::Chromosome(): this=" + Int2Str((int)this) - // + " nloc=" + Int2Str(nloc) - //// + " maternalLoci.size()=" + Int2Str((int)maternalLoci.size()) - //// + " paternalLoci.size()=" + Int2Str((int)paternalLoci.size()) - // ); -#endif - if (nloc > 0) nloci = nloc; else nloci = 1; - pLoci = new locus[nloci]; - for (int i = 0; i < nloci; i++) { - pLoci[i].allele[0] = pLoci[i].allele[1] = 0; - } -} - -Chromosome::~Chromosome() { -#if RSDEBUG - //DEBUGLOG << "Chromosome::~Chromosome(): this=" << this << endl; -#endif -#if RSDEBUG -//DEBUGLOG << "Chromosome::Chromosome(): deleting this=" << this << endl; -//DebugGUI("Chromosome::Chromosome(): deleting this=" + Int2Str((int)this)); -#endif - if (pLoci != 0) { - // for (int i = 0; i < nloci; i++) { - // delete pLoci[i]; pLoci[i] = NULL; - // } - delete[] pLoci; pLoci = NULL; - } -} - -short Chromosome::nLoci(void) { return nloci; } - -locus Chromosome::alleles(const int loc) { // return allele values at a specified locus - locus l; l.allele[0] = l.allele[1] = 0; - if (loc >= 0 && loc < nloci) { - l.allele[0] = pLoci[loc].allele[0]; l.allele[1] = pLoci[loc].allele[1]; - } - return l; -} - -double Chromosome::additive(const bool diploid) { - int sum = 0; - for (int i = 0; i < nloci; i++) { - sum += pLoci[i].allele[0]; - if (diploid) sum += pLoci[i].allele[1]; - } -#if RSDEBUG - //DEBUGLOG << "Chromosome::additive(): this=" << this - // << " sum=" << sum - // << endl; -#endif - return (double)sum / INTBASE; -} - -double Chromosome::meanvalue(const bool diploid) { - int sum = 0; - double mean; - for (int i = 0; i < nloci; i++) { - sum += pLoci[i].allele[0]; - if (diploid) sum += pLoci[i].allele[1]; - } - mean = (double)sum / (double)nloci; - if (diploid) mean /= 2.0; - mean /= INTBASE; -#if RSDEBUG - //DEBUGLOG << "Chromosome::meanvalue(): this=" << this - // << " sum=" << sum - // << " mean=" << mean - // << endl; -#endif - return mean; -} - -double Chromosome::additive(const short loc, const bool diploid) { - int sum = 0; - sum += pLoci[loc].allele[0]; - if (diploid) sum += pLoci[loc].allele[1]; -#if RSDEBUG - //DEBUGLOG << "Chromosome::additive(): this=" << this - // << " sum=" << sum - // << endl; -#endif - return (double)sum / INTBASE; -} - -/* -double Chromosome::probval(const bool diploid) { -double genval,phenval; -int sum = 0; -for (int i = 0; i < nloci; i++) { - sum += pLoci[i].allele[0]; - if (diploid) sum += pLoci[i].allele[1]; -} -genval = (double)sum / INTBASE; -phenval = 1.0 / (1.0 + exp(-genval)); -#if RSDEBUG -//DEBUGLOG << "Chromosome::probval(): this=" << this -// << " sum=" << sum -// << " genval=" << genval -// << " phenval=" << phenval -// << endl; -#endif -return phenval; -} -*/ - -// Set up chromosome at simulation initialisation -//void Chromosome::initialise(const float mean,const float sd, -// const bool diploid) { -void Chromosome::initialise(const double mean, const double sd, - const bool diploid) { - double avalue; - double intbase = INTBASE; - //// adjust mean and s.d. allowing for number of alleles determining phenotype - //double adjmean,adjsd,factor; - //if (diploid) factor = (double)(nloci * 2); else factor = (double)(nloci); - //adjmean = mean / factor; - //adjsd = sqrt(sd * sd / factor); - for (int i = 0; i < nloci; i++) { - // avalue = pRandom->Normal(adjmean,adjsd); - avalue = pRandom->Normal(mean, sd); - if (avalue > 0.0) - pLoci[i].allele[0] = (int)(avalue * intbase + 0.5); - else - pLoci[i].allele[0] = (int)(avalue * intbase - 0.5); -#if RSDEBUG - //DEBUGLOG << "Chromosome::initialise(): this=" << this - // << " mean=" << mean << " sd=" << sd - // << " i=" << i << " avalue=" << avalue - // << " allele[0]=" << pLoci[i].allele[0]; - //DEBUGLOG << endl; -#endif - if (diploid) { - // avalue = pRandom->Normal(adjmean,adjsd); - avalue = pRandom->Normal(mean, sd); - if (avalue > 0.0) - pLoci[i].allele[1] = (int)(avalue * intbase + 0.5); - else - pLoci[i].allele[1] = (int)(avalue * intbase - 0.5); -#if RSDEBUG - //DEBUGLOG << "Chromosome::initialise(): this=" << this - // << " mean=" << mean << " sd=" << sd - // << " i=" << i << " avalue=" << avalue - // << " allele[1]=" << pLoci[i].allele[1]; - //DEBUGLOG << endl; -#endif - } - } - -} - -// Set up specified locus at simulation initialisation -void Chromosome::initialise(const short locus, const short posn, const int aval) -{ - // note that initialising value is ADDED to current value to allow for pleiotropy - pLoci[locus].allele[posn] += aval; -} - -// Inherit from specified parent -void Chromosome::inherit(const Chromosome* parentChr, const short posn, const short nloc, - const double probmutn, const double probcross, const double mutnSD, const bool diploid) -{ - - // NOTE: At present for diploid genome, presence of crossover is determined at each - // locus (except first). However, Roslyn has shown that it is more efficient to sample - // crossover locations from geometric distribution if number of loci is large. - // HOW LARGE IS 'LARGE' IN THIS CASE?... - - //// adjust mutation variance for number of loci - //double mutnsd; - //if (diploid) - // mutnsd = sqrt(mutnSD * mutnSD / (double)(2*nloc)); - //else - // mutnsd = sqrt(mutnSD * mutnSD / (double)nloc); - int ix = 0; // indexes maternal and paternal strands - if (diploid) ix = pRandom->Bernoulli(0.5); // start index at random - for (int i = 0; i < nloc; i++) { - if (diploid) { - pLoci[i].allele[posn] = parentChr->pLoci[i].allele[ix]; - if (pRandom->Bernoulli(probcross)) { // crossover occurs - if (ix == 0) ix = 1; else ix = 0; - } - } - else - pLoci[i].allele[posn] = parentChr->pLoci[i].allele[0]; -#if RSDEBUG - //DEBUGLOG << "Chromosome::inherit(): this=" << this - // << " posn=" << posn << " nloc=" << nloc << " pmutn=" << pmutn - // << " i=" << i << " allele=" << pLoci[i].allele[posn] - // << endl; -#endif - if (pRandom->Bernoulli(probmutn)) { // mutation occurs - double intbase = INTBASE; -#if RSDEBUG - int oldval = pLoci[i].allele[posn]; -#endif - // double mutnvalue = pRandom->Normal(0,mutnsd); - double mutnvalue = pRandom->Normal(0, mutnSD); - if (mutnvalue > 0.0) - pLoci[i].allele[posn] += (int)(intbase * mutnvalue + 0.5); - else - pLoci[i].allele[posn] += (int)(intbase * mutnvalue - 0.5); -#if RSDEBUG - //DEBUGLOG << "Chromosome::inherit(): this=" << this - // << " probmutn=" << probmutn << " nloc=" << nloc - //// << " mutnsd=" << mutnsd - // << " mutnSD=" << mutnSD - // << " posn=" << posn << " locus=" << i << " MUTATED " - // << " old=" << oldval << " new=" << pLoci[i].allele[posn] - // << endl; -#endif -#if RSDEBUG -//MUTNLOG << 1 << endl; - MUTNLOG << mutnvalue << " " << oldval << " " << pLoci[i].allele[posn] << " " << endl; -#endif - } -#if RSDEBUG - // else { - //MUTNLOG << 0 << endl; - // } -#endif - } -} - - -//--------------------------------------------------------------------------- - -// NB THIS FUNCTION IS CURRENTLY NOT BEING CALLED TO CONSTRUCT AN INSTANCE OF Genome -// Genome(int) IS USED INSTEAD - -Genome::Genome() { - pChromosome = NULL; - nChromosomes = 0; -} - -// Set up new genome at initialisation for 1 chromosome per trait -Genome::Genome(int nchromosomes, int nloci, bool d) { -#if RSDEBUG - //DEBUGLOG << "Genome::Genome(): this=" << this - // << " nchromosomes=" << nchromosomes << " nLoci=" << nLoci - // << endl; -#endif - - diploid = d; - if (nchromosomes > 0) nChromosomes = nchromosomes; else nChromosomes = 1; - pChromosome = new Chromosome * [nChromosomes]; - for (int i = 0; i < nChromosomes; i++) { - pChromosome[i] = new Chromosome(nloci); - // pChromosome[i]->initialise(alleleMean,alleleSD); - } - -} - -// Set up new genome at initialisation for trait mapping -Genome::Genome(Species* pSpecies) { - int nloci; - nChromosomes = pSpecies->getNChromosomes(); - diploid = pSpecies->isDiploid(); -#if RSDEBUG - //DEBUGLOG << "Genome::Genome(): this=" << this - // << " nChromosomes=" << nChromosomes - // << endl; -#endif - pChromosome = new Chromosome * [nChromosomes]; - for (int i = 0; i < nChromosomes; i++) { - nloci = pSpecies->getNLoci(i); -#if RSDEBUG - //DEBUGLOG << "Genome::Genome(): this=" << this - // << " i=" << i << " nloci=" << nloci << endl; -#endif - pChromosome[i] = new Chromosome(nloci); - } -} - -// Inherit genome from parent(s) -Genome::Genome(Species* pSpecies, Genome* mother, Genome* father) -{ - genomeData gen = pSpecies->getGenomeData(); - - nChromosomes = mother->nChromosomes; - diploid = mother->diploid; - pChromosome = new Chromosome * [nChromosomes]; - - for (int i = 0; i < nChromosomes; i++) { - pChromosome[i] = new Chromosome(mother->pChromosome[i]->nLoci()); - inherit(mother, 0, i, gen.probMutn, gen.probCrossover, gen.mutationSD); - if (diploid) { - if (father == 0) { // species is hermaphrodite - inherit again from mother - inherit(mother, 1, i, gen.probMutn, gen.probCrossover, gen.mutationSD); - } - else inherit(father, 1, i, gen.probMutn, gen.probCrossover, gen.mutationSD); - } - } - -} - -Genome::~Genome() { - - if (pChromosome == NULL) return; - - for (int i = 0; i < nChromosomes; i++) { - delete pChromosome[i]; - } - delete[] pChromosome; - -} - -/* -Genome::~Genome(void) -{ -if (genome != 0) { - delete genome; genome = NULL; -} -} -*/ - -//--------------------------------------------------------------------------- - -void Genome::setDiploid(bool dip) { diploid = dip; } -bool Genome::isDiploid(void) { return diploid; } -short Genome::getNChromosomes(void) { return nChromosomes; } - -//--------------------------------------------------------------------------- - -// Inherit from specified parent -void Genome::inherit(const Genome* parent, const short posn, const short chr, - const double probmutn, const double probcross, const double mutnSD) -{ - // adjust mutation variance for number of loci - //double mutnSD = sqrt(mutationSD * mutationSD / (double)nLoci); - //for (int i = 0; i < nChromosomes; i++) { - // pChromosome[i]->inherit(parent->pChromosome[i],pChromosome[i]->nLoci()); - //} - pChromosome[chr]->inherit(parent->pChromosome[chr], posn, parent->pChromosome[chr]->nLoci(), - probmutn, probcross, mutnSD, diploid); - -} - -void Genome::outGenHeaders(const int rep, const int landNr, const bool xtab) -{ - - if (landNr == -999) { // close file - if (outGenetic.is_open()) { - outGenetic.close(); outGenetic.clear(); - } - return; - } - - string name; - simParams sim = paramsSim->getSim(); - - if (sim.batchMode) { - name = paramsSim->getDir(2) - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) - + "_Land" + Int2Str(landNr) + "_Rep" + Int2Str(rep) + "_Genetics.txt"; - } - else { - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) - + "_Rep" + Int2Str(rep) + "_Genetics.txt"; - } - outGenetic.open(name.c_str()); - - outGenetic << "Rep\tYear\tSpecies\tIndID"; - if (xtab) { - for (int i = 0; i < nChromosomes; i++) { - int nloci = pChromosome[i]->nLoci(); - for (int j = 0; j < nloci; j++) { - outGenetic << "\tChr" << i << "Loc" << j << "Allele0"; - if (diploid) outGenetic << "\tChr" << i << "Loc" << j << "Allele1"; - } - } - outGenetic << endl; - } - else { - outGenetic << "\tChromosome\tLocus\tAllele0"; - if (diploid) outGenetic << "\tAllele1"; - outGenetic << endl; - } - -} - -void Genome::outGenetics(const int rep, const int year, const int spnum, - const int indID, const bool xtab) -{ - locus l; - if (xtab) { - outGenetic << rep << "\t" << year << "\t" << spnum << "\t" << indID; - for (int i = 0; i < nChromosomes; i++) { - int nloci = pChromosome[i]->nLoci(); - for (int j = 0; j < nloci; j++) { - l = pChromosome[i]->alleles(j); - outGenetic << "\t" << l.allele[0]; - if (diploid) outGenetic << "\t" << l.allele[1]; - } - } - outGenetic << endl; - } - else { - for (int i = 0; i < nChromosomes; i++) { - int nloci = pChromosome[i]->nLoci(); - for (int j = 0; j < nloci; j++) { - outGenetic << rep << "\t" << year << "\t" << spnum << "\t" - << indID << "\t" << i << "\t" << j; - l = pChromosome[i]->alleles(j); - outGenetic << "\t" << l.allele[0]; - if (diploid) outGenetic << "\t" << l.allele[1]; - outGenetic << endl; - } - } - } -} - -//--------------------------------------------------------------------------- - -// Set up new gene at initialisation for 1 chromosome per trait -//void Genome::setGene(const short chr,const short exp, -// const float traitval,const float alleleSD) -void Genome::setGene(const short chr, const short exp, - const double traitval, const double alleleSD) - // NB PARAMETER exp FOR EXPRESSION TYPE IS NOT CURRENTLY USED... -{ -#if RSDEBUG - //DEBUGLOG << "Genome::setGene(): this=" << this - // << " chr=" << chr - // << " exp=" << exp << " traitval=" << traitval - // << " alleleSD=" << alleleSD - // << endl; -#endif - if (chr >= 0 && chr < nChromosomes) { - pChromosome[chr]->initialise(traitval, alleleSD, diploid); - } -} - -// Set up trait at initialisation for trait mapping -//void Genome::setTrait(Species *pSpecies,const int trait, -// const float traitval,const float alleleSD) -void Genome::setTrait(Species* pSpecies, const int trait, - const double traitval, const double alleleSD) -{ - traitAllele allele; - int nalleles = pSpecies->getNTraitAlleles(trait); - int ntraitmaps = pSpecies->getNTraitMaps(); -#if RSDEBUG - //DEBUGLOG << "Genome::setTrait(): this=" << this << " ntraitmaps=" << ntraitmaps - // << " trait=" << trait << " traitval=" << traitval << " alleleSD=" << alleleSD - // << " nalleles=" << nalleles - // << endl; -#endif - - int avalue; - double intbase = INTBASE; - if (trait < ntraitmaps) { - // // adjust mean and s.d. allowing for number of alleles determining phenotype - // double adjmean,adjsd,factor; - // if (diploid) factor = (double)(nalleles * 2); else factor = (double)(nalleles); - // adjmean = traitval / factor; - // adjsd = sqrt(alleleSD * alleleSD / factor); - - for (int i = 0; i < nalleles; i++) { - allele = pSpecies->getTraitAllele(trait, i); - // avalue = (int)(pRandom->Normal(adjmean,adjsd) * intbase); - avalue = (int)(pRandom->Normal(traitval, alleleSD) * intbase); -#if RSDEBUG - //DEBUGLOG << "Genome::setTrait(): this=" << this - // << " i=" << i << " chromo=" << allele.chromo << " locus=" << allele.locus - // << " posn=" << 0 << " avalue=" << avalue - // << endl; -#endif - pChromosome[allele.chromo]->initialise(allele.locus, 0, avalue); - if (diploid) { - // avalue = (int)(pRandom->Normal(adjmean,adjsd) * intbase); - avalue = (int)(pRandom->Normal(traitval, alleleSD) * intbase); - pChromosome[allele.chromo]->initialise(allele.locus, 1, avalue); - } - } - } - else { // insufficient traits were defined - // alleles cannot be initialised - all individuals have mean phenotype -#if RSDEBUG -//DEBUGLOG << "Genome::setTrait(): this=" << this -// << " *** unable to initialise undefined trait ***" << endl; -#endif - } - -} - -// Set up trait at initialisation for trait mapping -void Genome::setNeutralLoci(Species* pSpecies, const double alleleSD) -{ - traitAllele allele; - int nneutral = pSpecies->getNNeutralLoci(); -#if RSDEBUG - //DEBUGLOG << "Genome::setNeutralLoci(): this=" << this - // << " nneutral=" << nneutral << " alleleSD=" << alleleSD - // << endl; -#endif - -//int avalue; - double avalue; - double intbase = INTBASE; - //// adjust allele s.d. for diploid genotype - //double adjsd,factor; - //if (diploid) factor = 2.0; else factor = 1.0; - //adjsd = sqrt(alleleSD * alleleSD / factor); - - for (int i = 0; i < nneutral; i++) { - allele = pSpecies->getNeutralAllele(i); - // avalue = (int)(pRandom->Normal(0.0,adjsd) * intbase); - // pChromosome[allele.chromo]->initialise(allele.locus,0,avalue); - avalue = pRandom->Normal(0.0, alleleSD); - if (avalue > 0.0) - pChromosome[allele.chromo]->initialise(allele.locus, 0, (int)(avalue * intbase + 0.5)); - else - pChromosome[allele.chromo]->initialise(allele.locus, 0, (int)(avalue * intbase - 0.5)); -#if RSDEBUG - //DEBUGLOG << "Genome::setNeutralLoci(): this=" << this - // << " i=" << i << " chromo=" << allele.chromo << " locus=" << allele.locus - // << " avalue=" << avalue - // << endl; -#endif - if (diploid) { - // avalue = (int)(pRandom->Normal(0.0,adjsd) * intbase); - // pChromosome[allele.chromo]->initialise(allele.locus,1,avalue); - avalue = pRandom->Normal(0.0, alleleSD); - if (avalue > 0.0) - pChromosome[allele.chromo]->initialise(allele.locus, 1, (int)(avalue * intbase + 0.5)); - else - pChromosome[allele.chromo]->initialise(allele.locus, 1, (int)(avalue * intbase - 0.5)); - } - } -} - -// Return a single allele, having applied mutation -// Either allele is returned with equal probability, unless the gene is sex-linked, -// in which case a male returns the allele inherited from his father and a female -// returns the allele inherited from her mother -/* -double Genome::copy(int i,int sexx) -{ -double genevalue = 0.0; -return genevalue; -} -*/ - -// Return the expressed value of a gene when species has one chromosome per trait -double Genome::express(short chr, short expr, short indsex) -{ - double genevalue = 0.0; - //if (expr == 1) { - // genevalue = pChromosome[chr]->probval(diploid); - //} - //else - //genevalue = pChromosome[chr]->additive(diploid); - genevalue = pChromosome[chr]->meanvalue(diploid); -#if RSDEBUG - //DEBUGLOG << "Genome::express(): this=" << this - // << " chr=" << chr - // << " genevalue=" << genevalue - // << endl; -#endif - return genevalue; -} -/* -// Return the expressed value of an allele -double Genome::express(short chr,short loc) -{ -double genevalue = 0.0; -//if (expr == 1) { -// genevalue = pChromosome[chr]->probval(diploid); -//} -//else -genevalue = pChromosome[chr]->additive(loc,diploid); -#if RSDEBUG -//DEBUGLOG << "Genome::express(): this=" << this -// << " expr=" << expr -// << " genevalue=" << genevalue -// << endl; -#endif -return genevalue; -} -*/ - -// Return the expressed value of a trait when genetic architecture is defined -double Genome::express(Species* pSpecies, short traitnum) -{ - double genevalue = 0.0; - - traitAllele allele; - int nalleles = pSpecies->getNTraitAlleles(traitnum); - if (nalleles > 0) { - for (int i = 0; i < nalleles; i++) { - allele = pSpecies->getTraitAllele(traitnum, i); - genevalue += pChromosome[allele.chromo]->additive(allele.locus, diploid); - } - genevalue /= (double)nalleles; - if (diploid) genevalue /= 2.0; - } - - // genevalue = pChromosome[chr]->additive(diploid); -#if RSDEBUG -//DEBUGLOG << "Genome::express(): this=" << this -// << " traitnum=" << traitnum << " nalleles=" << nalleles -// << " genevalue=" << genevalue -// << endl; -#endif - return genevalue; -} - - -locusOK Genome::getAlleles(short chr, short loc) { - locusOK l; - l.allele[0] = l.allele[1] = 0; l.ok = false; - //double intbase = INTBASE; - if (chr >= 0 && chr < nChromosomes) { - if (pChromosome[chr] != 0) { - if (loc >= 0 && loc < pChromosome[chr]->nLoci()) { - locus a = pChromosome[chr]->alleles(loc); - l.allele[0] = a.allele[0]; l.allele[1] = a.allele[1]; l.ok = true; - } - } - } - // l.allele[0] = (int)(intbase * pChromosome[0]->additive(diploid)); - - return l; -} - -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- - -// OLD CODE WHICH MIGHT BE USEFUL FOR IMPLEMENTING ALTERNATIVE FORMS OF EXPRESSION - -/* - -// Set up new genome at initialisation -Genome::Genome(int g) { -if (g < 1) return; - -genomesize = g; -genome = new gene *[genomesize]; -for (int i = 0; i < genomesize; i++) { - genome[i] = new gene; - genome[i]->expression = 0; genome[i]->mutntype = 0; - genome[i]->Pmutn = 0.0; genome[i]->mutnSize = 0.0; - genome[i]->allele[0] = genome[i]->allele[1] = 0.0; -} - -} - -// Inherit genome from parent(s) -Genome::Genome(Genome *mother,Genome *father) -{ -#if RSDEBUG -//locn currloc = currCell->getLocn(); -//DEBUGLOG << "Genome::setGenes(): indId=" << indId -// << " x=" << currloc.x << " y=" << currloc.y -// << " pSpecies=" << pSpecies -// << " mother=" << mother -// << " father=" << father -// << endl; -#endif - -genomesize = mother->genomesize; -genome = new gene *[genomesize]; -for (int i = 0; i < genomesize; i++) { - genome[i] = new gene; - genome[i]->expression = mother->genome[i]->expression; - genome[i]->mutntype = mother->genome[i]->mutntype; - genome[i]->Pmutn = mother->genome[i]->Pmutn; - genome[i]->mutnSize = mother->genome[i]->mutnSize; - genome[i]->allele[0] = mother->copy(i,0); - if (father == 0) genome[i]->allele[1] = 0.0; - else genome[i]->allele[1] = father->copy(i,1); -} - -} - -Genome::~Genome(void) -{ -if (genome != 0) { - for (int i = 0; i < genomesize; i++) { - delete genome[i]; genome[i] = NULL; - } - delete genome; genome = NULL; -} - -} - -// Set up new gene -void Genome::setGene(int i,short exp,short mtype,float pmut,float msize,double a0,double a1) -{ -if (exp >= 0 && exp <= 4) genome[i]->expression = exp; -if (mtype >= 0 && mtype <= 5) genome[i]->mutntype = mtype; -if (pmut >= 0.0 && pmut <= 1.0) genome[i]->Pmutn = pmut; -if (msize > 0.0) genome[i]->mutnSize = msize; -genome[i]->allele[0] = a0; -genome[i]->allele[1] = a1; -} - -// Return a single allele, having applied mutation -// Either allele is returned with equal probability, unless the gene is sex-linked, -// in which case a male returns the allele inherited from his father and a female -// returns the allele inherited from her mother -double Genome::copy(int i,int sexx) -{ -double genevalue,logP,logitP; - -switch (genome[i]->expression) { -case 0: // haploid - genevalue = genome[i]->allele[0]; - break; -case 1: // sex-linked gene - if (sexx == 0 || sexx == 1) genevalue = genome[i]->allele[sexx]; - else return -999999.999; // indicates error in sex of parent animal - break; -default: // otherwise - select one of the alleles at random - genevalue = genome[i]->allele[pRandom->Bernoulli(0.5)]; - ; -} -#if RSDEBUG -//DEBUGLOG << "Gene::copy(): expression=" << expression -// << " mutntype=" << mutntype -// << " Pmutn=" << Pmutn << " mutnSize=" << mutnSize -// << " allele[0]=" << allele[0] << " allele[1]=" << allele[1] -// << " genevalue=" << genevalue -// << endl; -#endif -// apply mutation to the gene -if (pRandom->Random() < genome[i]->Pmutn) { - switch (genome[i]->mutntype) { - case 0: genevalue = pRandom->Random(); break; - case 1: genevalue += pRandom->Normal(0.0,genome[i]->mutnSize); break; - case 2: - logitP = log(genevalue/(1.0-genevalue)); - logitP += pRandom->Normal(0.0,genome[i]->mutnSize); - genevalue = 1.0 / (1 + exp(-logitP)); - if (genevalue >= 1.0) genevalue = 0.999999999; - if (genevalue <= 0.0) genevalue = 0.000000001; - break; - case 3: - logP = log(genevalue); - logP += pRandom->Normal(0.0,genome[i]->mutnSize); - genevalue = exp(logP); - break; - case 4: - genevalue += pRandom->Random()*(2.0*genome[i]->mutnSize) - genome[i]->mutnSize; - break; - case 5: - genevalue += pRandom->Random()*(2.0*genome[i]->mutnSize) - genome[i]->mutnSize; - if (genevalue > 1.0) genevalue = 1.0; - if (genevalue < 0.0) genevalue = 0.0; - break; - default: genevalue = -888888.888; // error in mutation type - } -} -#if RSDEBUG -//DEBUGLOG << "Gene::copy():" -// << " allele[0]=" << allele[0] << " allele[1]=" << allele[1] -// << " genevalue=" << genevalue -// << endl; -#endif -return genevalue; -} - -// Return the expressed value of a gene -double Genome::express(int i,int sexx) -{ -double genevalue; - -switch (genome[i]->expression) { - case 0: // sex-linked gene - genevalue = genome[i]->allele[0]; - break; - case 1: // sex-linked gene - if (sexx == 0 || sexx == 1) genevalue = genome[i]->allele[sexx]; - else genevalue = -999999.999; // indicates error in sex of parent animal - break; - case 2: // dominance of greater value - genevalue = genome[i]->allele[0]; - if (genome[i]->allele[1] > genevalue) genevalue = genome[i]->allele[1]; - break; - case 3: // co-dominance (mean value) - genevalue = (genome[i]->allele[0] + genome[i]->allele[1]) / 2.0; - break; - case 4: // sex-expressed co-dominance -// NB does not differ from co-dominance other than when genes interact to determine -// phenotypic level of expression - genevalue = (genome[i]->allele[0] + genome[i]->allele[1]) / 2.0; -// if (sexx == 0 || sexx == 1) genevalue = genome[i]->allele[sexx]; -// else genevalue = -999999.999; // indicates error in sex of parent animal - break; -default: genevalue = -777777.777; // error in expression type -} - -return genevalue; - -} - -locus Genome::getAlleles(int g) { -locus l; -if (g >= 0 && g < genomesize) { - l.allele[0] = genome[g]->allele[0]; - l.allele[1] = genome[g]->allele[1]; -} -else { - l.allele[0] = l.allele[1] = 0.0; -} -return l; -} - -*/ - -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- - diff --git a/Genome.h b/Genome.h deleted file mode 100644 index b19fee0..0000000 --- a/Genome.h +++ /dev/null @@ -1,251 +0,0 @@ -/*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * - * This file is part of RangeShifter. - * - * RangeShifter 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 3 of the License, or - * (at your option) any later version. - * - * RangeShifter is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RangeShifter. If not, see . - * - --------------------------------------------------------------------------*/ - - - /*------------------------------------------------------------------------------ - - RangeShifter v2.0 Genome - - Implements the Genome class - - Author: Steve Palmer & Roslyn Henry, University of Aberdeen - - Last updated: 28 July 2021 by Greta Bocedi - - ------------------------------------------------------------------------------*/ - -#ifndef GenomeH -#define GenomeH - -#include -#include - //#include "maths.h" - -#include "Parameters.h" -#include "Species.h" - -#define INTBASE 100.0; // to convert integer alleles into continuous traits - -struct locus { short allele[2]; }; -struct locusOK { short allele[2]; bool ok; }; - -//--------------------------------------------------------------------------- - -class Chromosome { - -public: - Chromosome(int); - ~Chromosome(); - short nLoci(void); - double additive( // Return trait value on normalised genetic scale - const bool // diploid - ); - double meanvalue( // Return trait value on normalised genetic scale - const bool // diploid - ); - double additive( // Return trait value on normalised genetic scale - const short, // locus - const bool // diploid - ); - // double probval(const bool); - locus alleles( // Return allele values at a specified locus - const int // position of locus on chromosome - ); - void initialise( // Set up chromosome at simulation initialisation - const double, // normalised phenotypic trait value - const double, // s.d. of allelic variance (genetic scale) - const bool // diploid - ); - void initialise( // Set up specified locus at simulation initialisation - const short, // locus - const short, // position: 0 from mother, 1 from father - const int // allele value - ); - void inherit( // Inherit chromosome from specified parent - const Chromosome*, // pointer to parent's chromosome - const short, // position: 0 from mother, 1 from father - const short, // no. of loci - const double, // mutation probability - const double, // crossover probability - const double, // s.d. of mutation magnitude (genetic scale) - const bool // diploid - ); - -protected: - -private: - short nloci; - locus* pLoci; - -}; - -//--------------------------------------------------------------------------- - -class Genome { - -public: - // - // static float delPMutation, delEffectSize, delDominance, delBackMutation ,genomeMeanRecombination; - // static int delMaxSize, delNMutations; - // static bool genomeCanRecombine, genomeCompletelyUnlinked; - // - - Genome(); - Genome(int, int, bool); - Genome(Species*); - Genome(Species*, Genome*, Genome*); - ~Genome(); - void setGene( // Set up new gene at initialisation for 1 chromosome per trait - const short, // chromosome number - const short, // expression type (NOT CURRENTLY USED) - const double, // normalised trait value - const double // s.d. of allelic variance - ); - void setTrait( // Set up trait at initialisation for trait mapping - Species*, // pointer to Species - const int, // trait number - const double, // normalised trait value - const double // s.d. of allelic variance - ); - void setNeutralLoci( // Set up neutral loci at initialisation - Species*, // pointer to Species - const double // s.d. of allelic variance - ); - // double copy(int,int); - double express( - // Return the expressed value of a gene when species has one chromosome per trait - short, // chromosome number - short, // expression type (NOT CURRENTLY USED) - short // individual's sex (NOT CURRENTLY USED) - ); - // double express( - // short, // chromosome number - // short // locus on chromosome - // ); - double express( - // Return the expressed value of a trait when genetic architecture is defined - Species*, // pointer to Species - short // trait number -// bool // true if trait is sex-dependent -); - locusOK getAlleles( // Get allele values at a specified locus - short, // chromosome number - short // locus position on chromosome - ); - // SCFP NEW DECLARATIONS - void setDiploid(bool); - bool isDiploid(void); - void inherit( // Inherit from specified parent - const Genome*, // pointer to parent's genome - const short, // position: 0 from mother, 1 from father - const short, // chromasome number - const double, // mutation probability - const double, // crossover probability - const double // s.d. of mutation magnitude (genetic scale) - ); - // void setStaticData(genomeData); - // genomeData getStaticData(void); - short getNChromosomes(void); - void outGenHeaders( - const int, // replicate - const int, // landscape number - const bool // output as cross table? - ); - void outGenetics( - const int, // replicate - const int, // year - const int, // species number - const int, // individual ID - const bool // output as cross table? - ); - - -private: - short nChromosomes; // no. of chromosomes - bool diploid; - Chromosome** pChromosome; - -}; - -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- - -/* - -struct gene { - short expression; // used to control how gene is expressed: - // 0 = haploid - // 1 = sex-linked - // 2 = dominance of greater value - // 3 = co-dominance (mean value) - // 4 = sex-expressed (but not sex-linked) - short mutntype; // mutation type: - // 0 = random in [0,1] - // 1 = normal - // 2 = logit scale - // 3 = log-normal (gene must be positive) - // 4 = RS method - random in specified range - // 5 = RS method - random in specified range and constrained to [0,1] - float Pmutn; // mutation probability - float mutnSize; // mutation size (s.d. of normal distribution) - double allele[2]; // allele pair: [0] from mother, [1] from father -}; -; - -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- - -class Genome -{ -public: - Genome(int); - Genome(Genome*,Genome*); - ~Genome(void); - void setGene(int); - void setGene(int,short,short,float,float,double,double); // new gene - double copy(int,int); - double express(int,int); - locus getAlleles( // Get allele values at a specified locus - int // locus position within genome - ); - -private: - int genomesize; - gene **genome; - -}; - -*/ - -//--------------------------------------------------------------------------- - -extern paramSim* paramsSim; -extern RSrandom* pRandom; - -#if RSDEBUG -extern ofstream DEBUGLOG; -extern ofstream MUTNLOG; -extern void DebugGUI(string); -#endif - -//--------------------------------------------------------------------------- - -#endif diff --git a/Individual.cpp b/Individual.cpp index c756f6f..411ffdc 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -26,6 +26,7 @@ //--------------------------------------------------------------------------- int Individual::indCounter = 0; +TraitFactory Individual::traitFactory = TraitFactory(); //--------------------------------------------------------------------------- @@ -39,10 +40,10 @@ Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short rep // << " stg=" << stg << " a=" << a << " probmale=" << probmale // << endl; #endif - + fitness = 1.0; stage = stg; - if (probmale <= 0.0) sex = 0; - else sex = pRandom->Bernoulli(probmale); + if (probmale <= 0.0) sex = FEM; + else sex = pRandom->Bernoulli(probmale) ? FEM : MAL; age = a; status = 0; @@ -53,437 +54,279 @@ Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short rep isDeveloping = false; pPrevCell = pCurrCell = pCell; pNatalPatch = pPatch; + pTrfrData = nullptr; //set to null as default if (movt) { locn loc = pCell->getLocn(); path = new pathData; path->year = 0; path->total = 0; path->out = 0; path->pSettPatch = 0; path->settleStatus = 0; // path->leftNatalPatch = false; -#if RS_RCPP - path->pathoutput = 1; -#endif if (moveType == 1) { // SMS // set up location data for SMS - smsData = new smsdata; - smsData->dp = smsData->gb = smsData->alphaDB = 1.0; - smsData->betaDB = 1; - smsData->prev.x = loc.x; smsData->prev.y = loc.y; // previous location - smsData->goal.x = loc.x; smsData->goal.y = loc.y; // goal location - initialised for dispersal bias + pTrfrData = make_unique(loc, loc); + } - else smsData = 0; if (moveType == 2) { // CRW // set up continuous co-ordinates etc. for CRW movement - crw = new crwParams; - crw->xc = ((float)pRandom->Random() * 0.999f) + (float)loc.x; - crw->yc = (float)(pRandom->Random() * 0.999f) + (float)loc.y; - crw->prevdrn = (float)(pRandom->Random() * 2.0 * PI); - crw->stepL = crw->rho = 0.0; + float xc = ((float)pRandom->Random() * 0.999f) + (float)loc.x; + float yc = (float)(pRandom->Random() * 0.999f) + (float)loc.y; + float prevdrn = (float)(pRandom->Random() * 2.0 * PI); + pTrfrData = make_unique(prevdrn, xc, yc); } - else crw = 0; } else { - path = 0; crw = 0; smsData = 0; + path = 0; + pTrfrData = make_unique(0.0, 0.0, 0.0); } - emigtraits = 0; - kerntraits = 0; - setttraits = 0; - pGenome = 0; + //pEmigTraits = make_unique(nullptr); + //pSettleTraits = make_unique(nullptr); #if RSDEBUG - //locn currloc = pCurrCell->getLocn(); - //DEBUGLOG << "Individual::Individual(): indId=" << indId - // << " x=" << currloc.x << " y=" << currloc.y - //// << " smsData=" << smsData << " dp=" << smsData->dp - // << endl; +//locn currloc = pCurrCell->getLocn(); +//DEBUGLOG << "Individual::Individual(): indId=" << indId +// << " x=" << currloc.x << " y=" << currloc.y +//// << " smsData=" << smsData << " dp=" << smsData->dp +// << endl; #endif } Individual::~Individual(void) { if (path != 0) delete path; - if (crw != 0) delete crw; - if (smsData != 0) delete smsData; - if (emigtraits != 0) delete emigtraits; - if (kerntraits != 0) delete kerntraits; - if (setttraits != 0) delete setttraits; + //if (crw != 0) delete crw; + //if (smsData != 0) delete smsData; + //if (emigtraits != 0) delete emigtraits; + //if (kerntraits != 0) delete kerntraits; + //if (setttraits != 0) delete setttraits; + +} + + +Individual* Individual::traitClone(Cell* pCell, Patch* pPatch, float probmale, bool movt, short moveType) { + + Individual* myTraitClone = new Individual(pCell, pPatch, 0, 0, 0, probmale, movt, moveType); + myTraitClone->pEmigTraits = make_unique(*pEmigTraits); + myTraitClone->pSettleTraits = make_unique(*pSettleTraits); + myTraitClone->pTrfrData->clone(*pTrfrData); + + return myTraitClone; +} + +void Individual::setEmigTraits(const emigTraits& emig) { + pEmigTraits = make_unique(emig); +} + +void Individual::setSettleTraits(const settleTraits& settle) { + pSettleTraits = make_unique(settle); +} - if (pGenome != 0) delete pGenome; +TTrait* Individual::getTrait(TraitType trait) const { + return this->traitTable.find(trait)->second.get(); +} + +//map> Individual::getTraitTable(void) const +//{ +// return traitTable; +//} + +set Individual::getTraitTypes() { + auto kv = std::views::keys(this->traitTable); + set< TraitType > keys{ kv.begin(), kv.end() }; + return keys; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -// Set genes for individual variation from species initialisation parameters -void Individual::setGenes(Species* pSpecies, int resol) { - demogrParams dem = pSpecies->getDemogr(); - emigRules emig = pSpecies->getEmig(); - trfrRules trfr = pSpecies->getTrfr(); - settleType sett = pSpecies->getSettle(); - genomeData gen = pSpecies->getGenomeData(); - simParams sim = paramsSim->getSim(); - int ntraits; // first trait for all/female expression, second for male expression - if (gen.trait1Chromosome) { - pGenome = new Genome(pSpecies->getNChromosomes(), pSpecies->getNLoci(0), - pSpecies->isDiploid()); - } - else { - pGenome = new Genome(pSpecies); - } -#if RSDEBUG - //DEBUGLOG << endl; - //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " sex=" << sex - // << " trait1Chromosome=" << gen.trait1Chromosome << " pGenome=" << pGenome - // << endl; -#endif +void Individual::inherit(Species* pSpecies, const Individual* mother, const Individual* father) { - int gposn = 0; // current position on genome - int expr = 0; // gene expression type - NOT CURRENTLY USED + int events = 0; + const set chromosomeEnds = pSpecies->getChromosomeEnds(); + const int genomeSize = pSpecies->getGenomeSize(); - //int emigposn = 0; -#if RSDEBUG -//DEBUGLOG << "Individual::setGenes(): emigration genes" << endl; -#endif - if (emig.indVar) { // set emigration genes - int emigposn = gposn; - double d0, alpha, beta; - emigParams eparams; - // emigScales scale = pSpecies->getEmigScales(); - if (emig.sexDep) { // must be a sexual species - ntraits = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction (haploid) - ntraits = 1; - } - else { // sexual reproduction - ntraits = 1; - } - } - for (int g = 0; g < ntraits; g++) { // first trait for females/all, second for males - eparams = pSpecies->getEmigParams(0, g); - d0 = pRandom->Normal(0.0, eparams.d0SD) / eparams.d0Scale; - if (emig.densDep) { - alpha = pRandom->Normal(0.0, eparams.alphaSD) / eparams.alphaScale; - beta = pRandom->Normal(0.0, eparams.betaSD) / eparams.betaScale; - } -#if RSDEBUG - //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g - // << " eparams.d0Mean=" << eparams.d0Mean << " eparams.d0SD=" << eparams.d0SD - // << " eparams.d0Scale=" << eparams.d0Scale << " d0=" << d0 - //// << " log(d0/(1.0-d0))=" << log(d0/(1.0-d0)) - // << endl; - //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g - // << " eparams.alphaMean=" << eparams.alphaMean << " eparams.alphaSD=" << eparams.alphaSD - // << " eparams.alphaScale=" << eparams.alphaScale << " alpha=" << alpha - // << endl; - //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g - // << " eparams.betaMean=" << eparams.betaMean << " eparams.betaSD=" << eparams.betaSD - // << " eparams.betaScale=" << eparams.betaScale << " beta=" << beta - // << endl; -#endif - if (gen.trait1Chromosome) { - pGenome->setGene(gposn++, expr, d0, gen.alleleSD); - if (emig.densDep) { - pGenome->setGene(gposn++, expr, alpha, gen.alleleSD); - pGenome->setGene(gposn++, expr, beta, gen.alleleSD); - } - } - else { - pGenome->setTrait(pSpecies, gposn++, d0, gen.alleleSD); - if (emig.densDep) { - pGenome->setTrait(pSpecies, gposn++, alpha, gen.alleleSD); - pGenome->setTrait(pSpecies, gposn++, beta, gen.alleleSD); - } - } - } - // record phenotypic traits - if (emig.densDep) { - setEmigTraits(pSpecies, emigposn, 3, emig.sexDep); - } - else { - setEmigTraits(pSpecies, emigposn, 1, emig.sexDep); - } + int maternalStartingChromosome = pRandom->Bernoulli(0.5); + int paternalStartingChromosome = pRandom->Bernoulli(0.5); + + set maternalRecomPositions; + set paternalRecomPositions; + + // Determine at which chromosome ends does the genome break + for (int pos : chromosomeEnds) { + if (pRandom->Bernoulli(0.5)) + maternalRecomPositions.insert(pos); + if (pRandom->Bernoulli(0.5)) + paternalRecomPositions.insert(pos); } - //int trfrposn = 0; - if (trfr.indVar) { // set transfer genes - int trfrposn = gposn; - if (trfr.sexDep) { // must be a sexual species - ntraits = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction - ntraits = 1; - } - else { // sexual reproduction - ntraits = 1; - } - } - // trfrScales scale = pSpecies->getTrfrScales(); - if (trfr.moveModel) { - if (trfr.moveType == 1) { // set SMS genes - double dp, gb, alphaDB, betaDB; - trfrSMSParams smsparams = pSpecies->getSMSParams(0, 0); // only traits for females/all - trfrSMSTraits smstraits = pSpecies->getSMSTraits(); - dp = pRandom->Normal(0.0, smsparams.dpSD) / smsparams.dpScale; - gb = pRandom->Normal(0.0, smsparams.gbSD) / smsparams.gbScale; - if (smstraits.goalType == 2) { - alphaDB = pRandom->Normal(0.0, smsparams.alphaDBSD) / smsparams.alphaDBScale; - betaDB = pRandom->Normal(0.0, smsparams.betaDBSD) / smsparams.betaDBScale; - } - if (gen.trait1Chromosome) { - pGenome->setGene(gposn++, expr, dp, gen.alleleSD); - pGenome->setGene(gposn++, expr, gb, gen.alleleSD); - if (smstraits.goalType == 2) { - pGenome->setGene(gposn++, expr, alphaDB, gen.alleleSD); - pGenome->setGene(gposn++, expr, betaDB, gen.alleleSD); - } - } - else { - pGenome->setTrait(pSpecies, gposn++, dp, gen.alleleSD); - pGenome->setTrait(pSpecies, gposn++, gb, gen.alleleSD); - if (smstraits.goalType == 2) { - pGenome->setTrait(pSpecies, gposn++, alphaDB, gen.alleleSD); - pGenome->setTrait(pSpecies, gposn++, betaDB, gen.alleleSD); - } - } - // record phenotypic traits - if (smstraits.goalType == 2) - setSMSTraits(pSpecies, trfrposn, 4, false); - else - setSMSTraits(pSpecies, trfrposn, 2, false); - } - if (trfr.moveType == 2) { // set CRW genes - double stepL, rho; - trfrCRWParams m = pSpecies->getCRWParams(0, 0); // only traits for females/all - stepL = pRandom->Normal(0.0, m.stepLgthSD) / m.stepLScale; - rho = pRandom->Normal(0.0, m.rhoSD) / m.rhoScale; - if (gen.trait1Chromosome) { - pGenome->setGene(gposn++, expr, stepL, gen.alleleSD); - pGenome->setGene(gposn++, expr, rho, gen.alleleSD); - } - else { - pGenome->setTrait(pSpecies, gposn++, stepL, gen.alleleSD); - pGenome->setTrait(pSpecies, gposn++, rho, gen.alleleSD); - } - // record phenotypic traits - setCRWTraits(pSpecies, trfrposn, 2, false); - } - } - else { // set kernel genes - double dist1, dist2, prob1; - trfrKernParams k; - for (int g = 0; g < ntraits; g++) { // first traits for females/all, second for males - k = pSpecies->getKernParams(0, g); - dist1 = pRandom->Normal(0.0, k.dist1SD) / k.dist1Scale; - if (trfr.twinKern) - { - dist2 = pRandom->Normal(0.0, k.dist2SD) / k.dist2Scale; - prob1 = pRandom->Normal(0.0, k.PKern1SD) / k.PKern1Scale; - } - if (gen.trait1Chromosome) { - pGenome->setGene(gposn++, expr, dist1, gen.alleleSD); - if (trfr.twinKern) - { - pGenome->setGene(gposn++, expr, dist2, gen.alleleSD); - pGenome->setGene(gposn++, expr, prob1, gen.alleleSD); - } - } - else { - pGenome->setTrait(pSpecies, gposn++, dist1, gen.alleleSD); - if (trfr.twinKern) - { - pGenome->setTrait(pSpecies, gposn++, dist2, gen.alleleSD); - pGenome->setTrait(pSpecies, gposn++, prob1, gen.alleleSD); - } - } - } - // record phenotypic traits - if (trfr.twinKern) - { - setKernTraits(pSpecies, trfrposn, 3, resol, trfr.sexDep); - } - else { - setKernTraits(pSpecies, trfrposn, 1, resol, trfr.sexDep); - } - } + // Draw recombination events for maternal genome + if (pSpecies->getRecombinationRate() > 0.0) + events = pRandom->Poisson(genomeSize * pSpecies->getRecombinationRate()); + int nbrCrossOvers = events + maternalRecomPositions.size(); + while (maternalRecomPositions.size() < nbrCrossOvers) { + // Sample recombination sites + maternalRecomPositions.insert(pRandom->IRandom(0, genomeSize)); } - //int settposn = 0; -#if RSDEBUG -//DEBUGLOG << "Individual::setGenes(): settlement genes" << endl; -#endif - if (sett.indVar) { - int settposn = gposn; - double s0, alpha, beta; - settParams sparams; - // settScales scale = pSpecies->getSettScales(); - if (sett.sexDep) { // must be a sexual species - ntraits = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction - ntraits = 1; - } - else { // sexual reproduction - ntraits = 1; - } - } - for (int g = 0; g < ntraits; g++) { // first trait for females/all, second for males - if (sim.batchMode) { - sparams = pSpecies->getSettParams(0, g); - } - else { // individual variability not (yet) implemented as sex-dependent in GUI - sparams = pSpecies->getSettParams(0, 0); - } - s0 = pRandom->Normal(0.0, sparams.s0SD) / sparams.s0Scale; - alpha = pRandom->Normal(0.0, sparams.alphaSSD) / sparams.alphaSScale; - beta = pRandom->Normal(0.0, sparams.betaSSD) / sparams.betaSScale; -#if RSDEBUG - //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g - // << " sparams.s0Mean=" << sparams.s0Mean - // << " sparams.s0SD=" << sparams.s0SD - // << " sparams.s0Scale=" << sparams.s0Scale - // << " s0=" << s0 - // << endl; - //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g - // << " sparams.alphaSMean=" << sparams.alphaSMean - // << " sparams.alphaSSD=" << sparams.alphaSSD - // << " sparams.alphaSScale=" << sparams.alphaSScale - // << " alpha=" << alpha - // << endl; - //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g - // << " sparams.betaSMean=" << sparams.betaSMean - // << " sparams.betaSSD=" << sparams.betaSSD - // << " sparams.betaSScale=" << sparams.betaSScale - // << " beta=" << beta - // << endl; -#endif - if (gen.trait1Chromosome) { - pGenome->setGene(gposn++, expr, s0, gen.alleleSD); - pGenome->setGene(gposn++, expr, alpha, gen.alleleSD); - pGenome->setGene(gposn++, expr, beta, gen.alleleSD); - } - else { - pGenome->setTrait(pSpecies, gposn++, s0, gen.alleleSD); - pGenome->setTrait(pSpecies, gposn++, alpha, gen.alleleSD); - pGenome->setTrait(pSpecies, gposn++, beta, gen.alleleSD); - } - } - // record phenotypic traits - setSettTraits(pSpecies, settposn, 3, sett.sexDep); + // Draw recombination events for paternal genome + if (pSpecies->getRecombinationRate() > 0.0) + events = pRandom->Poisson(genomeSize * pSpecies->getRecombinationRate()); + nbrCrossOvers = events + paternalRecomPositions.size(); + while (paternalRecomPositions.size() < nbrCrossOvers) { + paternalRecomPositions.insert(pRandom->IRandom(0, genomeSize)); } - if (!gen.trait1Chromosome) { - if (gen.neutralMarkers || pSpecies->getNNeutralLoci() > 0) { - pGenome->setNeutralLoci(pSpecies, gen.alleleSD); + // End of genome always recombines + maternalRecomPositions.insert(genomeSize - 1); + paternalRecomPositions.insert(genomeSize - 1); + + const auto& spTraits = pSpecies->getTraitTypes(); + + for (auto const& trait : spTraits) + { + const auto motherTrait = mother->getTrait(trait); + const auto fatherTrait = father->getTrait(trait); + auto newTrait = motherTrait->clone(); // shallow copy, pointer to proto trait initialised and empty sequence + + newTrait->inherit(motherTrait, maternalRecomPositions, FEM, maternalStartingChromosome); + if (newTrait->isInherited()) { + newTrait->inherit(fatherTrait, paternalRecomPositions, MAL, paternalStartingChromosome); + if (newTrait->getMutationRate() > 0 && pSpecies->areMutationsOn()) + newTrait->mutate(); } + if (trait == ADAPTIVE1 || trait == ADAPTIVE2 || trait == ADAPTIVE3 || trait == ADAPTIVE4 || trait == ADAPTIVE5) + fitness *= newTrait->express(); + + traitTable.insert(make_pair(trait, move(newTrait))); } -#if RSDEBUG - //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " finished" - // << endl; -#endif } -// Inherit genome from parent(s) -void Individual::setGenes(Species* pSpecies, Individual* mother, Individual* father, - int resol) -{ -#if RSDEBUG - //locn currloc = pCurrCell->getLocn(); - //DEBUGLOG << "Individual::setGenes(): indId=" << indId - // << " x=" << currloc.x << " y=" << currloc.y - //// << " pSpecies=" << pSpecies - // << " mother=" << mother - // << " motherID=" << mother->getId() - // << " father=" << father; - //if (father != 0) DEBUGLOG << " fatherID=" << father->getId(); - //DEBUGLOG << endl; -#endif - emigRules emig = pSpecies->getEmig(); - trfrRules trfr = pSpecies->getTrfr(); - settleType sett = pSpecies->getSettle(); +void Individual::inherit(Species* pSpecies, const Individual* mother) { + set recomPositions; //not used here cos haploid but need it for inherit function, not ideal + int startingChromosome = 0; + //const auto mumTraitTable = mother->getTraitTable(); //assuming mother and father share the same genetic structure.. - Genome* pFatherGenome; - if (father == 0) pFatherGenome = 0; else pFatherGenome = father->pGenome; + const auto& mumTraits = getTraitTypes(); - pGenome = new Genome(pSpecies, mother->pGenome, pFatherGenome); + for (auto const& trait : mumTraits) + { + const auto motherTrait = mother->getTrait(trait); - if (emig.indVar) { - // record emigration traits - if (father == 0) { // haploid - if (emig.densDep) { - setEmigTraits(pSpecies, 0, 3, 0); - } - else { - setEmigTraits(pSpecies, 0, 1, 0); - } - } - else { // diploid - if (emig.densDep) { - setEmigTraits(pSpecies, 0, 3, emig.sexDep); - } - else { - setEmigTraits(pSpecies, 0, 1, emig.sexDep); - } + auto newTrait = motherTrait->clone(); //shallow copy, pointer to proto trait initialised and empty sequence + + newTrait->inherit(motherTrait, recomPositions, FEM, startingChromosome); + if (newTrait->isInherited()) { + if (newTrait->getMutationRate() > 0 && pSpecies->areMutationsOn()) + newTrait->mutate(); } + if (trait == ADAPTIVE1 || trait == ADAPTIVE2 || trait == ADAPTIVE3 || trait == ADAPTIVE4 || trait == ADAPTIVE5) + fitness *= newTrait->express(); + + traitTable.insert(make_pair(trait, move(newTrait))); } +} - if (trfr.indVar) { - // record movement model traits - if (trfr.moveModel) { - if (trfr.moveType == 1) { // SMS - trfrSMSTraits s = pSpecies->getSMSTraits(); - if (s.goalType == 2) - setSMSTraits(pSpecies, trfr.movtTrait[0], 4, 0); - else - setSMSTraits(pSpecies, trfr.movtTrait[0], 2, 0); - } - if (trfr.moveType == 2) { // CRW - setCRWTraits(pSpecies, trfr.movtTrait[0], 2, 0); - } - } - else { // kernel - if (father == 0) { // haploid - if (trfr.twinKern) - { - setKernTraits(pSpecies, trfr.movtTrait[0], 3, resol, 0); - } - else { - setKernTraits(pSpecies, trfr.movtTrait[0], 1, resol, 0); - } - } - else { // diploid - if (trfr.twinKern) - { - setKernTraits(pSpecies, trfr.movtTrait[0], 3, resol, trfr.sexDep); - } - else { - setKernTraits(pSpecies, trfr.movtTrait[0], 1, resol, trfr.sexDep); - } - } - } +// Set genes for individual variation from species initialisation parameters +void Individual::setUpGenes(Species* pSpecies, int resol) { + + // this way to keep spp trait table immutable i.e. not able to call getTraitTable, + // could pass it back by value (copy) instead but could be heavy if large map + const auto& speciesTraits = pSpecies->getTraitTypes(); + + for (auto const& trait : speciesTraits) + { + const auto spTrait = pSpecies->getTrait(trait); + this->traitTable.emplace(trait, traitFactory.Create(trait, spTrait)); } + setQTLPhenotypes(pSpecies, resol); +} - if (sett.indVar) { - // record settlement traits - if (father == 0) { // haploid - setSettTraits(pSpecies, sett.settTrait[0], 3, 0); - } - else { // diploid - setSettTraits(pSpecies, sett.settTrait[0], 3, sett.sexDep); - // setSettTraits(pSpecies,sett.settTrait[0],3,0); +void Individual::setQTLPhenotypes(Species* pSpecies, int resol) { + + const emigRules emig = pSpecies->getEmig(); + const trfrRules trfr = pSpecies->getTrfr(); + const settleType sett = pSpecies->getSettle(); + + // record phenotypic traits + if (emig.indVar) + this->setEmigTraits(pSpecies, emig.sexDep, emig.densDep); + if (trfr.indVar) + this->setTransferTraits(pSpecies, trfr, resol); + if (sett.indVar) + this->setSettlementTraits(pSpecies, sett.sexDep); +} + +void Individual::setTransferTraits(Species* pSpecies, trfrRules trfr, int resol) { + if (trfr.moveModel) { + if (trfr.moveType == 1) { + setSMSTraits(pSpecies); } + else + setCRWTraits(pSpecies, trfr.sexDep); } + else + setKernelTraits(pSpecies, trfr.sexDep, trfr.twinKern, resol); +} +void Individual::setSettlementTraits(Species* pSpecies, bool sexDep) { + + settleTraits s; s.s0 = s.alpha = s.beta = 0.0; + if (sexDep && this->getSex() == MAL) { + s.s0 = getTrait(S_S0_M)->express(); + s.alpha = getTrait(S_ALPHA_M)->express(); + s.beta = getTrait(S_BETA_M)->express(); + } + else { + s.s0 = getTrait(S_S0_F)->express(); + s.alpha = getTrait(S_ALPHA_F)->express(); + s.beta = getTrait(S_BETA_F)->express(); + } + +#if RSDEBUG + //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId + // << " s.s0=" << s.s0 << " s.alpha=" << s.alpha << " s.beta=" << s.beta + // << endl; +#endif +#if RSDEBUG + //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId + // << " sparams.s0Mean=" << sparams.s0Mean << " sparams.s0SD=" << sparams.s0SD + // << " sparams.s0Scale=" << sparams.s0Scale + // << endl; +#endif + pSettleTraits = make_unique(); + pSettleTraits->s0 = (float)(s.s0); + pSettleTraits->alpha = (float)(s.alpha); + pSettleTraits->beta = (float)(s.beta); #if RSDEBUG - //emigParams e = getEmigTraits(0,1,0); - //DEBUGLOG << "Individual::setGenes(): indId=" << indId << " finished " - // << " d0=" << e.d0 - //// << " alpha=" << e.alpha << " beta=" << e.beta + //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId + // << " setttraits->s0=" << setttraits->s0 + // << " setttraits->alpha=" << setttraits->alpha << " setttraits->beta=" << setttraits->beta // << endl; #endif + if (pSettleTraits->s0 < 0.0) pSettleTraits->s0 = 0.0; + if (pSettleTraits->s0 > 1.0) pSettleTraits->s0 = 1.0; +#if RSDEBUG + //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId + // << " setttraits->s0=" << setttraits->s0 + // << " setttraits->alpha=" << setttraits->alpha << " setttraits->beta=" << setttraits->beta + // << endl; +#endif + return; +} + + +// Inherit genome from parent(s) +void Individual::inheritTraits(Species* pSpecies, Individual* mother, Individual* father, int resol) +{ + inherit(pSpecies, mother, father); + setQTLPhenotypes(pSpecies, resol); +} + +// Inherit genome from mother, haploid +void Individual::inheritTraits(Species* pSpecies, Individual* mother, int resol) +{ + inherit(pSpecies, mother); + setQTLPhenotypes(pSpecies, resol); } //--------------------------------------------------------------------------- @@ -491,7 +334,7 @@ void Individual::setGenes(Species* pSpecies, Individual* mother, Individual* fat // Identify whether an individual is a potentially breeding female - // if so, return her stage, otherwise return 0 int Individual::breedingFem(void) { - if (sex == 0) { + if (sex == FEM) { if (status == 0 || status == 4 || status == 5) return stage; else return 0; } @@ -500,10 +343,12 @@ int Individual::breedingFem(void) { int Individual::getId(void) { return indId; } -int Individual::getSex(void) { return sex; } +sex_t Individual::getSex(void) { return sex; } int Individual::getStatus(void) { return status; } +float Individual::getFitness(void) { return fitness; } + indStats Individual::getStats(void) { indStats s; s.stage = stage; s.sex = sex; s.age = age; s.status = status; s.fallow = fallow; @@ -568,86 +413,41 @@ void Individual::setSettPatch(const settlePatch s) { path->pSettPatch = s.pSettPatch; } -// Set phenotypic emigration traits -void Individual::setEmigTraits(Species* pSpecies, short emiggenelocn, short nemigtraits, - bool sexdep) { -#if RSDEBUG - //DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId - // << " emiggenelocn=" << emiggenelocn << " nemigtraits=" << nemigtraits << " sexdep=" << sexdep - // << endl; -#endif +void Individual::setEmigTraits(Species* pSpecies, bool sexDep, bool densityDep) { emigTraits e; e.d0 = e.alpha = e.beta = 0.0; - if (pGenome != 0) { - if (pSpecies->has1ChromPerTrait()) { - if (sexdep) { - if (nemigtraits == 3) { // emigration is density-dependent - e.d0 = (float)pGenome->express(emiggenelocn + 3 * sex, 0, 0); - e.alpha = (float)pGenome->express(emiggenelocn + 3 * sex + 1, 0, 0); - e.beta = (float)pGenome->express(emiggenelocn + 3 * sex + 2, 0, 0); - } - else { - e.d0 = (float)pGenome->express(emiggenelocn + sex, 0, 0); - } - } - else { - e.d0 = (float)pGenome->express(emiggenelocn, 0, 0); - if (nemigtraits == 3) { // emigration is density-dependent - e.alpha = (float)pGenome->express(emiggenelocn + 1, 0, 0); - e.beta = (float)pGenome->express(emiggenelocn + 2, 0, 0); - } - } - } - else { - if (sexdep) { - if (nemigtraits == 3) { // emigration is density-dependent - e.d0 = (float)pGenome->express(pSpecies, emiggenelocn + 3 * sex); - e.alpha = (float)pGenome->express(pSpecies, emiggenelocn + 3 * sex + 1); - e.beta = (float)pGenome->express(pSpecies, emiggenelocn + 3 * sex + 2); - } - else { - e.d0 = (float)pGenome->express(pSpecies, emiggenelocn + sex); - } - } - else { - e.d0 = (float)pGenome->express(pSpecies, emiggenelocn); - if (nemigtraits == 3) { // emigration is density-dependent - e.alpha = (float)pGenome->express(pSpecies, emiggenelocn + 1); - e.beta = (float)pGenome->express(pSpecies, emiggenelocn + 2); - } - } + if (sexDep && this->getSex() == MAL) { + e.d0 = this->getTrait(E_D0_M)->express(); + if (densityDep) { + e.alpha = getTrait(E_ALPHA_M)->express(); + e.beta = getTrait(E_BETA_M)->express(); } } -#if RSDEBUG - //DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId - // << " e.d0=" << e.d0 << " e.alpha=" << e.alpha << " e.beta=" << e.beta - // << endl; -#endif - - emigParams eparams; - if (sexdep) { - eparams = pSpecies->getEmigParams(0, sex); - } else { - eparams = pSpecies->getEmigParams(0, 0); + e.d0 = this->getTrait(E_D0_F)->express(); + if (densityDep) { + e.alpha = getTrait(E_ALPHA_F)->express(); + e.beta = getTrait(E_BETA_F)->express(); + } } + #if RSDEBUG //DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId // << " eparams.betaMean=" << eparams.betaMean << " eparams.betaSD=" << eparams.betaSD // << " eparams.betaScale=" << eparams.betaScale // << endl; #endif - emigtraits = new emigTraits; - emigtraits->d0 = (float)(e.d0 * eparams.d0Scale + eparams.d0Mean); - emigtraits->alpha = (float)(e.alpha * eparams.alphaScale + eparams.alphaMean); - emigtraits->beta = (float)(e.beta * eparams.betaScale + eparams.betaMean); + pEmigTraits = make_unique(); + pEmigTraits->d0 = (float)(e.d0); + pEmigTraits->alpha = (float)(e.alpha); + pEmigTraits->beta = (float)(e.beta); #if RSDEBUG //DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId // << " emigtraits->d0=" << emigtraits->d0 // << " emigtraits->alpha=" << emigtraits->alpha << " emigtraits->beta=" << emigtraits->beta // << endl; #endif - if (emigtraits->d0 < 0.0) emigtraits->d0 = 0.0; - if (emigtraits->d0 > 1.0) emigtraits->d0 = 1.0; + if (pEmigTraits->d0 < 0.0) pEmigTraits->d0 = 0.0; + if (pEmigTraits->d0 > 1.0) pEmigTraits->d0 = 1.0; #if RSDEBUG //DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId // << " emigtraits->d0=" << emigtraits->d0 @@ -664,10 +464,10 @@ emigTraits Individual::getEmigTraits(void) { // << endl; #endif emigTraits e; e.d0 = e.alpha = e.beta = 0.0; - if (emigtraits != 0) { - e.d0 = emigtraits->d0; - e.alpha = emigtraits->alpha; - e.beta = emigtraits->beta; + if (pEmigTraits != 0) { + e.d0 = pEmigTraits->d0; + e.alpha = pEmigTraits->alpha; + e.beta = pEmigTraits->beta; } #if RSDEBUG //DEBUGLOG << "Individual::getEmigTraits(): indId=" << indId @@ -677,74 +477,32 @@ emigTraits Individual::getEmigTraits(void) { return e; } - // Set phenotypic transfer by kernel traits -void Individual::setKernTraits(Species* pSpecies, short kerngenelocn, short nkerntraits, - int resol, bool sexdep) { -#if RSDEBUG - //DEBUGLOG << "Individual::setKernTraits(): indId=" << indId - // << " kerngenelocn=" << kerngenelocn << " nkerntraits=" << nkerntraits << " sexdep=" << sexdep - // << endl; -#endif +void Individual::setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel, int resol) { + trfrKernTraits k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; - if (pGenome != 0) { - if (pSpecies->has1ChromPerTrait()) { - if (sexdep) { - if (nkerntraits == 3) { // twin kernel - k.meanDist1 = (float)pGenome->express(kerngenelocn + 3 * sex, 0, sex); - k.meanDist2 = (float)pGenome->express(kerngenelocn + 3 * sex + 1, 0, sex); - k.probKern1 = (float)pGenome->express(kerngenelocn + 3 * sex + 2, 0, sex); - } - else { - k.meanDist1 = (float)pGenome->express(kerngenelocn + sex, 0, sex); - } - } - else { - k.meanDist1 = (float)pGenome->express(kerngenelocn, 0, 0); - if (nkerntraits == 3) { // twin kernel - k.meanDist2 = (float)pGenome->express(kerngenelocn + 1, 0, 0); - k.probKern1 = (float)pGenome->express(kerngenelocn + 2, 0, 0); - } - } - } - else { - if (sexdep) { - if (nkerntraits == 3) { // twin kernel - k.meanDist1 = (float)pGenome->express(pSpecies, kerngenelocn + 3 * sex); - k.meanDist2 = (float)pGenome->express(pSpecies, kerngenelocn + 3 * sex + 1); - k.probKern1 = (float)pGenome->express(pSpecies, kerngenelocn + 3 * sex + 2); - } - else { - k.meanDist1 = (float)pGenome->express(pSpecies, kerngenelocn + sex); - } - } - else { - k.meanDist1 = (float)pGenome->express(pSpecies, kerngenelocn); - if (nkerntraits == 3) { // twin kernel - k.meanDist2 = (float)pGenome->express(pSpecies, kerngenelocn + 1); - k.probKern1 = (float)pGenome->express(pSpecies, kerngenelocn + 2); - } - } + if (sexDep && this->sex == MAL) { + k.meanDist1 = getTrait(KERNEL_MEANDIST_1_M)->express(); + + if (twinKernel) { // twin kernel + k.meanDist2 = getTrait(KERNEL_MEANDIST_2_M)->express(); + k.probKern1 = getTrait(KERNEL_PROBABILITY_M)->express(); } - } -#if RSDEBUG - //DEBUGLOG << "Individual::setKernTraits(): indId=" << indId - // << " k.meanDist1=" << k.meanDist1 << " k.meanDist2=" << k.meanDist2 - // << " k.probKern1=" << k.probKern1 - // << endl; -#endif - trfrKernParams kparams; - if (sexdep) { - kparams = pSpecies->getKernParams(0, sex); } else { - kparams = pSpecies->getKernParams(0, 0); + k.meanDist1 = getTrait(KERNEL_MEANDIST_1_F)->express(); + + if (twinKernel) { // twin kernel + k.meanDist2 = getTrait(KERNEL_MEANDIST_2_F)->express(); + k.probKern1 = getTrait(KERNEL_PROBABILITY_F)->express(); + } + } - kerntraits = new trfrKernTraits; - kerntraits->meanDist1 = (float)(k.meanDist1 * kparams.dist1Scale + kparams.dist1Mean); - kerntraits->meanDist2 = (float)(k.meanDist2 * kparams.dist2Scale + kparams.dist2Mean); - kerntraits->probKern1 = (float)(k.probKern1 * kparams.PKern1Scale + kparams.PKern1Mean); + float meanDist1 = (float)(k.meanDist1); + float meanDist2 = (float)(k.meanDist2); + float probKern1 = (float)(k.probKern1); + #if RSDEBUG //DEBUGLOG << "Individual::setKernTraits(): indId=" << indId // << " kerntraits->meanDist1=" << kerntraits->meanDist1 @@ -754,11 +512,11 @@ void Individual::setKernTraits(Species* pSpecies, short kerngenelocn, short nker #endif if (!pSpecies->useFullKernel()) { // kernel mean(s) may not be less than landscape resolution - if (kerntraits->meanDist1 < resol) kerntraits->meanDist1 = (float)resol; - if (kerntraits->meanDist2 < resol) kerntraits->meanDist2 = (float)resol; + if (meanDist1 < resol) meanDist1 = (float)resol; + if (meanDist2 < resol) meanDist2 = (float)resol; } - if (kerntraits->probKern1 < 0.0) kerntraits->probKern1 = 0.0; - if (kerntraits->probKern1 > 1.0) kerntraits->probKern1 = 1.0; + if (probKern1 < 0.0) probKern1 = 0.0; + if (probKern1 > 1.0) probKern1 = 1.0; #if RSDEBUG //DEBUGLOG << "Individual::setKernTraits(): indId=" << indId // << " kerntraits->meanDist1=" << kerntraits->meanDist1 @@ -766,9 +524,16 @@ void Individual::setKernTraits(Species* pSpecies, short kerngenelocn, short nker // << " kerntraits->probKern1=" << kerntraits->probKern1 // << endl; #endif + auto& pKernel = dynamic_cast(*pTrfrData); + pKernel.meanDist1 = meanDist1; + pKernel.meanDist2 = meanDist2; + pKernel.probKern1 = probKern1; + return; } + + // Get phenotypic emigration traits trfrKernTraits Individual::getKernTraits(void) { #if RSDEBUG @@ -776,10 +541,13 @@ trfrKernTraits Individual::getKernTraits(void) { // << endl; #endif trfrKernTraits k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; - if (kerntraits != 0) { - k.meanDist1 = kerntraits->meanDist1; - k.meanDist2 = kerntraits->meanDist2; - k.probKern1 = kerntraits->probKern1; + if (pTrfrData != 0) { + + auto& pKernel = dynamic_cast(*pTrfrData); + + k.meanDist1 = pKernel.meanDist1; + k.meanDist2 = pKernel.meanDist2; + k.probKern1 = pKernel.probKern1; } #if RSDEBUG //DEBUGLOG << "Individual::getKernTraits(): indId=" << indId @@ -791,78 +559,35 @@ trfrKernTraits Individual::getKernTraits(void) { return k; } -// Set phenotypic transfer by SMS traits -void Individual::setSMSTraits(Species* pSpecies, short SMSgenelocn, short nSMStraits, - bool sexdep) { -#if RSDEBUG - //DEBUGLOG << "Individual::setSMSTraits(): indId=" << indId - // << " SMSgenelocn=" << SMSgenelocn << " nSMStraits=" << nSMStraits << " sexdep=" << sexdep - // << endl; -#endif +void Individual::setSMSTraits(Species* pSpecies) { + trfrSMSTraits s = pSpecies->getSMSTraits(); + double dp, gb, alphaDB, betaDB; dp = gb = alphaDB = betaDB = 0.0; - if (pGenome != 0) { - if (pSpecies->has1ChromPerTrait()) { - if (sexdep) { - dp = pGenome->express(SMSgenelocn, 0, 0); - gb = pGenome->express(SMSgenelocn + 1, 0, 0); - if (nSMStraits == 4) { - alphaDB = pGenome->express(SMSgenelocn + 2, 0, 0); - betaDB = pGenome->express(SMSgenelocn + 3, 0, 0); - } - } - else { - dp = pGenome->express(SMSgenelocn, 0, 0); - gb = pGenome->express(SMSgenelocn + 1, 0, 0); - if (nSMStraits == 4) { - alphaDB = pGenome->express(SMSgenelocn + 2, 0, 0); - betaDB = pGenome->express(SMSgenelocn + 3, 0, 0); - } - } - } - else { - if (sexdep) { - dp = pGenome->express(pSpecies, SMSgenelocn); - gb = pGenome->express(pSpecies, SMSgenelocn + 1); - if (nSMStraits == 4) { - alphaDB = pGenome->express(pSpecies, SMSgenelocn + 2); - betaDB = pGenome->express(pSpecies, SMSgenelocn + 3); - } - } - else { - dp = pGenome->express(pSpecies, SMSgenelocn); - gb = pGenome->express(pSpecies, SMSgenelocn + 1); - if (nSMStraits == 4) { - alphaDB = pGenome->express(pSpecies, SMSgenelocn + 2); - betaDB = pGenome->express(pSpecies, SMSgenelocn + 3); - } - } - } + dp = getTrait(SMS_DP)->express(); + gb = getTrait(SMS_GB)->express(); + if (s.goalType == 2) { + alphaDB = getTrait(SMS_ALPHADB)->express(); + betaDB = getTrait(SMS_BETADB)->express(); } + #if RSDEBUG //DEBUGLOG << "Individual::setSMSTraits(): indId=" << indId // << " dp=" << dp << " gb=" << gb // << " alphaDB=" << alphaDB << " betaDB=" << betaDB // << endl; #endif - - trfrSMSParams smsparams; - if (sexdep) { - smsparams = pSpecies->getSMSParams(0, 0); - } - else { - smsparams = pSpecies->getSMSParams(0, 0); - } - smsData->dp = (float)(dp * smsparams.dpScale + smsparams.dpMean); - smsData->gb = (float)(gb * smsparams.gbScale + smsparams.gbMean); + auto& pSMS = dynamic_cast(*pTrfrData); + pSMS.dp = (float)(dp); + pSMS.gb = (float)(gb); if (s.goalType == 2) { - smsData->alphaDB = (float)(alphaDB * smsparams.alphaDBScale + smsparams.alphaDBMean); - smsData->betaDB = (int)(betaDB * smsparams.betaDBScale + smsparams.betaDBMean + 0.5); + pSMS.alphaDB = (float)(alphaDB); + pSMS.betaDB = (int)(betaDB); } else { - smsData->alphaDB = s.alphaDB; - smsData->betaDB = s.betaDB; + pSMS.alphaDB = s.alphaDB; + pSMS.betaDB = s.betaDB; } #if RSDEBUG //DEBUGLOG << "Individual::setSMSTraits() 1111: indId=" << indId @@ -870,10 +595,10 @@ void Individual::setSMSTraits(Species* pSpecies, short SMSgenelocn, short nSMStr // << " smsData->alphaDB=" << smsData->alphaDB << " smsData->betaDB=" << smsData->betaDB // << endl; #endif - if (smsData->dp < 1.0) smsData->dp = 1.0; - if (smsData->gb < 1.0) smsData->gb = 1.0; - if (smsData->alphaDB <= 0.0) smsData->alphaDB = 0.000001f; - if (smsData->betaDB < 1) smsData->betaDB = 1; + if (pSMS.dp < 1.0) pSMS.dp = 1.0; + if (pSMS.gb < 1.0) pSMS.gb = 1.0; + if (pSMS.alphaDB <= 0.0) pSMS.alphaDB = 0.000001f; + if (pSMS.betaDB < 1) pSMS.betaDB = 1; #if RSDEBUG //DEBUGLOG << "Individual::setSMSTraits() 2222: indId=" << indId // << " smsData->dp=" << smsData->dp << " smsData->gb=" << smsData->gb @@ -883,6 +608,10 @@ void Individual::setSMSTraits(Species* pSpecies, short SMSgenelocn, short nSMStr return; } +trfrData* Individual::getTrfrData(void) { + return pTrfrData.get(); +} + // Get phenotypic transfer by SMS traits trfrSMSTraits Individual::getSMSTraits(void) { #if RSDEBUG @@ -890,9 +619,12 @@ trfrSMSTraits Individual::getSMSTraits(void) { // << endl; #endif trfrSMSTraits s; s.dp = s.gb = s.alphaDB = 1.0; s.betaDB = 1; - if (smsData != 0) { - s.dp = smsData->dp; s.gb = smsData->gb; - s.alphaDB = smsData->alphaDB; s.betaDB = smsData->betaDB; + if (pTrfrData != 0) { + + auto& pSMS = dynamic_cast(*pTrfrData); + + s.dp = pSMS.dp; s.gb = pSMS.gb; + s.alphaDB = pSMS.alphaDB; s.betaDB = pSMS.betaDB; } #if RSDEBUG //DEBUGLOG << "Individual::getSMSTraits(): indId=" << indId @@ -903,60 +635,36 @@ trfrSMSTraits Individual::getSMSTraits(void) { return s; } + // Set phenotypic transfer by CRW traits -void Individual::setCRWTraits(Species* pSpecies, short CRWgenelocn, short nCRWtraits, - bool sexdep) { -#if RSDEBUG - //DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId - // << " CRWgenelocn=" << CRWgenelocn << " nCRWtraits=" << nCRWtraits << " sexdep=" << sexdep - // << endl; -#endif +void Individual::setCRWTraits(Species* pSpecies, bool sexDep) { trfrCRWTraits c; c.stepLength = c.rho = 0.0; - if (pGenome != 0) { - if (pSpecies->has1ChromPerTrait()) { - if (sexdep) { - c.stepLength = (float)pGenome->express(CRWgenelocn + sex, 0, sex); - c.rho = (float)pGenome->express(CRWgenelocn + 2 + sex, 0, sex); - } - else { - c.stepLength = (float)pGenome->express(CRWgenelocn, 0, 0); - c.rho = (float)pGenome->express(CRWgenelocn + 1, 0, 0); - } - } - else { - if (sexdep) { - c.stepLength = (float)pGenome->express(pSpecies, CRWgenelocn + sex); - c.rho = (float)pGenome->express(pSpecies, CRWgenelocn + 2 + sex); - } - else { - c.stepLength = (float)pGenome->express(pSpecies, CRWgenelocn); - c.rho = (float)pGenome->express(pSpecies, CRWgenelocn + 1); - } - } + if (sexDep && this->sex == MAL) { + c.stepLength = getTrait(CRW_STEPLENGTH_M)->express(); + c.rho = getTrait(CRW_STEPCORRELATION_M)->express(); + } + else { + c.stepLength = getTrait(CRW_STEPLENGTH_F)->express(); + c.rho = getTrait(CRW_STEPCORRELATION_F)->express(); } + #if RSDEBUG //DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId // << " c.stepLength=" << c.stepLength << " c.rho=" << c.rho // << endl; #endif - trfrCRWParams cparams; - if (sexdep) { - cparams = pSpecies->getCRWParams(0, sex); - } - else { - cparams = pSpecies->getCRWParams(0, 0); - } - crw->stepL = (float)(c.stepLength * cparams.stepLScale + cparams.stepLgthMean); - crw->rho = (float)(c.rho * cparams.rhoScale + cparams.rhoMean); + auto& pCRW = dynamic_cast(*pTrfrData); + pCRW.stepLength = (float)(c.stepLength); + pCRW.rho = (float)(c.rho); #if RSDEBUG //DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId // << " crw->stepL=" << crw->stepL << " crw->rho=" << crw->rho // << endl; #endif - if (crw->stepL < 1.0) crw->stepL = 1.0; - if (crw->rho < 0.0) crw->rho = 0.0; - if (crw->rho > 0.999) crw->rho = 0.999f; + if (pCRW.stepLength < 1.0) pCRW.stepLength = 1.0; + if (pCRW.rho < 0.0) pCRW.rho = 0.0; + if (pCRW.rho > 0.999) pCRW.rho = 0.999f; #if RSDEBUG //DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId // << " crw->stepL=" << crw->stepL << " crw->rho=" << crw->rho @@ -972,95 +680,23 @@ trfrCRWTraits Individual::getCRWTraits(void) { // << endl; #endif trfrCRWTraits c; c.stepLength = c.rho = 0.0; - if (crw != 0) { - c.stepLength = crw->stepL; - c.rho = crw->rho; - } -#if RSDEBUG - //DEBUGLOG << "Individual::getCRWTraits(): indId=" << indId - // << " c.stepLength=" << c.stepLength << " c.rho=" << c.rho - // << endl; -#endif - return c; -} + if (pTrfrData != 0) { -// Set phenotypic settlement traits -void Individual::setSettTraits(Species* pSpecies, short settgenelocn, short nsetttraits, - bool sexdep) { -#if RSDEBUG - //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId << " sex=" << sex - // << " settgenelocn=" << settgenelocn << " nsetttraits=" << nsetttraits << " sexdep=" << sexdep - // << endl; -#endif -//simParams sim = paramsSim->getSim(); - settleTraits s; s.s0 = s.alpha = s.beta = 0.0; - if (pGenome != 0) { - if (pSpecies->has1ChromPerTrait()) { - if (sexdep) { - s.s0 = (float)pGenome->express(settgenelocn + 3 * sex, 0, 0); - s.alpha = (float)pGenome->express(settgenelocn + 3 * sex + 1, 0, 0); - s.beta = (float)pGenome->express(settgenelocn + 3 * sex + 2, 0, 0); - } - else { - s.s0 = (float)pGenome->express(settgenelocn, 0, 0); - s.alpha = (float)pGenome->express(settgenelocn + 1, 0, 0); - s.beta = (float)pGenome->express(settgenelocn + 2, 0, 0); - } - } - else { - if (sexdep) { - s.s0 = (float)pGenome->express(pSpecies, settgenelocn + 3 * sex); - s.alpha = (float)pGenome->express(pSpecies, settgenelocn + 3 * sex + 1); - s.beta = (float)pGenome->express(pSpecies, settgenelocn + 3 * sex + 2); - } - else { - s.s0 = (float)pGenome->express(pSpecies, settgenelocn); - s.alpha = (float)pGenome->express(pSpecies, settgenelocn + 1); - s.beta = (float)pGenome->express(pSpecies, settgenelocn + 2); - } + auto& pCRW = dynamic_cast(*pTrfrData); - } + c.stepLength = pCRW.stepLength; + c.rho = pCRW.rho; } #if RSDEBUG - //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId - // << " s.s0=" << s.s0 << " s.alpha=" << s.alpha << " s.beta=" << s.beta + //DEBUGLOG << "Individual::getCRWTraits(): indId=" << indId + // << " c.stepLength=" << c.stepLength << " c.rho=" << c.rho // << endl; #endif - settParams sparams; - if (sexdep) { - sparams = pSpecies->getSettParams(0, sex); - } - else { - sparams = pSpecies->getSettParams(0, 0); - } -#if RSDEBUG - //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId - // << " sparams.s0Mean=" << sparams.s0Mean << " sparams.s0SD=" << sparams.s0SD - // << " sparams.s0Scale=" << sparams.s0Scale - // << endl; -#endif - setttraits = new settleTraits; - setttraits->s0 = (float)(s.s0 * sparams.s0Scale + sparams.s0Mean); - setttraits->alpha = (float)(s.alpha * sparams.alphaSScale + sparams.alphaSMean); - setttraits->beta = (float)(s.beta * sparams.betaSScale + sparams.betaSMean); -#if RSDEBUG - //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId - // << " setttraits->s0=" << setttraits->s0 - // << " setttraits->alpha=" << setttraits->alpha << " setttraits->beta=" << setttraits->beta - // << endl; -#endif - if (setttraits->s0 < 0.0) setttraits->s0 = 0.0; - if (setttraits->s0 > 1.0) setttraits->s0 = 1.0; -#if RSDEBUG - //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId - // << " setttraits->s0=" << setttraits->s0 - // << " setttraits->alpha=" << setttraits->alpha << " setttraits->beta=" << setttraits->beta - // << endl; -#endif - return; + return c; + } // Get phenotypic settlement traits @@ -1070,10 +706,10 @@ settleTraits Individual::getSettTraits(void) { // << endl; #endif settleTraits s; s.s0 = s.alpha = s.beta = 0.0; - if (setttraits != 0) { - s.s0 = setttraits->s0; - s.alpha = setttraits->alpha; - s.beta = setttraits->beta; + if (pSettleTraits != 0) { + s.s0 = pSettleTraits->s0; + s.alpha = pSettleTraits->alpha; + s.beta = pSettleTraits->beta; } #if RSDEBUG //DEBUGLOG << "Individual::getSettTraits(): indId=" << indId @@ -1164,14 +800,14 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, if (trfr.indVar) { // get individual's kernel parameters kern.meanDist1 = kern.meanDist2 = kern.probKern1 = 0.0; - // kparams = pSpecies->getKernParams(stage,sex); - if (pGenome != 0) { - kern.meanDist1 = kerntraits->meanDist1; - if (trfr.twinKern) - { - kern.meanDist2 = kerntraits->meanDist2; - kern.probKern1 = kerntraits->probKern1; - } + + auto& pKernel = dynamic_cast(*pTrfrData); + + kern.meanDist1 = pKernel.meanDist1; + if (trfr.twinKern) + { + kern.meanDist2 = pKernel.meanDist2; + kern.probKern1 = pKernel.probKern1; } } else { // get kernel parameters for the species @@ -1386,7 +1022,6 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, const short landIx, const bool absorbing) { - if (status != 1) return 0; // not currently dispersing intptr patch; @@ -1476,7 +1111,6 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, loc = pCurrCell->getLocn(); newX = loc.x; newY = loc.y; - switch (trfr.moveType) { case 1: // SMS @@ -1533,11 +1167,12 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, break; case 2: // CRW - if (trfr.indVar) { - if (crw != 0) { - movt.stepLength = crw->stepL; - movt.rho = crw->rho; - } + + auto & pCRW = dynamic_cast(*pTrfrData); + + if (trfr.indVar) { + movt.stepLength = pCRW.stepLength; + movt.rho = pCRW.rho; } steplen = movt.stepLength; if (steplen < 0.2 * land.resol) steplen = 0.2 * land.resol; @@ -1559,13 +1194,13 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, || pCurrCell == 0) { // individual has tried to go out-of-bounds or into no-data area // allow random move to prevent repeated similar move - angle = wrpcauchy(crw->prevdrn, 0.0); + angle = wrpcauchy(pCRW.prevdrn, 0.0); } else - angle = wrpcauchy(crw->prevdrn, rho); + angle = wrpcauchy(pCRW.prevdrn, rho); // new continuous cell coordinates - xcnew = crw->xc + sin(angle) * steplen / (float)land.resol; - ycnew = crw->yc + cos(angle) * steplen / (float)land.resol; + xcnew = pCRW.xc + sin(angle) * steplen / (float)land.resol; + ycnew = pCRW.yc + cos(angle) * steplen / (float)land.resol; if (xcnew < 0.0) newX = -1; else newX = (int)xcnew; if (ycnew < 0.0) newY = -1; else newY = (int)ycnew; loopsteps++; @@ -1594,8 +1229,8 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, // << " pCurrCell=" << pCurrCell << " patch=" << patch << endl; #endif } while (!absorbing && pCurrCell == 0 && loopsteps < 1000); - crw->prevdrn = (float)angle; - crw->xc = (float)xcnew; crw->yc = (float)ycnew; + pCRW.prevdrn = (float)angle; + pCRW.xc = (float)xcnew; pCRW.yc = (float)ycnew; if (absorbed) { // beyond absorbing boundary or in no-data square status = 6; dispersing = 0; @@ -1677,7 +1312,6 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, const short landIx, const bool natalPatch, const bool indvar, const bool absorbing) { - array3x3d nbr; // to hold weights/costs/probs of moving to neighbouring cells array3x3d goal; // to hold weights for moving towards a goal location array3x3f hab; // to hold weights for habitat (includes percep range) @@ -1690,6 +1324,7 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, int cellcost, newcellcost; locn current; + auto& pSMS = dynamic_cast(*pTrfrData); //if (write_out) { // out<settleStatus > 0)) { // inflate directional persistence to promote leaving the patch - if (indvar) nbr = getSimDir(current.x, current.y, 10.0f * smsData->dp); + if (indvar) nbr = getSimDir(current.x, current.y, 10.0f * pSMS.dp); else nbr = getSimDir(current.x, current.y, 10.0f * movt.dp); } else { - if (indvar) nbr = getSimDir(current.x, current.y, smsData->dp); + if (indvar) nbr = getSimDir(current.x, current.y, pSMS.dp); else nbr = getSimDir(current.x, current.y, movt.dp); } if (natalPatch || path->settleStatus > 0) path->out = 0; @@ -1755,12 +1390,12 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, nsteps = path->total; } if (indvar) { - double exp_arg = -((double)nsteps - (double)smsData->betaDB) * (-smsData->alphaDB); + double exp_arg = -((double)nsteps - (double)pSMS.betaDB) * (-pSMS.alphaDB); #if RSDEBUG //DEBUGLOG << "Individual::smsMove(): exp_arg=" << exp_arg; #endif if (exp_arg > 100.0) exp_arg = 100.0; // to prevent exp() overflow error - gb = 1.0 + (smsData->gb - 1.0) / (1.0 + exp(exp_arg)); + gb = 1.0 + (pSMS.gb - 1.0) / (1.0 + exp(exp_arg)); } else { double exp_arg = -((double)nsteps - (double)movt.betaDB) * (-movt.alphaDB); @@ -1952,6 +1587,8 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, } } + //to prevent very rare bug that random draw is greater than 0.999999999 + if (cumulative[8] != 1) cumulative[8] = 1; // select direction at random based on cell selection probabilities // landscape boundaries and no-data cells may be reflective or absorbing cellcost = pCurrCell->getCost(); @@ -2086,6 +1723,7 @@ array3x3d Individual::getGoalBias(const int x, const int y, array3x3d d; double theta; int xx, yy; + auto& pSMS = dynamic_cast(*pTrfrData); if (goaltype == 0) { // no goal set for (xx = 0; xx < 3; xx++) { @@ -2096,7 +1734,7 @@ array3x3d Individual::getGoalBias(const int x, const int y, } else { d.cell[1][1] = 0; - if ((x - smsData->goal.x) == 0 && (y - smsData->goal.y) == 0) { + if ((x - pSMS.goal.x) == 0 && (y - pSMS.goal.y) == 0) { // at goal, set matrix to unity // if (write_out) out<<"*** at goal: x,y = "<goal.x), ((double)y - (double)smsData->goal.y)); + theta = atan2(((double)x - (double)pSMS.goal.x), ((double)y - (double)pSMS.goal.y)); // if (write_out) out<<"goalx,goaly: "<(toAdd); + + CRW.stepLength += stepLength; + CRW.rho += rho; + + //stepLength += pCRW.stepLength; + // rho += pCRW.rho; + } + + movement_t getType() { return CRW; } + + void clone(const trfrData& copyFrom) { + + + auto pCopy = dynamic_cast(copyFrom); + + stepLength = pCopy.stepLength; + rho = pCopy.rho; + } + + void divideTraitsBy(int i) { + + stepLength /= i; + rho /= i; + } + }; struct array3x3d { double cell[3][3]; }; struct movedata { float dist; float cost; }; -struct smsdata { +struct smsData : trfrData { locn prev; // location of previous cell locn goal; // location of goal float dp; // directional persistence float gb; // goal bias float alphaDB; // dispersal bias decay rate int betaDB; // dispersal bias decay inflection point (no. of steps) + + //below are shared + //static short pr; + //static short prMethod; + //static short memSize; + //static short goalType; + //static float stepMort; + //static bool straigtenPath; + + smsData(locn prevA, locn goalA) : prev(prevA), goal(goalA), dp(0.0), gb(0.0), alphaDB(0.0), betaDB(0.0) {} + ~smsData() {} + + + void addMyself(trfrData& toAdd) { + auto& SMS = dynamic_cast(toAdd); + SMS.dp += dp; + SMS.gb += gb; + SMS.alphaDB += alphaDB; + SMS.betaDB += betaDB; + } + + movement_t getType() { return SMS; } + + void clone(const trfrData& copyFrom) { + auto& pCopy = dynamic_cast(copyFrom); + dp = pCopy.dp; + gb = pCopy.gb; + alphaDB = pCopy.alphaDB; + betaDB = pCopy.betaDB; + } + + void divideTraitsBy(int i) { + + dp /= i; + gb /= i; + alphaDB /= i; + betaDB /= i; + } + +}; + +struct kernelData : trfrData { + float meanDist1; + float meanDist2; + float probKern1; + + kernelData(float meanDist1A, float meanDist2A, float probKern1A) : meanDist1(meanDist1A), meanDist2(meanDist2A), probKern1(probKern1A) {} + ~kernelData() {} + + void addMyself(trfrData& toAdd) { + + auto& Kernel = dynamic_cast(toAdd); + + Kernel.meanDist1 += meanDist1; + Kernel.meanDist2 += meanDist2; + Kernel.probKern1 += probKern1; + } + + movement_t getType() { return KERNEL; } + + void clone(const trfrData& copyFrom) { + auto pCopy = dynamic_cast(copyFrom); + meanDist1 = pCopy.meanDist1; + meanDist2 = pCopy.meanDist2; + probKern1 = pCopy.probKern1; + } + + void divideTraitsBy(int i) { + meanDist1 /= i; + meanDist2 /= i; + probKern1 /= i; + } }; class Individual { public: static int indCounter; // used to create ID, held by class, not members of class + static TraitFactory traitFactory; Individual( // Individual constructor Cell*, // pointer to Cell Patch*, // pointer to patch @@ -116,62 +236,67 @@ class Individual { short // movement type: 1 = SMS, 2 = CRW ); ~Individual(void); - void setGenes( // Set genes for individual variation from species initialisation parameters + void setUpGenes( // Set genes for individual variation from species initialisation parameters Species*, // pointer to Species int // Landscape resolution ); - void setGenes( // Inherit genome from parents + void inheritTraits( // Inherit genome from parents Species*, // pointer to Species Individual*, // pointer to mother Individual*, // pointer to father (must be 0 for an asexual Species) int // Landscape resolution ); - void setEmigTraits( // Set phenotypic emigration traits - Species*, // pointer to Species - short, // location of emigration genes on genome - short, // number of emigration genes - bool // TRUE if emigration is sex-dependent - ); + + void inheritTraits(Species* pSpecies, Individual* mother, int resol); //haploid + + void setQTLPhenotypes(Species* pSpecies, int resol); + + TTrait* getTrait(TraitType trait) const; + + set getTraitTypes(); + + //map> getTraitTable(void) const; + + void inherit(Species* pSpecies, const Individual* mother, const Individual* father); + + void inherit(Species* pSpecies, const Individual* mother); // haploid + + Individual* traitClone(Cell*, Patch*, float, bool, short); + + + void setEmigTraits(Species* pSpecies, bool sexDep, bool densityDep); + void setTransferTraits(Species* pSpecies, trfrRules trfr, int resol); + emigTraits getEmigTraits(void); // Get phenotypic emigration traits - void setKernTraits( // Set phenotypic transfer by kernel traits - Species*, // pointer to Species - short, // location of kernel genes on genome - short, // number of kernel genes - int, // Landscape resolution - bool // TRUE if transfer is sex-dependent - ); + void setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel, int resol); + trfrKernTraits getKernTraits(void); // Get phenotypic transfer by kernel traits - void setSMSTraits( // Set phenotypic transfer by SMS traits - Species*, // pointer to Species - short, // location of SMS genes on genome - short, // number of SMS genes - bool // TRUE if transfer is sex-dependent - ); + void setSMSTraits(Species* pSpecies); + trfrSMSTraits getSMSTraits(void); // Get phenotypic transfer by SMS traits - void setCRWTraits( // Set phenotypic transfer by CRW traits - Species*, // pointer to Species - short, // location of CRW genes on genome - short, // number of CRW genes - bool // TRUE if transfer is sex-dependent - ); + + void setCRWTraits(Species* pSpecies, bool sexDep); + trfrCRWTraits getCRWTraits(void); // Get phenotypic transfer by CRW traits - void setSettTraits( // Set phenotypic settlement traits - Species*, // pointer to Species - short, // location of settlement genes on genome - short, // number of settlement genes - bool // TRUE if settlement is sex-dependent - ); + void setSettlementTraits(Species* pSpecies, bool sexDep); + settleTraits getSettTraits(void); // Get phenotypic settlement traits + trfrData* getTrfrData(void); + void setEmigTraits(const emigTraits& emig); + void setSettleTraits(const settleTraits& settle); + + // Identify whether an individual is a potentially breeding female - // if so, return her stage, otherwise return 0 int breedingFem(void); int getId(void); - int getSex(void); + sex_t getSex(void); int getStatus(void); + float getFitness(void); indStats getStats(void); Cell* getLocn( // Return location (as pointer to Cell) const short // option: 0 = get natal locn, 1 = get current locn @@ -264,8 +389,9 @@ class Individual { private: int indId; + float fitness; short stage; - short sex; + sex_t sex; short age; short status; // 0 = initial status in natal patch / philopatric recruit // 1 = disperser @@ -285,16 +411,12 @@ class Individual { Cell* pPrevCell; // pointer to previous Cell Cell* pCurrCell; // pointer to current Cell Patch* pNatalPatch; // pointer to natal Patch - emigTraits* emigtraits; // pointer to emigration traits - trfrKernTraits* kerntraits; // pointers to transfer by kernel traits pathData* path; // pointer to path data for movement model - crwParams* crw; // pointer to CRW traits and data - smsdata* smsData; // pointer to variables required for SMS - settleTraits* setttraits; // pointer to settlement traits + std::unique_ptr pEmigTraits; // pointer to emigration traits + std::unique_ptr pSettleTraits; // pointer to settlement traits + std::unique_ptr pTrfrData; //can be sms, kernel, crw std::queue memory; // memory of last N squares visited for SMS - - Genome* pGenome; - + map> traitTable; }; diff --git a/Landscape.cpp b/Landscape.cpp index efa88a4..e38d93e 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -184,10 +184,8 @@ int InitDist::readDistribution(string distfile) { // read landscape data from header records of distribution file // NB headers of all files have already been compared - double tmpresol; dfile >> header >> ncols >> header >> nrows >> header >> minEast >> header >> minNorth - >> header >> tmpresol >> header >> nodata; - resol = (int)tmpresol; + >> header >> resol >> header >> nodata; #if RS_RCPP if (!dfile.good()) { // corrupt file stream @@ -225,7 +223,7 @@ int InitDist::readDistribution(string distfile) { return 22; } #if RS_RCPP - } + } else { // corrupt file stream #if RS_RCPP && !R_CMD @@ -235,17 +233,17 @@ int InitDist::readDistribution(string distfile) { dfile.close(); dfile.clear(); return 144; - } -#endif } +#endif + } } #if RS_RCPP dfile >> p; if (!dfile.eof()) EOFerrorR(distfile); #endif -dfile.close(); dfile.clear(); -return 0; + dfile.close(); dfile.clear(); + return 0; } @@ -369,6 +367,7 @@ void Landscape::resetLand(void) { #endif for (int i = 0; i < npatches; i++) if (patches[i] != NULL) delete patches[i]; patches.clear(); + patchnums.clear(); #if RSDEBUG //DebugGUI("Landscape::resetLand(): finished resetting patches"); #endif @@ -661,6 +660,7 @@ void Landscape::generatePatches(void) int patchnum = 0; // initial patch number for cell-based landscape // create patch 0 - the matrix patch (even if there is no matrix) + patchnums.push_back(patchnum); newPatch(patchnum++); // as landscape generator returns cells in a random sequence, first set up all cells @@ -697,6 +697,7 @@ void Landscape::generatePatches(void) pCell = findCell(x, y); if (continuous) { if (iter->value > 0.0) { // habitat + patchnums.push_back(patchnum); pPatch = newPatch(patchnum++); addCellToPatch(pCell, pPatch, iter->value); } @@ -709,6 +710,7 @@ void Landscape::generatePatches(void) addCellToPatch(pCell, patches[0]); } else { // habitat + patchnums.push_back(patchnum); pPatch = newPatch(patchnum++); addCellToPatch(pCell, pPatch); pCell->changeHabIndex(0, 1); @@ -738,6 +740,7 @@ void Landscape::generatePatches(void) // << " i=" << i << " hab=" << hab << " patchnum=" << patchnum // << endl; #endif + patchnums.push_back(patchnum); pPatch = newPatch(patchnum++); pCell = findCell(x, y); addCellToPatch(pCell, pPatch); @@ -777,6 +780,17 @@ void Landscape::generatePatches(void) // << patchCount() << endl; #endif + simParams sim = paramsSim->getSim(); + if (pSpecies->getNumberOfNeutralLoci() > 0 && (sim.outputWCFstat || sim.outputPairwiseFst)) { + + string cellsToSample = pSpecies->getNSampleCellsFst(); + int n = (cellsToSample == "all") ? -9999 : stoi(cellsToSample); + + auto patchesToSample = samplePatches(n, (cellsToSample == "all")); + + pSpecies->setSamplePatchList(patchesToSample); + + } } //--------------------------------------------------------------------------- @@ -810,6 +824,7 @@ void Landscape::allocatePatches(Species* pSpecies) // create the matrix patch patches.push_back(new Patch(0, 0)); Patch* matrixPatch = patches[0]; + patchnums.push_back(0); #if RSDEBUG //DEBUGLOG << "Landscape::allocatePatches(): npatches=" << npatches // << " N patches=" << (int)patches.size() << endl; @@ -842,6 +857,7 @@ void Landscape::allocatePatches(Species* pSpecies) #endif } if (habK > 0.0) { // cell is suitable - create a patch for it + patchnums.push_back(patchnum); pPatch = newPatch(patchnum++); addCellToPatch(pCell, pPatch); } @@ -877,6 +893,7 @@ void Landscape::allocatePatches(Species* pSpecies) #endif } if (habK > 0.0) { // cell is suitable - create a patch for it + patchnums.push_back(patchnum); pPatch = newPatch(patchnum++); addCellToPatch(pCell, pPatch); } @@ -912,6 +929,7 @@ void Landscape::allocatePatches(Species* pSpecies) #endif } if (habK > 0.0) { // cell is suitable (at some time) - create a patch for it + patchnums.push_back(patchnum); pPatch = newPatch(patchnum++); addCellToPatch(pCell, pPatch); } @@ -926,8 +944,21 @@ void Landscape::allocatePatches(Species* pSpecies) } // end of switch (rasterType) + simParams sim = paramsSim->getSim(); + if (pSpecies->getNumberOfNeutralLoci() > 0 && (sim.outputWCFstat || sim.outputPairwiseFst)) { + + string cellsToSample = pSpecies->getNSampleCellsFst(); + int n = (cellsToSample == "all") ? -9999 : stoi(cellsToSample); + + auto patchesToSample = samplePatches(n, (cellsToSample == "all")); + + pSpecies->setSamplePatchList(patchesToSample); + + } + + #if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): finished, N patches = " << (int)patches.size() << endl; + //DEBUGLOG << "Landscape::allocatePatches(): finished, N patches = " << (int)patches.size() << endl; #endif } @@ -1046,6 +1077,33 @@ Patch* Landscape::findPatch(int num) { return 0; } +set Landscape::samplePatches(int n, bool all) { + + vector sampledPatches; + vector allPatches; + + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) + allPatches.push_back(patches[i]->getPatchNum()); + + + if (!all) { + + auto rng = pRandom->getRNG(); + + sample(allPatches.begin(), allPatches.end(), std::back_inserter(sampledPatches), + n, rng); + + } + else sampledPatches = allPatches; + + set patchIds; + copy(sampledPatches.begin(), sampledPatches.end(), inserter(patchIds, patchIds.end())); + + return patchIds; + +} + void Landscape::resetPatchPopns(void) { int npatches = (int)patches.size(); for (int i = 0; i < npatches; i++) { @@ -1437,16 +1495,16 @@ int Landscape::readLandChange(int filenum, bool costs) return 171; } #endif - if (patchModel) { - pfloat = badpfloat; + if (patchModel) { + pfloat = badpfloat; #if RS_RCPP if (pfile >> pfloat) { #else - pfile >> pfloat; + pfile >> pfloat; #endif - p = (int)pfloat; + p = (int)pfloat; #if RS_RCPP - } + } else { // corrupt file stream #if RS_RCPP && !R_CMD @@ -1461,16 +1519,16 @@ int Landscape::readLandChange(int filenum, bool costs) } #endif } - if (costs) { - cfloat = badcfloat; + if (costs) { + cfloat = badcfloat; #if RS_RCPP if (cfile >> cfloat) { #else - cfile >> cfloat; + cfile >> cfloat; #endif - c = (int)cfloat; + c = (int)cfloat; #if RS_RCPP - } + } else { // corrupt file stream #if RS_RCPP && !R_CMD @@ -1486,60 +1544,60 @@ int Landscape::readLandChange(int filenum, bool costs) #endif } #if RSDEBUG - //DebugGUI(("Landscape::readLandscape(): x=" + Int2Str(x) + " y=" + Int2Str(y) - // + " h=" + Int2Str(h) + " p=" + Int2Str(p) - //).c_str()); + //DebugGUI(("Landscape::readLandscape(): x=" + Int2Str(x) + " y=" + Int2Str(y) + // + " h=" + Int2Str(h) + " p=" + Int2Str(p) + //).c_str()); #endif - if (cells[y][x] != 0) { // not a no data cell (in initial landscape) - if (h == habnodata) { // invalid no data cell in change map - hfile.close(); hfile.clear(); - return 36; - } - else { - if (h < 0 || (sim.batchMode && (h < 1 || h > nHabMax))) { - // invalid habitat code - hfile.close(); hfile.clear(); - if (patchModel) { pfile.close(); pfile.clear(); } - return 33; - } - else { - addHabCode(h); - cells[y][x]->setHabIndex(h); - } - } - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code + if (cells[y][x] != 0) { // not a no data cell (in initial landscape) + if (h == habnodata) { // invalid no data cell in change map + hfile.close(); hfile.clear(); + return 36; + } + else { + if (h < 0 || (sim.batchMode && (h < 1 || h > nHabMax))) { + // invalid habitat code + hfile.close(); hfile.clear(); + if (patchModel) { pfile.close(); pfile.clear(); } + return 33; + } + else { + addHabCode(h); + cells[y][x]->setHabIndex(h); + } + } + if (patchModel) { + if (p < 0 || p == pchnodata) { // invalid patch code #if RS_RCPP && !R_CMD if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; #endif - hfile.close(); hfile.clear(); - pfile.close(); pfile.clear(); - return 34; - } - else { - patchChgMatrix[y][x][2] = p; - if (p > 0 && !existsPatch(p)) { - addPatchNum(p); - newPatch(pchseq++, p); + hfile.close(); hfile.clear(); + pfile.close(); pfile.clear(); + return 34; + } + else { + patchChgMatrix[y][x][2] = p; + if (p > 0 && !existsPatch(p)) { + addPatchNum(p); + newPatch(pchseq++, p); + } + } + } + if (costs) { + if (c < 1) { // invalid cost + hfile.close(); hfile.clear(); + if (pfile.is_open()) { + pfile.close(); pfile.clear(); + } + return 38; + } + else { + costsChgMatrix[y][x][2] = c; + } + } } } } - if (costs) { - if (c < 1) { // invalid cost - hfile.close(); hfile.clear(); - if (pfile.is_open()) { - pfile.close(); pfile.clear(); - } - return 38; - } - else { - costsChgMatrix[y][x][2] = c; - } - } - } - } - } #if RS_RCPP hfile >> hfloat; if (!hfile.eof()) EOFerrorR("habitatchgfile"); @@ -1581,16 +1639,16 @@ int Landscape::readLandChange(int filenum, bool costs) return 172; } #endif - if (patchModel) { - pfloat = badpfloat; + if (patchModel) { + pfloat = badpfloat; #if RS_RCPP if (pfile >> pfloat) { #else - pfile >> pfloat; + pfile >> pfloat; #endif - p = (int)pfloat; + p = (int)pfloat; #if RS_RCPP - } + } else { // corrupt file stream #if RS_RCPP && !R_CMD @@ -1605,16 +1663,16 @@ int Landscape::readLandChange(int filenum, bool costs) } #endif } - if (costs) { - cfloat = badcfloat; + if (costs) { + cfloat = badcfloat; #if RS_RCPP if (cfile >> cfloat) { #else - cfile >> cfloat; + cfile >> cfloat; #endif - c = (int)cfloat; + c = (int)cfloat; #if RS_RCPP - } + } else { // corrupt file stream #if RS_RCPP && !R_CMD @@ -1630,56 +1688,56 @@ int Landscape::readLandChange(int filenum, bool costs) #endif } #if RSDEBUG - //MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) - // + " p=" + Int2Str(p)).c_str()); + //MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) + // + " p=" + Int2Str(p)).c_str()); #endif - if (cells[y][x] != 0) { // not a no data cell (in initial landscape) - if (h == habnodata) { // invalid no data cell in change map - hfile.close(); hfile.clear(); - if (patchModel) { pfile.close(); pfile.clear(); } - return 36; - } - else { - if (hfloat < 0.0 || hfloat > 100.0) { // invalid quality score - hfile.close(); hfile.clear(); - if (patchModel) { pfile.close(); pfile.clear(); } - return 37; - } - else { - cells[y][x]->setHabitat(hfloat); - } - } - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code + if (cells[y][x] != 0) { // not a no data cell (in initial landscape) + if (h == habnodata) { // invalid no data cell in change map + hfile.close(); hfile.clear(); + if (patchModel) { pfile.close(); pfile.clear(); } + return 36; + } + else { + if (hfloat < 0.0 || hfloat > 100.0) { // invalid quality score + hfile.close(); hfile.clear(); + if (patchModel) { pfile.close(); pfile.clear(); } + return 37; + } + else { + cells[y][x]->setHabitat(hfloat); + } + } + if (patchModel) { + if (p < 0 || p == pchnodata) { // invalid patch code #if RS_RCPP && !R_CMD if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; #endif - hfile.close(); hfile.clear(); - pfile.close(); pfile.clear(); - return 34; - } - else { - patchChgMatrix[y][x][2] = p; - if (p > 0 && !existsPatch(p)) { - addPatchNum(p); - newPatch(pchseq++, p); + hfile.close(); hfile.clear(); + pfile.close(); pfile.clear(); + return 34; + } + else { + patchChgMatrix[y][x][2] = p; + if (p > 0 && !existsPatch(p)) { + addPatchNum(p); + newPatch(pchseq++, p); + } + } } - } - } - if (costs) { - if (c < 1) { // invalid cost - hfile.close(); hfile.clear(); - if (pfile.is_open()) { - pfile.close(); pfile.clear(); + if (costs) { + if (c < 1) { // invalid cost + hfile.close(); hfile.clear(); + if (pfile.is_open()) { + pfile.close(); pfile.clear(); + } + return 38; + } + else { + costsChgMatrix[y][x][2] = c; + } } - return 38; } - else { - costsChgMatrix[y][x][2] = c; - } - } - } } } #if RS_RCPP @@ -1698,8 +1756,8 @@ int Landscape::readLandChange(int filenum, bool costs) #endif break; -default: - break; + default: + break; } if (hfile.is_open()) { hfile.close(); hfile.clear(); } @@ -1968,10 +2026,8 @@ bool Landscape::inInitialDist(Species* pSpecies, locn loc) { void Landscape::deleteDistribution(Species* pSpecies) { // WILL NEED TO SELECT DISTRIBUTION FOR CORRECT SPECIES ... - // ... CURRENTLY IT IS THE ONLY ONE ... - // ... FOR MULTIPLE SPECIES IT MAY BE BETTER TO USE A DYNAMIC ARRAY FOR - // SPECIES DISTRIBUTIONS INDEXED BY SPECIES NUMBER, RATHER THAN A VECTOR - if (distns[0] != 0) delete distns[0]; distns.clear(); + // ... CURRENTLY IT IS THE ONLY ONE + if (distns[0] != 0) delete distns[0]; } // Return no. of initial distributions @@ -2103,10 +2159,8 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string // read landscape data from header records of habitat file // NB headers of all files have already been compared - double tmpresol; hfile >> header >> ncols >> header >> nrows >> header >> minEast >> header >> minNorth - >> header >> tmpresol >> header >> habnodata; - resol = (int)tmpresol; + >> header >> resol >> header >> habnodata; #if RS_RCPP if (!hfile.good()) { @@ -2209,68 +2263,68 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string if (patchModel) { pfile.close(); pfile.clear(); - } + } return 135; } #endif #if RSDEBUG - //DebugGUI(("Landscape::readLandscape(): x=" + Int2Str(x) + " y=" + Int2Str(y) - // + " h=" + Int2Str(h) + " p=" + Int2Str(p) - //).c_str()); + //DebugGUI(("Landscape::readLandscape(): x=" + Int2Str(x) + " y=" + Int2Str(y) + // + " h=" + Int2Str(h) + " p=" + Int2Str(p) + //).c_str()); #endif - if (h == habnodata) - addNewCellToLand(x, y, -1); // add cell only to landscape - else { + if (h == habnodata) + addNewCellToLand(x, y, -1); // add cell only to landscape + else { - // THERE IS AN ANOMALY HERE - CURRENTLY HABITAT 0 IS OK FOR GUI VERSION BUT - // NOT ALLOWED FOR BATCH VERSION (HABITATS MUST BE 1...n) - // SHOULD WE MAKE THE TWO VERSIONS AGREE? ... + // THERE IS AN ANOMALY HERE - CURRENTLY HABITAT 0 IS OK FOR GUI VERSION BUT + // NOT ALLOWED FOR BATCH VERSION (HABITATS MUST BE 1...n) + // SHOULD WE MAKE THE TWO VERSIONS AGREE? ... - if (h < 0 || (sim.batchMode && (h < 1 || h > nHabMax))) { - // invalid habitat code + if (h < 0 || (sim.batchMode && (h < 1 || h > nHabMax))) { + // invalid habitat code #if RS_RCPP && !R_CMD Rcpp::Rcout << "Found invalid habitat code." << std::endl; #endif - hfile.close(); hfile.clear(); - if (patchModel) { - pfile.close(); pfile.clear(); - } - return 13; - } - else { - addHabCode(h); - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code + hfile.close(); hfile.clear(); + if (patchModel) { + pfile.close(); pfile.clear(); + } + return 13; + } + else { + addHabCode(h); + if (patchModel) { + if (p < 0 || p == pchnodata) { // invalid patch code #if RS_RCPP && !R_CMD if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; #endif - hfile.close(); hfile.clear(); - pfile.close(); pfile.clear(); - return 14; - } - if (p == 0) { // cell is in the matrix - addNewCellToPatch(0, x, y, h); - } - else { - if (existsPatch(p)) { - pPatch = findPatch(p); - addNewCellToPatch(pPatch, x, y, h); - // addNewCellToPatch(findPatch(p),x,y,h); + hfile.close(); hfile.clear(); + pfile.close(); pfile.clear(); + return 14; + } + if (p == 0) { // cell is in the matrix + addNewCellToPatch(0, x, y, h); + } + else { + if (existsPatch(p)) { + pPatch = findPatch(p); + addNewCellToPatch(pPatch, x, y, h); + // addNewCellToPatch(findPatch(p),x,y,h); + } + else { + pPatch = newPatch(seq++, p); + addNewCellToPatch(pPatch, x, y, h); + } + } } - else { - pPatch = newPatch(seq++, p); - addNewCellToPatch(pPatch, x, y, h); + else { // cell-based model + // add cell to landscape (patches created later) + addNewCellToLand(x, y, h); } } } - else { // cell-based model - // add cell to landscape (patches created later) - addNewCellToLand(x, y, h); - } - } - } } } #if RS_RCPP @@ -2282,27 +2336,27 @@ if (patchModel) if (!pfile.eof()) EOFerrorR(pchfile); } #endif -break; + break; -case 1: // multiple % cover - for (int y = dimY - 1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { - hfloat = badhfloat; + case 1: // multiple % cover + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + hfloat = badhfloat; #if RS_RCPP if (hfile >> hfloat) { #else - hfile >> hfloat; + hfile >> hfloat; #endif - h = (int)hfloat; - if (fileNum == 0) { // first habitat cover layer - if (patchModel) { - pfloat = badpfloat; + h = (int)hfloat; + if (fileNum == 0) { // first habitat cover layer + if (patchModel) { + pfloat = badpfloat; #if RS_RCPP if (pfile >> pfloat) { #else - pfile >> pfloat; + pfile >> pfloat; #endif - p = (int)pfloat; + p = (int)pfloat; #if RS_RCPP } else { @@ -2318,76 +2372,76 @@ case 1: // multiple % cover return 135; } #endif - } //end if patchmodel + } //end if patchmodel #if RSDEBUG //MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) // + " p=" + Int2Str(p)).c_str()); #endif - if (h == habnodata) { - addNewCellToLand(x, y, -1); // add cell only to landscape - } - else { - if (hfloat < 0.0 || hfloat > 100.0) { // invalid cover score + if (h == habnodata) { + addNewCellToLand(x, y, -1); // add cell only to landscape + } + else { + if (hfloat < 0.0 || hfloat > 100.0) { // invalid cover score #if RS_RCPP && !R_CMD Rcpp::Rcout << "Found invalid habitat cover score." << std::endl; #endif - hfile.close(); hfile.clear(); - if (patchModel) { - pfile.close(); pfile.clear(); - } - return 17; - } - else { - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code + hfile.close(); hfile.clear(); + if (patchModel) { + pfile.close(); pfile.clear(); + } + return 17; + } + else { + if (patchModel) { + if (p < 0 || p == pchnodata) { // invalid patch code #if RS_RCPP && !R_CMD if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; #endif - hfile.close(); hfile.clear(); - pfile.close(); pfile.clear(); - return 14; - } - if (p == 0) { // cell is in the matrix - addNewCellToPatch(0, x, y, hfloat); - } - else { - if (existsPatch(p)) { - pPatch = findPatch(p); - addNewCellToPatch(pPatch, x, y, hfloat); - // addNewCellToPatch(findPatch(p),x,y,hfloat); + hfile.close(); hfile.clear(); + pfile.close(); pfile.clear(); + return 14; + } + if (p == 0) { // cell is in the matrix + addNewCellToPatch(0, x, y, hfloat); + } + else { + if (existsPatch(p)) { + pPatch = findPatch(p); + addNewCellToPatch(pPatch, x, y, hfloat); + // addNewCellToPatch(findPatch(p),x,y,hfloat); + } + else { + pPatch = newPatch(seq++, p); + addNewCellToPatch(pPatch, x, y, hfloat); + } + } } - else { - pPatch = newPatch(seq++, p); - addNewCellToPatch(pPatch, x, y, hfloat); + else { // cell-based model + // add cell to landscape (patches created later) + addNewCellToLand(x, y, hfloat); } } } - else { // cell-based model - // add cell to landscape (patches created later) - addNewCellToLand(x, y, hfloat); - } } - } - } -else { // additional habitat cover layers - if (h != habnodata) { - if (hfloat < 0.0 || hfloat > 100.0) { // invalid cover score + else { // additional habitat cover layers + if (h != habnodata) { + if (hfloat < 0.0 || hfloat > 100.0) { // invalid cover score #if RS_RCPP && !R_CMD Rcpp::Rcout << "Found invalid habitat cover score." << std::endl; #endif - hfile.close(); hfile.clear(); - if (patchModel) { - pfile.close(); pfile.clear(); - } - return 17; - } - else { - cells[y][x]->setHabitat(hfloat); - } - } // end of h != habnodata -} + hfile.close(); hfile.clear(); + if (patchModel) { + pfile.close(); pfile.clear(); + } + return 17; + } + else { + cells[y][x]->setHabitat(hfloat); + } + } // end of h != habnodata + } #if RS_RCPP } else { // couldn't read from hfile @@ -2406,9 +2460,9 @@ else { // couldn't read from hfile } #endif + } } - } - habIndexed = true; // habitats are already numbered 1...n in correct order + habIndexed = true; // habitats are already numbered 1...n in correct order #if RS_RCPP hfile >> hfloat; if (!hfile.eof()) EOFerrorR(habfile); @@ -2418,19 +2472,19 @@ else { // couldn't read from hfile if (!pfile.eof()) EOFerrorR(pchfile); } #endif - break; + break; -case 2: // habitat quality - if (fileNum > 0) return 19; // error condition - should not occur - for (int y = dimY - 1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { - hfloat = badhfloat; + case 2: // habitat quality + if (fileNum > 0) return 19; // error condition - should not occur + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + hfloat = badhfloat; #if RS_RCPP if (hfile >> hfloat) { #else - hfile >> hfloat; + hfile >> hfloat; #endif - h = (int)hfloat; + h = (int)hfloat; #if RS_RCPP } else { @@ -2441,7 +2495,7 @@ case 2: // habitat quality StreamErrorR(habfile); hfile.close(); hfile.clear(); - if (patchModel) { + if (patchModel) { pfile.close(); pfile.clear(); } @@ -2449,13 +2503,13 @@ case 2: // habitat quality } #endif if (patchModel) { - pfloat = badpfloat; + pfloat = badpfloat; #if RS_RCPP if (pfile >> pfloat) { #else - pfile >> pfloat; + pfile >> pfloat; #endif - p = (int)pfloat; + p = (int)pfloat; #if RS_RCPP } else { @@ -2471,60 +2525,60 @@ case 2: // habitat quality return 135; } #endif - } + } #if RSDEBUG - //MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) - // + " p=" + Int2Str(p)).c_str()); + //MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) + // + " p=" + Int2Str(p)).c_str()); #endif - if (h == habnodata) { - addNewCellToLand(x, y, -1); // add cell only to landscape - } - else { - if (hfloat < 0.0 || hfloat > 100.0) { // invalid quality score + if (h == habnodata) { + addNewCellToLand(x, y, -1); // add cell only to landscape + } + else { + if (hfloat < 0.0 || hfloat > 100.0) { // invalid quality score #if RS_RCPP && !R_CMD Rcpp::Rcout << "Found invalid habitat quality score." << std::endl; #endif - hfile.close(); hfile.clear(); - if (patchModel) { - pfile.close(); pfile.clear(); - } - return 17; - } - else { - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code + hfile.close(); hfile.clear(); + if (patchModel) { + pfile.close(); pfile.clear(); + } + return 17; + } + else { + if (patchModel) { + if (p < 0 || p == pchnodata) { // invalid patch code #if RS_RCPP && !R_CMD if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; #endif - hfile.close(); hfile.clear(); - pfile.close(); pfile.clear(); - return 14; - } - if (p == 0) { // cell is in the matrix - addNewCellToPatch(0, x, y, hfloat); - } - else { - if (existsPatch(p)) { - pPatch = findPatch(p); - addNewCellToPatch(pPatch, x, y, hfloat); - // addNewCellToPatch(findPatch(p),x,y,hfloat); - } - else { - addPatchNum(p); - pPatch = newPatch(seq++, p); - addNewCellToPatch(pPatch, x, y, hfloat); + hfile.close(); hfile.clear(); + pfile.close(); pfile.clear(); + return 14; + } + if (p == 0) { // cell is in the matrix + addNewCellToPatch(0, x, y, hfloat); + } + else { + if (existsPatch(p)) { + pPatch = findPatch(p); + addNewCellToPatch(pPatch, x, y, hfloat); + // addNewCellToPatch(findPatch(p),x,y,hfloat); + } + else { + addPatchNum(p); + pPatch = newPatch(seq++, p); + addNewCellToPatch(pPatch, x, y, hfloat); + } + } + } + else { // cell-based model + // add cell to landscape (patches created later) + addNewCellToLand(x, y, hfloat); + } } } } - else { // cell-based model - // add cell to landscape (patches created later) - addNewCellToLand(x, y, hfloat); - } - } - } } - } #if RS_RCPP hfile >> hfloat; if (!hfile.eof()) EOFerrorR(habfile); @@ -2534,10 +2588,10 @@ case 2: // habitat quality if (!pfile.eof()) EOFerrorR(pchfile); } #endif - break; + break; -default: - break; + default: + break; } // end switch(rasterType) if (hfile.is_open()) { hfile.close(); hfile.clear(); } @@ -2577,7 +2631,6 @@ int Landscape::readCosts(string fname) wstring header; #else string header; -#endif Cell* pCell; #if !RS_RCPP simView v = paramsSim->getViews(); @@ -2587,10 +2640,10 @@ int Landscape::readCosts(string fname) #if RSDEBUG #if BATCH - //DEBUGLOG << "Landscape::readCosts(): fname=" << fname << endl; + DEBUGLOG << "Landscape::readCosts(): fname=" << fname << endl; #endif #endif - // open cost file + // open cost file #if !RS_RCPP || RSWIN64 costs.open(fname.c_str()); #else @@ -2628,10 +2681,8 @@ int Landscape::readCosts(string fname) costs.close(); costs.clear(); return -1; } - double tmpresolCost; costs >> maxXcost >> header >> maxYcost >> header >> minLongCost; - costs >> header >> minLatCost >> header >> tmpresolCost >> header >> NODATACost; - resolCost = (int)tmpresolCost; + costs >> header >> minLatCost >> header >> resolCost >> header >> NODATACost; #if !RS_RCPP MemoLine("Loading costs map. Please wait..."); @@ -2658,28 +2709,28 @@ int Landscape::readCosts(string fname) return -181; } #endif - if (hc < 1 && hc != NODATACost) { + if (hc < 1 && hc != NODATACost) { #if RSDEBUG #if BATCH - // DEBUGLOG << "Landscape::readCosts(): x=" << x << " y=" << y - // << " fcost=" << fcost << " hc=" << hc - // << endl; + // DEBUGLOG << "Landscape::readCosts(): x=" << x << " y=" << y + // << " fcost=" << fcost << " hc=" << hc + // << endl; #endif #endif #if RS_RCPP && !R_CMD Rcpp::Rcout << "Cost map my only contain values of 1 or higher, but found " << fcost << "." << endl; #endif - // error - zero / negative cost not allowed + // error - zero / negative cost not allowed // MessageDlg("Error in the costs map file : zero or negative cost detected." // , mtError, TMsgDlgButtons() << mbOK,0); - costs.close(); costs.clear(); - return -999; - } - pCell = findCell(x, y); - if (pCell != 0) { // not no-data cell - pCell->setCost(hc); - if (hc > maxcost) maxcost = hc; - } + costs.close(); costs.clear(); + return -999; + } + pCell = findCell(x, y); + if (pCell != 0) { // not no-data cell + pCell->setCost(hc); + if (hc > maxcost) maxcost = hc; + } } } #if RS_RCPP @@ -2688,15 +2739,15 @@ if (costs.eof()) { #if RS_RCPP && !R_CMD Rcpp::Rcout << "Costs map loaded." << endl; #endif -} + } else EOFerrorR(fname); #else -MemoLine("Costs map loaded."); + MemoLine("Costs map loaded."); #endif -costs.close(); costs.clear(); + costs.close(); costs.clear(); -return maxcost; + return maxcost; } diff --git a/Landscape.h b/Landscape.h index c82dc7a..d73ffbd 100644 --- a/Landscape.h +++ b/Landscape.h @@ -65,18 +65,14 @@ Authors: Greta Bocedi & Steve Palmer, University of Aberdeen - Last updated: 2 December 2021 by Steve Palmer + Last updated: 28 July 2021 by Greta Bocedi ------------------------------------------------------------------------------*/ #ifndef LandscapeH #define LandscapeH - //#include - //#include #include #include -//#include -//#include #include using namespace std; @@ -239,7 +235,7 @@ class Landscape { void setCellArray(void); void addPatchNum(int); - void generatePatches(void); // create an artificial landscape + void generatePatches(Species*); // create an artificial landscape void allocatePatches(Species*); // create patches for a cell-based landscape Patch* newPatch( int // patch sequential no. (id no. is set to equal sequential no.) @@ -294,6 +290,7 @@ class Landscape { Patch* findPatch( int // Patch id no. ); + set samplePatches(int n, bool all); int checkTotalCover(void); void resetPatchPopns(void); void updateCarryingCapacity( diff --git a/Model.cpp b/Model.cpp index c14c7ce..7caed2b 100644 --- a/Model.cpp +++ b/Model.cpp @@ -25,7 +25,7 @@ #include "Model.h" ofstream outPar; - +using namespace std::chrono; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #if RS_RCPP && !R_CMD @@ -72,6 +72,7 @@ int RunModel(Landscape* pLandscape, int seqsim) // NB this is an overhead here, but is necessary in case the identity of // suitable habitats has been changed from one simulation to another (GUI or batch) // substantial time savings may result during simulation in certain landscapes + // if using neutral markers, set up patches to sample from pLandscape->allocatePatches(pSpecies); } pComm = new Community(pLandscape); // set up community @@ -127,6 +128,9 @@ int RunModel(Landscape* pLandscape, int seqsim) pLandscape->resetVisits(); } + if (sim.fixReplicateSeed) { + pRandom->fixNewSeed(rep); + } patchChange patchchange; costChange costchange; int npatchchanges = pLandscape->numPatchChanges(); @@ -151,24 +155,16 @@ int RunModel(Landscape* pLandscape, int seqsim) #if RSDEBUG DEBUGLOG << "RunModel(): finished resetting landscape" << endl << endl; #endif - pLandscape->generatePatches(); - //#if VCL + pLandscape->generatePatches(pSpecies); if (v.viewLand || sim.saveMaps) { pLandscape->setLandMap(); pLandscape->drawLandscape(rep, 0, ppLand.landNum); } - //#endif - //#if BATCH - // if (sim.saveMaps) { - // pLandscape->drawLandscape(rep,0,ppLand.landNum); - // } - //#endif #if RSDEBUG DEBUGLOG << endl << "RunModel(): finished generating patches" << endl; #endif pComm = new Community(pLandscape); // set up community // set up a sub-community associated with each patch (incl. the matrix) - // pLandscape->updateCarryingCapacity(pSpecies,0); pLandscape->updateCarryingCapacity(pSpecies, 0, 0); patchData ppp; int npatches = pLandscape->patchCount(); @@ -250,6 +246,12 @@ int RunModel(Landscape* pLandscape, int seqsim) MemoLine("UNABLE TO OPEN CONNECTIVITY FILE"); filesOK = false; } + if (sim.outputWCFstat) { // open neutral genetics file + if (!pComm->openWCFstatFile(pSpecies, ppLand.landNum)) { + MemoLine("UNABLE TO OPEN NEUTRAL GENETICS FILE"); + filesOK = false; + } + } } #if RSDEBUG DEBUGLOG << "RunModel(): completed opening output files" << endl; @@ -273,6 +275,9 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->outTraitsRowsHeaders(pSpecies, -999); if (sim.outConnect && ppLand.patchModel) pLandscape->outConnectHeaders(-999); + if (sim.outputWCFstat) { + pComm->openWCFstatFile(pSpecies, -999); + } #if RS_RCPP && !R_CMD return Rcpp::List::create(Rcpp::Named("Errors") = 666); #else @@ -307,6 +312,7 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->initialise(pSpecies, -1); // } bool updateland = false; + bool cloneFromColdStorage = false; int landIx = 0; // landscape change index #if RSDEBUG @@ -324,13 +330,12 @@ int RunModel(Landscape* pLandscape, int seqsim) // open a new individuals file for each replicate if (sim.outInds) pComm->outInds(rep, 0, 0, ppLand.landNum); - // open a new genetics file for each replicate - if (sim.outGenetics) { - pComm->outGenetics(rep, 0, 0, ppLand.landNum); - if (!dem.stageStruct && sim.outStartGenetic == 0) { - // write genetic data for initialised individuals of non-strucutred population - pComm->outGenetics(rep, 0, 0, -1); - } + // open a new genetics file for each replicate for per locus and pairwise stats + if (sim.outputPerLocusWCFstat) { + pComm->openWCPerLocusFstatFile(pSpecies, pLandscape, ppLand.landNum, rep); + } + if (sim.outputPairwiseFst) { + pComm->openPairwiseFSTFile(pSpecies, pLandscape, ppLand.landNum, rep); } #if RSDEBUG // output initialised Individuals @@ -418,6 +423,22 @@ int RunModel(Landscape* pLandscape, int seqsim) } } } + + if (yr == sim.storeIndsYr) { //implement after first change only + + if (sim.fionaOptions == 1) + pSpecies->turnOffMutations(); + + if (sim.fionaOptions == 2) { + pComm->addIndividualsToColdStorage(); + cloneFromColdStorage = true; + } + + if (sim.fionaOptions == 3) { + pComm->createAverageTraitIndividualAndStore(pSpecies, pLandscape); + cloneFromColdStorage = true; + } + } // environmental gradient, stochasticity & local extinction // or dynamic landscape updateland = false; @@ -519,7 +540,6 @@ int RunModel(Landscape* pLandscape, int seqsim) pLandscape->updateCarryingCapacity(pSpecies, yr, landIx); } - if (sim.outConnect && ppLand.patchModel) pLandscape->resetConnectMatrix(); @@ -600,7 +620,7 @@ int RunModel(Landscape* pLandscape, int seqsim) } // reproduction - pComm->reproduction(yr); + pComm->reproduction(yr, cloneFromColdStorage); if (dem.stageStruct) { if (sstruct.survival == 0) { // at reproduction @@ -656,9 +676,15 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outInds && yr >= sim.outStartInd && yr % sim.outIntInd == 0) pComm->outInds(rep, yr, gen, -1); // output Genetics - if (sim.outGenetics && yr >= sim.outStartGenetic && yr % sim.outIntGenetic == 0) - pComm->outGenetics(rep, yr, gen, -1); + //auto start = high_resolution_clock::now(); + if ((sim.outputWCFstat || sim.outputPairwiseFst) && yr % sim.outputGeneticInterval == 0) { + if (pLandscape) pComm->sampleIndividuals(pSpecies); + pComm->outNeutralGenetics(pSpecies, rep, yr, gen, sim.outputPerLocusWCFstat, sim.outputPairwiseFst); + } + //auto stop = high_resolution_clock::now(); + // auto duration = duration_cast(stop - start); + //cout << "genetic output took " << duration.count() << endl; // survival part 1 if (dem.stageStruct) { // if (sstruct.survival != 2) { // at reproduction or between reproduction events @@ -826,8 +852,10 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outInds) // close Individuals output file pComm->outInds(rep, 0, 0, -999); - if (sim.outGenetics) // close Genetics output file - pComm->outGenetics(rep, 0, 0, -999); + if (sim.outputPerLocusWCFstat) //close per locus file + pComm->openWCPerLocusFstatFile(pSpecies, pLandscape, -999, rep); + if (sim.outputPairwiseFst) //close per locus file + pComm->openPairwiseFSTFile(pSpecies, pLandscape, -999, rep); if (sim.saveVisits) { pLandscape->outVisits(rep, ppLand.landNum); @@ -873,7 +901,9 @@ int RunModel(Landscape* pLandscape, int seqsim) // close Individuals & Genetics output files if open // they can still be open if the simulation was stopped by the user if (sim.outInds) pComm->outInds(0, 0, 0, -999); - if (sim.outGenetics) pComm->outGenetics(0, 0, 0, -999); + if (sim.outputWCFstat) pComm->openWCFstatFile(pSpecies, -999); + if (sim.outputPerLocusWCFstat) pComm->openWCPerLocusFstatFile(pSpecies, pLandscape, -999, 0); + if (sim.outputPairwiseFst) pComm->openPairwiseFSTFilei(pSpecies, pLandscape, -999, 0); MemoLine("Deleting community..."); delete pComm; pComm = 0; @@ -946,12 +976,7 @@ void PreReproductionOutput(Landscape* pLand, Community* pComm, int rep, int yr, //DEBUGLOG << "PreReproductionOutput(): 22222 " << endl; #endif -//emigCanvas ecanv; -//trfrCanvas tcanv; traitCanvas tcanv; - //for (int i = 0; i < 6; i++) { - // ecanv.pcanvas[i] = 0; tcanv.pcanvas[i] = 0; - //} for (int i = 0; i < NTRAITS; i++) { tcanv.pcanvas[i] = 0; } @@ -959,9 +984,6 @@ void PreReproductionOutput(Landscape* pLand, Community* pComm, int rep, int yr, // trait outputs and visualisation if (v.viewTraits) { - // ecanv = SetupEmigCanvas(); - // tcanv = SetupTrfrCanvas(); - // tcanv = SetupTraitCanvas(v.viewGrad); tcanv = SetupTraitCanvas(); } @@ -969,7 +991,6 @@ void PreReproductionOutput(Landscape* pLand, Community* pComm, int rep, int yr, || ((sim.outTraitsCells && yr >= sim.outStartTraitCell && yr % sim.outIntTraitCell == 0) || (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0))) { - // pComm->outTraits(ecanv,tcanv,pSpecies,rep,yr,gen); pComm->outTraits(tcanv, pSpecies, rep, yr, gen); } @@ -1470,7 +1491,6 @@ void OutParameters(Landscape* pLandscape) } emigTraits ep0, ep1; - emigParams eparams0, eparams1; string sexdept = "SEX-DEPENDENT: "; string stgdept = "STAGE-DEPENDENT: "; string indvar = "INDIVIDUAL VARIABILITY: "; @@ -1496,37 +1516,13 @@ void OutParameters(Landscape* pLandscape) } else { // !emig.stgDep outPar << stgdept << "no" << endl; - outPar << indvar; - if (emig.indVar) { - eparams0 = pSpecies->getEmigParams(0, 0); - eparams1 = pSpecies->getEmigParams(0, 1); - outPar << "yes" << endl; - if (dem.stageStruct) { - outPar << emigstage << emig.emigStage << endl; - } - outPar << "D0 females: mean " << eparams0.d0Mean << " s.d. " << eparams0.d0SD - << " scaling factor " << eparams0.d0Scale << endl; - outPar << "D0 males: mean " << eparams1.d0Mean << " s.d. " << eparams1.d0SD - << " scaling factor " << eparams1.d0Scale << endl; - outPar << "Alpha females: mean " << eparams0.alphaMean << " s.d. " << eparams0.alphaSD - << " scaling factor " << eparams0.alphaScale << endl; - outPar << "Alpha males: mean " << eparams1.alphaMean << " s.d. " << eparams1.alphaSD - << " scaling factor " << eparams1.alphaScale << endl; - outPar << "Beta females: mean " << eparams0.betaMean << " s.d. " << eparams0.betaSD - << " scaling factor " << eparams0.betaScale << endl; - outPar << "Beta males: mean " << eparams1.betaMean << " s.d. " << eparams1.betaSD - << " scaling factor " << eparams1.betaScale << endl; - } - else { - outPar << "no" << endl; - ep0 = pSpecies->getEmigTraits(0, 0); - ep1 = pSpecies->getEmigTraits(0, 1); - outPar << "D0: females " << ep0.d0 << " males " << ep1.d0 << endl; - outPar << "alpha: females " << ep0.alpha << " males " << ep1.alpha << endl; - outPar << "beta: females " << ep0.beta << " males " << ep1.beta << endl; - } - } + ep0 = pSpecies->getEmigTraits(0, 0); + ep1 = pSpecies->getEmigTraits(0, 1); + outPar << "D0: females " << ep0.d0 << " males " << ep1.d0 << endl; + outPar << "alpha: females " << ep0.alpha << " males " << ep1.alpha << endl; + outPar << "beta: females " << ep0.beta << " males " << ep1.beta << endl; } + } else { // !emig.sexDep outPar << sexdept << "no" << endl; if (emig.stgDep) { @@ -1540,28 +1536,10 @@ void OutParameters(Landscape* pLandscape) } else { // !emig.stgDep outPar << stgdept << "no" << endl; - outPar << indvar; - if (emig.indVar) { - eparams0 = pSpecies->getEmigParams(0, 0); - emigScales scale = pSpecies->getEmigScales(); - outPar << "yes" << endl; - if (dem.stageStruct) { - outPar << emigstage << emig.emigStage << endl; - } - outPar << "D0 mean: " << eparams0.d0Mean << " s.d.: " << eparams0.d0SD - << " scaling factor: " << scale.d0Scale << endl; - outPar << "Alpha mean: " << eparams0.alphaMean << " s.d.: " << eparams0.alphaSD - << " scaling factor: " << scale.alphaScale << endl; - outPar << "Beta mean: " << eparams0.betaMean << " s.d.: " << eparams0.betaSD - << " scaling factor: " << scale.betaScale << endl; - } - else { - outPar << "no" << endl; - ep0 = pSpecies->getEmigTraits(0, 0); - outPar << "D0: " << ep0.d0 << endl; - outPar << "alpha: " << ep0.alpha << endl; - outPar << "beta: " << ep0.beta << endl; - } + ep0 = pSpecies->getEmigTraits(0, 0); + outPar << "D0: " << ep0.d0 << endl; + outPar << "alpha: " << ep0.alpha << endl; + outPar << "beta: " << ep0.beta << endl; } } } @@ -1587,27 +1565,8 @@ void OutParameters(Landscape* pLandscape) } else { // !emig.stgDep outPar << stgdept << "no" << endl; - outPar << indvar; - if (emig.indVar) { - eparams0 = pSpecies->getEmigParams(0, 0); - eparams1 = pSpecies->getEmigParams(0, 1); - emigScales scale = pSpecies->getEmigScales(); - outPar << "yes" << endl; - if (dem.stageStruct) { - outPar << emigstage << emig.emigStage << endl; - } - outPar << initprob << "mean: " << "females " << eparams0.d0Mean - << " males " << eparams1.d0Mean << endl; - outPar << initprob << "s.d.: " << "females " << eparams0.d0SD - << " males " << eparams1.d0SD << endl; - outPar << initprob << "scaling factor: " << scale.d0Scale - << endl; - } - else { - outPar << "no" << endl; - outPar << "EMIGRATION PROB.: \tfemales " << pSpecies->getEmigD0(0, 0) - << "\t males " << pSpecies->getEmigD0(0, 1) << endl; - } + outPar << "EMIGRATION PROB.: \tfemales " << pSpecies->getEmigD0(0, 0) + << "\t males " << pSpecies->getEmigD0(0, 1) << endl; } } else { // !emig.sexDep @@ -1622,22 +1581,7 @@ void OutParameters(Landscape* pLandscape) } else { // !emig.stgDep outPar << stgdept << "no" << endl; - outPar << indvar; - if (emig.indVar) { - eparams0 = pSpecies->getEmigParams(0, 0); - emigScales scale = pSpecies->getEmigScales(); - outPar << "yes" << endl; - if (dem.stageStruct) { - outPar << emigstage << emig.emigStage << endl; - } - outPar << initprob << "mean: " << eparams0.d0Mean << endl; - outPar << initprob << "s.d.: " << eparams0.d0SD << endl; - outPar << initprob << "scaling factor: " << scale.d0Scale << endl; - } - else { - outPar << "no" << endl; - outPar << "EMIGRATION PROB.:\t" << pSpecies->getEmigD0(0, 0) << endl; - } + outPar << "EMIGRATION PROB.:\t" << pSpecies->getEmigD0(0, 0) << endl; } } } @@ -1675,7 +1619,6 @@ void OutParameters(Landscape* pLandscape) outPar << pr << " METHOD: " << move.prMethod << endl; if (!trfr.indVar) outPar << "DIRECTIONAL PERSISTENCE: " << move.dp << endl; outPar << "MEMORY SIZE: " << move.memSize << endl; - //if (!trfr.indVar) outPar << "GOAL BIAS: " << move.gb << endl; outPar << "GOAL TYPE: " << move.goalType << endl; if (!trfr.indVar) { if (move.goalType == 2) { // dispersal bias @@ -1684,23 +1627,7 @@ void OutParameters(Landscape* pLandscape) outPar << "BETA DB: " << move.betaDB << endl; } } - if (trfr.indVar) { - trfrSMSParams s = pSpecies->getSMSParams(0, 0); - outPar << indvar << "yes " << endl; - outPar << "DP mean: " << s.dpMean << " s.d.: " << s.dpSD - << " scaling factor: " << s.dpScale << endl; - outPar << "GB mean: " << s.gbMean << " s.d.: " << s.gbSD - << " scaling factor: " << s.gbScale << endl; - if (move.goalType == 2) { // dispersal bias - outPar << "Alpha DB mean: " << s.alphaDBMean << " s.d.: " << s.alphaDBSD - << " scaling factor: " << s.alphaDBScale << endl; - outPar << "Beta DB mean: " << s.betaDBMean << " s.d.: " << s.betaDBSD - << " scaling factor: " << s.betaDBScale << endl; - } - } - else { - outPar << indvar << "no " << endl; - } + outPar << indvar << "no " << endl; } else { // CRW trfrCRWTraits move = pSpecies->getCRWTraits(); @@ -1708,21 +1635,8 @@ void OutParameters(Landscape* pLandscape) outPar << "CRW" << endl; string lgth = "STEP LENGTH (m) "; string corr = "STEP CORRELATION"; - if (trfr.indVar) { - trfrCRWParams m = pSpecies->getCRWParams(0, 0); - outPar << indvar << "yes" << endl; - outPar << lgth << " mean: " << m.stepLgthMean; - outPar << " s.d.: " << m.stepLgthSD; - outPar << " scaling factor: " << m.stepLScale << endl; - outPar << corr << " mean: " << m.rhoMean; - outPar << " s.d.: " << m.rhoSD; - outPar << " scaling factor: " << m.rhoScale << endl; - } - else { - outPar << indvar << "no" << endl; - outPar << lgth << ": " << move.stepLength << endl; - outPar << corr << ": " << move.rho << endl; - } + outPar << lgth << ": " << move.stepLength << endl; + outPar << corr << ": " << move.rho << endl; } outPar << "STRAIGHTEN PATH AFTER DECISION NOT TO SETTLE: "; if (straigtenPath) outPar << "yes" << endl; @@ -1752,7 +1666,6 @@ void OutParameters(Landscape* pLandscape) string meandist = "MEAN DISTANCE"; string probkern = "PROB. KERNEL I"; trfrKernTraits kern0, kern1; - trfrKernParams k0, k1; outPar << "dispersal kernel" << endl << "TYPE: \t"; if (trfr.twinKern) outPar << "double "; outPar << "negative exponential" << endl; @@ -1776,43 +1689,13 @@ void OutParameters(Landscape* pLandscape) } else { // !trfr.stgDep outPar << stgdept << "no" << endl; - outPar << indvar; - if (trfr.indVar) { - k0 = pSpecies->getKernParams(0, 0); - k1 = pSpecies->getKernParams(0, 1); - outPar << "yes" << endl; - outPar << meandist << " I (mean): \tfemales " << k0.dist1Mean - << " \tmales " << k1.dist1Mean << endl; - outPar << meandist << " I (s.d.): \tfemales " << k0.dist1SD - << " \tmales " << k1.dist1SD << endl; - outPar << meandist << " I (scaling factor): \tfemales " << k0.dist1Scale - << " \tmales " << k1.dist1Scale << endl; - if (trfr.twinKern) - { - outPar << meandist << " II (mean): \tfemales " << k0.dist2Mean - << " \tmales " << k1.dist2Mean << endl; - outPar << meandist << " II (s.d.): \tfemales " << k0.dist2SD - << " \tmales " << k1.dist2SD << endl; - outPar << meandist << " II (scaling factor): \tfemales " << k0.dist2Scale - << " \tmales " << k1.dist2Scale << endl; - outPar << probkern << " (mean): \tfemales " << k0.PKern1Mean - << " \tmales " << k1.PKern1Mean << endl; - outPar << probkern << " (s.d.): \tfemales " << k0.PKern1SD - << " \tmales " << k1.PKern1SD << endl; - outPar << probkern << " (scaling factor): \tfemales " << k0.PKern1Scale - << " \tmales " << k1.PKern1Scale << endl; - } - } - else { - outPar << "no" << endl; - kern0 = pSpecies->getKernTraits(0, 0); - kern1 = pSpecies->getKernTraits(0, 1); - outPar << meandist << " I: \tfemales " << kern0.meanDist1 << " \tmales " << kern1.meanDist1 << endl; - if (trfr.twinKern) - { - outPar << meandist << " II: \tfemales " << kern0.meanDist2 << " \tmales " << kern1.meanDist2 << endl; - outPar << probkern << ": \tfemales " << kern0.probKern1 << " \tmales " << kern1.probKern1 << endl; - } + kern0 = pSpecies->getKernTraits(0, 0); + kern1 = pSpecies->getKernTraits(0, 1); + outPar << meandist << " I: \tfemales " << kern0.meanDist1 << " \tmales " << kern1.meanDist1 << endl; + if (trfr.twinKern) + { + outPar << meandist << " II: \tfemales " << kern0.meanDist2 << " \tmales " << kern1.meanDist2 << endl; + outPar << probkern << ": \tfemales " << kern0.probKern1 << " \tmales " << kern1.probKern1 << endl; } } } @@ -1834,32 +1717,12 @@ void OutParameters(Landscape* pLandscape) } else { // !trfr.stgDep outPar << stgdept << "no" << endl; - outPar << indvar; - if (trfr.indVar) { - k0 = pSpecies->getKernParams(0, 0); - outPar << "yes" << endl; - outPar << meandist << " I (mean): " << k0.dist1Mean - << " \t(s.d.): " << k0.dist1SD - << " \t(scaling factor): " << k0.dist1Scale << endl; - if (trfr.twinKern) - { - outPar << meandist << " II (mean): " << k0.dist2Mean - << " \t(s.d.): " << k0.dist2SD - << " \t(scaling factor): " << k0.dist2Scale << endl; - outPar << probkern << " (mean): " << k0.PKern1Mean - << " \t(s.d.): " << k0.PKern1SD - << " \t(scaling factor): " << k0.PKern1Scale << endl; - } - } - else { - outPar << "no" << endl; - kern0 = pSpecies->getKernTraits(0, 0); - outPar << meandist << " I: \t" << kern0.meanDist1 << endl; - if (trfr.twinKern) - { - outPar << meandist << " II: \t" << kern0.meanDist2 << endl; - outPar << probkern << ": \t" << kern0.probKern1 << endl; - } + kern0 = pSpecies->getKernTraits(0, 0); + outPar << meandist << " I: \t" << kern0.meanDist1 << endl; + if (trfr.twinKern) + { + outPar << meandist << " II: \t" << kern0.meanDist2 << endl; + outPar << probkern << ": \t" << kern0.probKern1 << endl; } } } @@ -1944,24 +1807,6 @@ void OutParameters(Landscape* pLandscape) } } } - if (sett.indVar) { - settParams sparams0; - outPar << "DENSITY DEPENDENCE + " << indvar << "yes" << endl; - for (int sex = 0; sex < nsexes; sex++) { - if (sett.sexDep) { - if (sex == 0) outPar << "FEMALES:" << endl; - else outPar << "MALES:" << endl; - } - sparams0 = pSpecies->getSettParams(0, sex); - settScales scale = pSpecies->getSettScales(); - outPar << "S0 - mean: " << sparams0.s0Mean << " s.d.: " << sparams0.s0SD - << " scaling factor: " << scale.s0Scale << endl; - outPar << "AlphaS - mean: " << sparams0.alphaSMean << " s.d.: " << sparams0.alphaSSD - << " scaling factor: " << scale.alphaSScale << endl; - outPar << "BetaS - mean: " << sparams0.betaSMean << " s.d.: " << sparams0.betaSSD - << " scaling factor: " << scale.betaSScale << endl; - } - } } else { // kernel-based transfer string notsuit = "IF THE ARRIVAL CELL/PATCH IS UNSUITABLE: "; @@ -2024,71 +1869,19 @@ void OutParameters(Landscape* pLandscape) // Genetics outPar << endl << "GENETICS:" << endl; - int nspptraits = pSpecies->getNTraits(); - outPar << "No. of variable traits: " << nspptraits << endl; + set traitList = pSpecies->getTraitTypes(); - genomeData d = pSpecies->getGenomeData(); - if (emig.indVar || trfr.indVar || sett.indVar || d.neutralMarkers) - { - if (d.diploid) outPar << "DIPLOID" << endl; else outPar << "HAPLOID" << endl; - int nchromosomes = pSpecies->getNChromosomes(); - outPar << "No. of chromosomes: " << nchromosomes; - if (d.trait1Chromosome) { - outPar << endl << "No. of loci/chromosome: " << d.nLoci << endl; - } - else { - outPar << " (chrom:loci)"; - for (int i = 0; i < nchromosomes; i++) { - outPar << " " << i << ":" << pSpecies->getNLoci(i); - } - outPar << endl; - } - outPar << "Mutation probability: " << d.probMutn << endl; - outPar << "Crossover probability: " << d.probCrossover << endl; - outPar << "Initial allele s.d.: " << d.alleleSD << endl; - outPar << "Mutation s.d.: " << d.mutationSD << endl; - if (d.neutralMarkers) { - outPar << "NEUTRAL MARKERS ONLY" << endl; - } - else { - if (!d.trait1Chromosome) { - traitAllele allele; - outPar << "TRAIT MAPPING:" << endl; - outPar << "Architecture file: " << genfilename << endl; - int ntraitmaps = pSpecies->getNTraitMaps(); - outPar << "No. of traits defined: " << ntraitmaps << endl; - for (int i = 0; i < ntraitmaps; i++) { - int nalleles = pSpecies->getNTraitAlleles(i); - outPar << "Trait " << i << ": (" << pSpecies->getTraitName(i) - << ") alleles: " << nalleles << " (chrom:locus)"; - for (int j = 0; j < nalleles; j++) { - allele = pSpecies->getTraitAllele(i, j); - outPar << " " << allele.chromo << ":" << allele.locus; - } - outPar << endl; - } - if (ntraitmaps < nspptraits) { // list undefined traits - outPar << "WARNING - the following traits were not defined" - << " in the genetic architecture file:" << endl; - for (int i = ntraitmaps; i < nspptraits; i++) { - outPar << "Trait " << i << ": (" << pSpecies->getTraitName(i) - << ") all individuals have mean phenotype" << endl; - } - } - int nneutral = pSpecies->getNNeutralLoci(); - if (nneutral > 0) { - outPar << "Neutral loci: " << nneutral << " (chrom:locus)"; - for (int i = 0; i < nneutral; i++) { - allele = pSpecies->getNeutralAllele(i); - outPar << " " << allele.chromo << ":" << allele.locus; - } - outPar << endl; - } - if (d.pleiotropic) - outPar << "Genome exhibits pleiotropy" << endl; - } - } - } + if (pSpecies->isDiploid()) outPar << "DIPLOID" << endl; else outPar << "HAPLOID" << endl; + outPar << "Genome size: " << pSpecies->getGenomeSize() << endl; + outPar << "Chromosome breaks : "; + + for (auto end : pSpecies->getChromosomeEnds()) + outPar << end << " "; + outPar << endl; + outPar << "Recombination rate: " << pSpecies->getRecombinationRate() << endl; + outPar << "Traits modelled: " << endl; + for (auto trait : traitList) + outPar << trait << endl; // Initialisation @@ -2214,24 +2007,11 @@ void OutParameters(Landscape* pLandscape) if (sim.outStartInd > 0) outPar << " starting year " << sim.outStartInd; outPar << endl; } - if (sim.outGenetics) { - outPar << "Genetics - every " << sim.outIntGenetic << " year"; - if (sim.outIntGenetic > 1) outPar << "s"; - if (sim.outStartGenetic > 0) outPar << " starting year " << sim.outStartGenetic; - if (dem.stageStruct) { - switch (sim.outGenType) { - case 0: - outPar << " - juveniles only"; - break; - case 1: - outPar << " - all individuals"; - break; - case 2: - outPar << " - adults only"; - break; - } - } - if (sim.outGenXtab) outPar << " (as cross table)"; + if (sim.outputWCFstat || sim.outputPairwiseFst) { + outPar << "Neutral genetics - every " << sim.outputGeneticInterval << " year"; + if (sim.outputGeneticInterval > 1) outPar << "s"; + if (sim.outputPairwiseFst) outPar << " outputting pairwise patch fst"; + if (sim.outputPerLocusWCFstat) outPar << " outputting per locus fst "; outPar << endl; } @@ -2282,9 +2062,7 @@ void OutParameters(Landscape* pLandscape) if (sim.saveVisits) outPar << "yes" << endl; else outPar << "no" << endl; } - outPar.close(); outPar.clear(); - } //--------------------------------------------------------------------------- diff --git a/Model.h b/Model.h index 41c50a3..56dc1f7 100644 --- a/Model.h +++ b/Model.h @@ -40,7 +40,7 @@ Authors: Greta Bocedi & Steve Palmer, University of Aberdeen - Last updated: 26 October 2021 by Steve Palmer + Last updated: 28 July 2021 by Greta Bocedi ------------------------------------------------------------------------------*/ #ifndef ModelH @@ -52,11 +52,6 @@ //#if RS_RCPP && !R_CMD #include "../Version.h" //#endif - -//#if !RS_RCPP && R_CMD -//#include "../../Batch/Version.h" -//#endif - #include "Parameters.h" #include "Landscape.h" #include "Community.h" diff --git a/Mutation.h b/Mutation.h new file mode 100644 index 0000000..a9ea4fc --- /dev/null +++ b/Mutation.h @@ -0,0 +1,16 @@ +#ifndef MUTATIONH +#define MUTATIONH + +class Mutation { + const int id; + const float selCoef; + const float dominance; + inline static int counter = 0; +public: + Mutation(float selCoefA, float dominanceA) : selCoef(selCoefA), dominance(dominanceA), id(counter) { ++counter; } + ~Mutation() {} + float getSelectionCoef() const { return selCoef; }; + float getDominanceCoef() const { return dominance; }; + float getId() const { return id; } +}; +#endif \ No newline at end of file diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp new file mode 100644 index 0000000..141eb03 --- /dev/null +++ b/NeutralStatsManager.cpp @@ -0,0 +1,713 @@ + +#include "NeutralStatsManager.h" +#include "Population.h" + +/*---------------------------------------------------------------------------- + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * + * This file is part of RangeShifter. + * + * RangeShifter 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 3 of the License, or + * (at your option) any later version. + * + * RangeShifter is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RangeShifter. If not, see . + * + * File Created by RH March 2023. Code adapted from NEMO (https://nemo2.sourceforge.io/) + --------------------------------------------------------------------------*/ + + // ---------------------------------------------------------------------------------------- + // Cstor + // ---------------------------------------------------------------------------------------- + + + +NeutralStatsManager::NeutralStatsManager(set const& patchList, const int nLoci) { + + this->_fst_matrix = PatchMatrix(patchList.size(), patchList.size()); + + globalAlleleTable.reserve(nLoci); //don't have to be pointers, not shared or moved + +} + +// ---------------------------------------------------------------------------------------- +// Set allele tables in NeutralData structs +// ---------------------------------------------------------------------------------------- + + +void NeutralStatsManager::updateAlleleTables(Species* pSpecies, Landscape* pLandscape, set const& patchList) { + + const int nLoci = pSpecies->getNPositionsForTrait(SNP); + const int nAlleles = (int)pSpecies->getTrait(SNP)->getMutationParameters().find(MAX)->second; + const int chromosomes = (pSpecies->isDiploid() ? 2 : 1); + + if (!globalAlleleTable.empty()) + resetGlobalAlleleTable(); + + int populationSize = 0; + + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + pPop->updateAlleleTable(); + populationSize += pPop->sampleSize(); + + for (int loci = 0; loci < nLoci; loci++) { + for (int allele = 0; allele < nAlleles; allele++) { + + int patchAlleleCount = pPop->getAlleleCount(loci, allele); + + if (globalAlleleTable.size() <= loci) { //if first allele of new loci (should only happen in first calculation step) + NeutralData n = NeutralData(nAlleles, allele, patchAlleleCount); + globalAlleleTable.push_back(n); + } + else globalAlleleTable[loci].incrementCountBy(patchAlleleCount, allele); + } + } + } + + populationSize *= chromosomes; + + std::for_each(globalAlleleTable.begin(), + globalAlleleTable.end(), + [&](NeutralData &v) -> void { + v.setFrequencies(populationSize); + }); +} + +// ---------------------------------------------------------------------------------------- +// Reset allele tables in NeutralData structs +// ---------------------------------------------------------------------------------------- + +void NeutralStatsManager::resetGlobalAlleleTable() { + for (auto& entry : globalAlleleTable) { + entry.reset(); + } +} + + +// ---------------------------------------------------------------------------------------- +// set loci diversity +// ---------------------------------------------------------------------------------------- + +void NeutralStatsManager::setLociDiversityCounter(set const& patchList, const int nInds, Species* pSpecies, Landscape* pLandscape) +{ + unsigned int i, j, k; + const int nLoci = pSpecies->getNPositionsForTrait(SNP); + const int nAlleles = (int)pSpecies->getTrait(SNP)->getMutationParameters().find(MAX)->second; + const int chromosomes = (pSpecies->isDiploid() ? 2 : 1); + unsigned int nbpatch = 0; + double patch_mean, pop_mean = 0; + + bool** pop_div; + + // number of alleles per locus, Patch and pop counters: + pop_div = new bool* [nLoci]; + + for (i = 0; i < nLoci; ++i) { + pop_div[i] = new bool[nAlleles]; + for (j = 0; j < nAlleles; ++j) + pop_div[i][j] = 0; + } + + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + + nbpatch += (pPop->sampleSize() != 0); + if (pPop->sampleSize() > 0) { + patch_mean = 0; + for (i = 0; i < nLoci; ++i) + for (j = 0; j < nAlleles; ++j) { + patch_mean += (pPop->getAlleleCount(i, j) != 0); + pop_div[i][j] |= (pPop->getAlleleCount(i, j) != 0); + } + // add mean nb of alleles per locus for Patch k to the pop mean + pop_mean += patch_mean / nLoci; + } + } + + _nb_alleles_local = (nbpatch ? pop_mean / nbpatch : nanf("NULL")); + _nb_alleles_global = 0; + + for (i = 0; i < nLoci; ++i) + for (j = 0; j < nAlleles; ++j) + _nb_alleles_global += pop_div[i][j]; + + _nb_alleles_global /= nLoci; + + for (i = 0; i < nLoci; ++i) + delete[] pop_div[i]; + delete[] pop_div; + + //number of fixed loci, local and global counters: + _fix_loc_local = 0; + + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + for (i = 0; i < nLoci; ++i) + for (j = 0; j < nAlleles; ++j) + _fix_loc_local += (pPop->getAlleleFrequency(i, j) == 1); + } + + _fix_loc_local /= nbpatch; + _fix_loc_global = 0; + + //globally: + for (i = 0; i < nLoci; ++i) + for (j = 0; j < nAlleles; ++j) + _fix_loc_global += (globalAlleleTable[i].getFrequency(j) == 1); +} + +// ---------------------------------------------------------------------------------------- +// calculate Ho per Nei and Chesser +// ---------------------------------------------------------------------------------------- +void NeutralStatsManager::calculateHo(set const& patchList, const int nbInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape) { + + double hetero = 0; + double nLoci = nbInds * nbrLoci; + + if (nLoci != 0) { + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + hetero += pPop->countHeterozygoteLoci(); + } + _ho = hetero / nLoci; + } + else _ho = 0.0; +} + +// ---------------------------------------------------------------------------------------- +// calculate Hs per Nei and Chesser, currently not used but may be useful +// ---------------------------------------------------------------------------------------- + + +void NeutralStatsManager::calculateHs(set const& patchList, const int nbrLoci, Species* pSpecies, Landscape* pLandscape) { + + double hs = 0; + int nPatches = 0; + + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + + if (pPop->sampleSize() > 0) { + nPatches++; + hs += pPop->computeHs(); + } + } + + _hs = (nPatches != 0 ? hs / (nbrLoci * nPatches) : 0.0); + +} + +// ---------------------------------------------------------------------------------------- +// calculate Ht per Nei and Chesser, currently not used but may be useful +// ---------------------------------------------------------------------------------------- + + +void NeutralStatsManager::calculateHt(Species* pSpecies, Landscape* pLandscape, const int nLoci, const int nAlleles) { + + double ht = 0; + int nPatches = 0; + vectorlocihet(nLoci, 1); + double freq; + + for (int loci = 0; loci < nLoci; ++loci) { + + for (int allele = 0; allele < nAlleles; ++allele) { + + freq = globalAlleleTable[loci].getFrequency(allele); + + freq *= freq; //squared frequencies + + locihet[loci] -= freq; //1 - sum of p2 = expected heterozygosity + } + + ht += locihet[loci]; + } + + _ht = ht / nLoci; +} + +// ---------------------------------------------------------------------------------------- +// calculate Ho per locus as per Nei and Chesser +// ---------------------------------------------------------------------------------------- + +void NeutralStatsManager::calculateHo2(set const& patchList, const int nbInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape) { + + vector hetero(nbrLoci, 0); + + double nLoci = nbInds * nbrLoci; + + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + if (pPop->sampleSize() > 0) { + const vector heteroPatch = pPop->countLociHeterozyotes(); + + transform(hetero.begin(), hetero.end(), heteroPatch.begin(), + hetero.begin(), plus()); + } + } + + if (nbInds != 0) + for (double h : hetero) { + h /= nbInds; + } + ho_loc = hetero; +} + + +// ---------------------------------------------------------------------------------------- +// Fstat Weir & Cockerham +// ---------------------------------------------------------------------------------------- + + +void NeutralStatsManager::calculateFstatWC(set const& patchList, const int nInds, const int nLoci, const int nAlleles, Species* pSpecies, Landscape* pLandscape) { + + double inverse_n_total; + double sum_weights = 0; + double n_bar, n_c, inverse_n_bar; + unsigned int extantPs = 0; + + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + int patchSize = pPop->sampleSize(); + if (patchSize) { + extantPs++; + sum_weights += (patchSize * patchSize / nInds); + } + } + + _n_extantPopulations = extantPs; + _n_individuals = nInds; + + n_bar = nInds / extantPs; + n_c = (nInds - sum_weights) / (extantPs - 1); + inverse_n_bar = 1 / (n_bar - 1); + inverse_n_total = 1 / nInds; + + double var; + double s2, p_bar, h_bar; + double s2_denom = 1.0 / ((extantPs - 1) * n_bar), + r = (double)(extantPs - 1) / extantPs, + h_bar_factor = (2 * n_bar - 1) / (4 * n_bar); + + double a = 0, b = 0, c = 0, x; + + for (unsigned int loci = 0; loci < nLoci; ++loci) { + + for (unsigned int allele = 0; allele < nAlleles; ++allele) { + + s2 = p_bar = h_bar = 0; + + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + + var = pPop->getAlleleFrequency(loci, allele) - globalAlleleTable[loci].getFrequency(allele); //(p_liu - pbar_u)^2 + + var *= var; + + s2 += var * pPop->sampleSize(); + + h_bar += pPop->getHetero(loci, allele); + + }//end for pop + + s2 *= s2_denom; + p_bar = globalAlleleTable[loci].getFrequency(allele); + h_bar *= inverse_n_total; + + x = p_bar * (1 - p_bar) - r * s2; + a += s2 - inverse_n_bar * (x - 0.25 * h_bar); + b += x - h_bar_factor * h_bar; + c += h_bar; + } // end for allele + } // end for locus + + a *= n_bar / n_c; + b *= n_bar / (n_bar - 1); + c *= 0.5; + + _fst_WC = a / (a + b + c); + _fit_WC = (a + b) / (a + b + c); + _fis_WC = b / (b + c); +} + + +// ---------------------------------------------------------------------------------------- +// Fstat Weir & Cockerham using Mean square approach. Similar to implementation in Hierfstat +// ---------------------------------------------------------------------------------------- + +void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const int nInds, const int nLoci, const int nAlleles, Species* pSpecies, Landscape* pLandscape) { + + double sum_weights = 0; + double nc; + unsigned int extantPs = 0; + + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + int patchSize = pPop->sampleSize(); + if (patchSize) { + extantPs++; + sum_weights += (patchSize * patchSize / nInds); + } + + } + + nc = (nInds - sum_weights) / (extantPs - 1); + + + unsigned int npl = extantPs; //all loci typed in all patches + + //p = _alleleFreqTable + //pb = _globalAlleleFreq + + vector alploc(nLoci); + + unsigned int** alploc_table = new unsigned int* [nLoci]; + + for (unsigned int i = 0; i < nLoci; ++i) + alploc_table[i] = new unsigned int[nAlleles]; + + unsigned int tot_num_allele = 0; + + for (unsigned int l = 0; l < nLoci; ++l) { + + alploc[l] = 0; + + for (unsigned int cnt, a = 0; a < nAlleles; ++a) { + + cnt = 0; + + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + + cnt += pPop->getAlleleCount(l, a); + + } + alploc_table[l][a] = (cnt != 0); + alploc[l] += (cnt != 0); + } + + tot_num_allele += alploc[l]; + } + + //n, and nal are given by pop_sizes, same num ind typed at all loci in each patch +//nc is the same for each locus +//nt is given by tot_size, same tot num of ind typed for all loci + +//SSG: het/2 for each allele + vector SSG(tot_num_allele); + vector SSP(tot_num_allele); + vector SSi(tot_num_allele); + + unsigned int all_cntr = 0; + + double het, freq, var; + + for (unsigned int l = 0; l < nLoci; ++l) { + + for (unsigned int a = 0; a < nAlleles && all_cntr < tot_num_allele; ++a) { + + if (alploc_table[l][a] == 0) continue; //do not consider alleles not present in the pop + + SSG[all_cntr] = 0; + SSi[all_cntr] = 0; + SSP[all_cntr] = 0; + + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + int popSize = pPop->sampleSize(); + if (!popSize) continue; //skip empty patches + + het = pPop->getHetero(l, a); + + freq = pPop->getAlleleFrequency(l, a); + + var = freq - globalAlleleTable[l].getFrequency(a); //(p_liu - pbar_u)^2 + + var *= var; + + SSG[all_cntr] += het; + + SSi[all_cntr] += 2 * popSize * freq * (1 - freq) - het / 2; + + SSP[all_cntr] += 2 * popSize * var; + } + + all_cntr++; + } + + } + + + if (all_cntr != tot_num_allele) + cout << endl << ("Error:: allele counter and total number of alleles differ in WC mean squared Fstat calculation \n"); + + + //these shouldn't have to be dynamically allocated manually, if using a vector from stl then would do allocation for you + + vector MSG(tot_num_allele); + vector MSP(tot_num_allele); + vector MSI(tot_num_allele); + vector sigw(tot_num_allele); + vector siga(tot_num_allele); + vector sigb(tot_num_allele); + + // double *FST_pal = new double[tot_num_allele]; + // double *FIS_pal = new double[tot_num_allele]; + + double SIGA = 0, SIGB = 0, SIGW = 0; + + //per locus stats, resize should only happen in first timestep of calculation: + if (_fst_WC_loc.size() == 0) + _fst_WC_loc.resize(nLoci); + if (_fis_WC_loc.size() == 0) + _fis_WC_loc.resize(nLoci); + if (_fit_WC_loc.size() == 0) + _fit_WC_loc.resize(nLoci); + + if (tot_num_allele != nLoci) { + for (unsigned int i = 0; i < tot_num_allele; ++i) { + + MSG[i] = SSG[i] / (2 * nInds); + sigw[i] = MSG[i]; //wasted! + + MSP[i] = SSP[i] / (npl - 1); + + MSI[i] = SSi[i] / (nInds - npl); + + sigb[i] = 0.5 * (MSI[i] - MSG[i]); + + siga[i] = (MSP[i] - MSI[i]) / (2 * nc); + + // FST_pal[i] = siga[i]/(siga[i]+sigb[i]+sigw[i]); + // FIS_pal[i] = sigb[i]/(sigb[i]+sigw[i]); + + SIGA += siga[i]; + SIGB += sigb[i]; + SIGW += sigw[i]; + } + + + + double lsiga, lsigb, lsigw; + + // cout<<" computing sigma per locus\n"; + + for (unsigned int allcntr = 0, i = 0; i < nLoci; ++i) { + + lsiga = lsigb = lsigw = 0; + + for (unsigned int l = 0; l < alploc[i]; ++l) { + + lsiga += siga[allcntr]; + lsigb += sigb[allcntr]; + lsigw += sigw[allcntr]; + + allcntr++; + + } + + _fst_WC_loc[i] = lsiga / (lsiga + lsigb + lsigw); + _fis_WC_loc[i] = lsigb / (lsigb + lsigw); + _fit_WC_loc[i] = (lsiga + lsigb) / (lsiga + lsigb + lsigw); + + } + + // Total F-stats + _fst_WC = SIGA / (SIGA + SIGB + SIGW); + _fit_WC = (SIGA + SIGB) / (SIGA + SIGB + SIGW); + _fis_WC = SIGB / (SIGB + SIGW); + + } + else { //then there is no variation at any locus, only 1 allele (wildtype) at each locus so don't calculate to avoid division by zero issues + // Total F-stats + _fst_WC = 0; + _fit_WC = 0; + _fis_WC = 0; + } + + for (unsigned int i = 0; i < nLoci; ++i) + delete[]alploc_table[i]; + delete[]alploc_table; +} + + +// ---------------------------------------------------------------------------------------- +// Patch pairwise Fst +// Computes the weighted within and between patch Fst's as well as the overall Fst (Theta). +// The method used here is that of Weir& Hill 2002, Ann.Rev.Genet. 36:721 - 750. +// The weighting is done for samples(patches) of unequal sizes. +// ---------------------------------------------------------------------------------------- + +void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape) { + + const int nAlleles = (int)pSpecies->getTrait(SNP)->getMutationParameters().find(MAX)->second; + + vector patchVect; + + copy(patchList.begin(), patchList.end(), std::back_inserter(patchVect)); //needs to be in vector to iterate over, copy preserves order + + int nPatches = patchList.size(); + + //initialise + + if (_fst_matrix.length() != nPatches * nPatches) + + _fst_matrix = PatchMatrix(nPatches, nPatches); + + //reset table + _fst_matrix.assign(nanf("NULL")); + + //init + double* pop_weights = new double[nPatches]; + double* pop_sizes = new double[nPatches]; + double** numerator = new double* [nPatches]; + for (unsigned int i = 0; i < nPatches; i++) numerator[i] = new double[nPatches]; + double tot_size; + double numerator_W = 0; + double denominator = 0; + double sum_weights = 0; + + tot_size = nInds * 2; //diploid + + + for (unsigned int i = 0; i < nPatches; ++i) { + + const auto patch = pLandscape->findPatch(patchVect[i]); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + pop_sizes[i] = pPop->sampleSize() * 2; + pop_weights[i] = pop_sizes[i] - (pop_sizes[i] * pop_sizes[i] / tot_size); //n_ic in Weir & Hill 2002 + sum_weights += pop_weights[i]; + for (unsigned int j = 0; j < nPatches; j++) + numerator[i][j] = 0; + } + + double p, pq, var, num; + + for (unsigned int i = 0; i < nPatches; ++i) { + + if (!pop_sizes[i]) continue; + + const auto patch = pLandscape->findPatch(patchVect[i]); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + +//#if RSDEBUG +// DEBUGLOG << "OutputPairwiseStats: 644 " +// << " population " << patch->getPatchNum() << " popSize[i] " << pop_sizes[i] << endl; +// // << endl; +//#endif + + for (unsigned int l = 0; l < nLoci; ++l) { + + for (unsigned int u = 0; u < nAlleles; ++u) { + + p = pPop->getAlleleFrequency(l, u); //p_liu + + pq = p * (1 - p); + + var = p - globalAlleleTable[l].getFrequency(u); //(p_liu - pbar_u)^2 + + var *= var; + + num = pq * pop_sizes[i] / (pop_sizes[i] - 1); + + numerator[i][i] += num; + + numerator_W += num * pop_sizes[i]; //see equ. 9, Weir & Hill 2002 + + denominator += pop_sizes[i] * var + pop_weights[i] * pq; //common denominator + +//#if RSDEBUG +// DEBUGLOG << "OutputPairwiseStats: 671 " +// << " loci " << l << " allele " << u << " frequency " << p << " pq " << pq << " var " << var << " num " << num << +// " numerator[i][i] " << numerator[i][i] << " numerator_W " << numerator_W << " denominator " << denominator +// << endl; +//#endif + + + } // end for allele + }// end for locus + }//end for pop + + for (unsigned int i = 0; i < nPatches; ++i) { + if (!pop_sizes[i]) continue; + if(denominator != 0) + _fst_matrix.set(i, i, 1 - (numerator[i][i] * sum_weights / denominator)); + else + _fst_matrix.set(i, i, 0.0); +//#if RSDEBUG +// DEBUGLOG << "OutputPairwiseStats: 717 " +// << " result " << 1 - (numerator[i][i] * sum_weights / denominator) << " in matrix " << getPairwiseFst(i, i) +// << endl; +//#endif + } + _fst_WH = 1 - ((numerator_W * sum_weights) / (denominator * tot_size)); //equ. 9 Weir & Hill 2002 + + //pairwise Fst: + double pi, pj; + for (unsigned int l = 0; l < nLoci; ++l) + for (unsigned int u = 0; u < nAlleles; ++u) + for (unsigned int i = 0; i < nPatches - 1; ++i) { + if (!pop_sizes[i]) continue; + + const auto patch = pLandscape->findPatch(patchVect[i]); + const auto pPopI = (Population*)patch->getPopn((intptr)pSpecies); + + for (unsigned int j = i + 1; j < nPatches; ++j) { + if (!pop_sizes[j]) continue; + const auto patch = pLandscape->findPatch(patchVect[j]); + const auto pPopJ = (Population*)patch->getPopn((intptr)pSpecies); + + pi = pPopI->getAlleleFrequency(l, u); + pj = pPopJ->getAlleleFrequency(l, u); + numerator[i][j] += pi * (1 - pj) + pj * (1 - pi); //equ. 7 of Weir & Hill 2002 + } + } + + + for (unsigned int i = 0; i < nPatches - 1; ++i) { + if (!pop_sizes[i]) continue; + for (unsigned int j = i + 1; j < nPatches; ++j) { + if (!pop_sizes[j]) continue; + if (denominator != 0) + _fst_matrix.set(i, j, 1 - ((numerator[i][j] * sum_weights) / (2 * denominator))); + else + _fst_matrix.set(i, j, 0.0); + +//#if RSDEBUG +// DEBUGLOG << "OutputPairwiseStats: 717 " +// << " result " << 1 - ((numerator[i][j] * sum_weights) / (2 * denominator)) << " in matrix " << getPairwiseFst(i, j) +// << endl; +//#endif + + } + } + delete[] pop_weights; + delete[] pop_sizes; + for (unsigned int i = 0; i < nPatches; i++) delete[] numerator[i]; + delete[] numerator; +} + + + + + diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h new file mode 100644 index 0000000..5385314 --- /dev/null +++ b/NeutralStatsManager.h @@ -0,0 +1,177 @@ +#ifndef NEUTRALSTATSH +#define NEUTRALSTATSH + +#include "Species.h" +#include "Landscape.h" + + +using namespace std; + +/**Creates an array of doubles of size = rows*cols, taken from NEMO**/ +struct PatchMatrix +{ +private: + unsigned int _rows, _cols, _length; + vector _val; + +public: + + PatchMatrix() {}; + + PatchMatrix(unsigned int rows, unsigned int cols) : _rows(0), _cols(0), _length(0), _val(0) { + _length = rows * cols; + _val.resize(_length); + _rows = rows; _cols = cols; + }; + + + /**Assigns a value to all element of the matrix.*/ + void assign(double val) + { + for (unsigned int i = 0; i < _length; ++i) _val[i] = val; + } + + int length() { return _length; }; + + /**Sets element at row i and column j to value val**/ + void set(unsigned int i, unsigned int j, double val) { + if (i * j < _length) + _val[i * _cols + j] = val; + else + cout << endl << ("Error: PatchMatrix::set() out of range!\n"); + } + + double get(unsigned int i, unsigned int j) { + if (!((i + 1) * (j + 1) > _length)) + return _val[i * _cols + j]; + else + cout << endl << ("Error: PatchMatrix::get() out of range!\n"); + return 0; + } +}; + + +struct NeutralData { + +private: + //int lociPosition; + //char allele; + vector counts; + vector freqs; + vector heteros; + +public: + //for community allele table, heteros not technically needed so don't reserve + NeutralData(int nAllele, int allele, int alleleCount) : counts(nAllele), freqs(nAllele) { + this->incrementCountBy(alleleCount, allele); + }; + + //for population allele tables + NeutralData(int nAllele) : counts(nAllele), freqs(nAllele), heteros(nAllele) {}; + + void setFrequencies(int populationSize) { + int i = 0; + for (auto count : counts) { + if (freqs.size() <= i) + freqs.push_back(((count != 0) ? count / static_cast(populationSize) : 0)); + else + freqs[i] = ((count != 0) ? count / static_cast(populationSize) : 0); + ++i; + } + }; + + void reset() { + fill(counts.begin(), counts.end(), 0); fill(freqs.begin(), freqs.end(), 0); + fill(heteros.begin(), heteros.end(), 0); + } + + int getCount(int allele) { + return counts[allele]; + }; + double getFrequency(int allele) { return freqs[allele]; }; + + double getHetero(int allele) { return heteros[allele]; }; + + void incrementCount(int allele) { counts[allele]++; }; + + void incrementCountBy(int count, int allele) { this->counts[allele] += count; } + + void incrementHeteroBy(int count, int allele) { + this->heteros[allele] += count; + } + + + + +}; + + + +class NeutralStatsManager { + +private: + int _n_extantPopulations, _n_individuals; + /**F-statistics*/ + double _ho, _hs, _ht, _hsnei, _htnei, _nb_alleles_local, _nb_alleles_global, + _fst, _fis, _fit, _fix_loc_local, _fix_loc_global; + /**Weir & Hill (2002) F-stat estimates.*/ + double _fst_WH; + /**Weir & Cockerham (1984) F-stat estimates.*/ + double _fst_WC, _fis_WC, _fit_WC; + /**Per-locus F-stats (Weir&Cockerham).*/ + vector _fst_WC_loc, _fis_WC_loc, _fit_WC_loc, ho_loc; //no need for pointers because shouldn't be copied or moved, resized + + /**Pairwise Fst matrix.*/ + PatchMatrix _fst_matrix; + vector globalAlleleTable; //don't have to be pointers, not shared or moved + +public: + + NeutralStatsManager(set const& patchList, const int nLoci); + + void updateAlleleTables(Species* pSpecies, Landscape* pLandscape, set const& patchList); + + void resetGlobalAlleleTable(); + + void setLociDiversityCounter(set const& patchList, const int nInds, Species* pSpecies, Landscape* pLandscape); + + void calculateHo(set const& patchList, const int nbInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape); + void calculateHs(set const& patchList, const int nbrLoci, Species* pSpecies, Landscape* pLandscape); + void calculateHt(Species* pSpecies, Landscape* pLandscape, const int nLoci, const int nAlleles); + void calculateHo2(set const& patchList, const int nbInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape); + + void calculateFstatWC(set const& patchList, const int nInds, const int nLoci, const int nAlleles, Species* pSpecies, Landscape* pLandscape); + void calculateFstatWC_MS(set const& patchList, const int nInds, const int nLoci, const int nAlleles, Species* pSpecies, Landscape* pLandscape); + + void setFstMatrix(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape); + + double getHsnei() const { return _hsnei; } + double getHtnei() const { return _htnei; } + double getHo() const { return _ho; } + double getHs() const { return _hs; } + double getHt() const { return _ht; } + double getFst() const { return _fst; } + double getFis() const { return _fis; } + double getFit() const { return _fit; } + double getFstWC() const { return _fst_WC; } + double getFisWC() const { return _fis_WC; } + double getFitWC() const { return _fit_WC; } + int getNExtantPatchs() const { return _n_extantPopulations; } + int getNIndividuals() const { return _n_individuals; } + double getWeightedFst() { return _fst_WH; } + double getNbAllLocal() const { return _nb_alleles_local; } + double getNbAllGlobal() const { return _nb_alleles_global; } + double getFixLocLocal() const { return _fix_loc_local; } + double getFixLocGlobal() const { return _fix_loc_global; } + double getPairwiseFst(int i, int j) { return _fst_matrix.get(i, j); } + double get_fst_WC_loc(int i) const { return _fst_WC_loc[i]; } + double get_fis_WC_loc(int i) const { return _fis_WC_loc[i]; } + double get_fit_WC_loc(int i) const { return _fit_WC_loc[i]; } + double get_ho_loc(int i) const { return ho_loc[i]; } +}; + +#endif + + + + diff --git a/Parameters.cpp b/Parameters.cpp index 28c2c67..37d9b5f 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -228,16 +228,16 @@ paramSim::paramSim(void) { reps = years = 1; outIntRange = 1; // outStartRange = outStartOcc = outStartPop = outStartInd = 0; - outStartPop = outStartInd = outStartGenetic = 0; + outStartPop = outStartInd = 0; outStartTraitCell = outStartTraitRow = outStartConn = 0; - outIntOcc = outIntPop = outIntInd = outIntGenetic = 10; + outIntOcc = outIntPop = outIntInd = outputGeneticInterval = 10; outIntTraitCell = outIntTraitRow = outIntConn = 10; mapInt = traitInt = 10; slowFactor = 1; batchMode = absorbing = false; outRange = outOccup = outPop = outInds = false; - outGenetics = outGenXtab = false; outGenType = 0; outTraitsCells = outTraitsRows = outConnect = false; + outputWCFstat = outputPerLocusWCFstat = outputPairwiseFst = false; saveMaps = false; saveTraitMaps = false; saveVisits = false; #if RS_RCPP @@ -245,6 +245,9 @@ paramSim::paramSim(void) { outPaths = false; ReturnPopRaster = false; CreatePopFile = true; #endif drawLoaded = false; + fionaOptions = 0.0; + storeIndsYr = -9999; + fixReplicateSeed = false; viewLand = false; viewPatch = false; viewGrad = false; viewCosts = false; viewPop = false; viewTraits = false; viewPaths = false; viewGraph = false; dir = ' '; @@ -262,18 +265,12 @@ void paramSim::setSim(simParams s) { batchMode = s.batchMode; absorbing = s.absorbing; outRange = s.outRange; outOccup = s.outOccup; outPop = s.outPop; outInds = s.outInds; - outGenetics = s.outGenetics; - if (s.outGenType >= 0 && s.outGenType <= 2) { - outGenType = s.outGenType; - } - outGenXtab = s.outGenXtab; outTraitsCells = s.outTraitsCells; outTraitsRows = s.outTraitsRows; outConnect = s.outConnect; //if (s.outStartRange >= 0) outStartRange = s.outStartRange; //if (s.outStartOcc >= 0) outStartOcc = s.outStartOcc; if (s.outStartPop >= 0) outStartPop = s.outStartPop; if (s.outStartInd >= 0) outStartInd = s.outStartInd; - if (s.outStartGenetic >= 0) outStartGenetic = s.outStartGenetic; if (s.outStartTraitCell >= 0) outStartTraitCell = s.outStartTraitCell; if (s.outStartTraitRow >= 0) outStartTraitRow = s.outStartTraitRow; if (s.outStartConn >= 0) outStartConn = s.outStartConn; @@ -281,7 +278,6 @@ void paramSim::setSim(simParams s) { if (s.outIntOcc >= 1) outIntOcc = s.outIntOcc; if (s.outIntPop >= 1) outIntPop = s.outIntPop; if (s.outIntInd >= 1) outIntInd = s.outIntInd; - if (s.outIntGenetic >= 1) outIntGenetic = s.outIntGenetic; if (s.outIntTraitCell >= 1) outIntTraitCell = s.outIntTraitCell; if (s.outIntTraitRow >= 1) outIntTraitRow = s.outIntTraitRow; if (s.outIntConn >= 1) outIntConn = s.outIntConn; @@ -295,6 +291,16 @@ void paramSim::setSim(simParams s) { CreatePopFile = s.CreatePopFile; #endif drawLoaded = s.drawLoaded; + fionaOptions = s.fionaOptions; + storeIndsYr = s.storeIndsYr; + fixReplicateSeed = s.fixReplicateSeed; +} + +void paramSim::setGeneticSim(bool outputWCFstat, bool outputPerLocusWCFstat, bool outputPairwiseFst, int outputGeneticInterval) { + this->outputWCFstat = outputWCFstat; + this->outputPerLocusWCFstat = outputPerLocusWCFstat; + this->outputPairwiseFst = outputPairwiseFst; + this->outputGeneticInterval = outputGeneticInterval; } simParams paramSim::getSim(void) { @@ -302,16 +308,15 @@ simParams paramSim::getSim(void) { s.batchNum = batchNum; s.simulation = simulation; s.reps = reps; s.years = years; s.outRange = outRange; s.outOccup = outOccup; s.outPop = outPop; s.outInds = outInds; - s.outGenetics = outGenetics; s.outGenType = outGenType; s.outGenXtab = outGenXtab; s.outTraitsCells = outTraitsCells; s.outTraitsRows = outTraitsRows; s.outConnect = outConnect; //s.outStartRange = outStartRange; //s.outStartOcc = outStartOcc; - s.outStartPop = outStartPop; s.outStartInd = outStartInd; s.outStartGenetic = outStartGenetic; + s.outStartPop = outStartPop; s.outStartInd = outStartInd; s.outStartTraitCell = outStartTraitCell; s.outStartTraitRow = outStartTraitRow; s.outStartConn = outStartConn; s.outIntRange = outIntRange; s.outIntOcc = outIntOcc; s.outIntPop = outIntPop; - s.outIntInd = outIntInd; s.outIntGenetic = outIntGenetic; + s.outIntInd = outIntInd; s.outIntTraitCell = outIntTraitCell; s.outIntTraitRow = outIntTraitRow; s.outIntConn = outIntConn; @@ -328,6 +333,13 @@ simParams paramSim::getSim(void) { s.CreatePopFile = CreatePopFile; #endif s.drawLoaded = drawLoaded; + s.fionaOptions = fionaOptions; + s.storeIndsYr = storeIndsYr; + s.outputWCFstat = outputWCFstat; + s.outputPerLocusWCFstat = outputPerLocusWCFstat; + s.outputPairwiseFst = outputPairwiseFst; + s.outputGeneticInterval = outputGeneticInterval; + return s; } diff --git a/Parameters.h b/Parameters.h index 2c45bd2..bef43e3 100644 --- a/Parameters.h +++ b/Parameters.h @@ -59,17 +59,19 @@ #include #include #include +#include using namespace std; //#if RS_RCPP && !R_CMD #include "../Version.h" //#endif -//#if !RS_RCPP && R_CMD -//#include "../../Batch/Version.h" -//#endif - #include "RSrandom.h" +class Landscape; + +#define NODATACOST 100000 // cost to use in place of nodata value for SMS; +#define ABSNODATACOST 100 // cost to use in place of nodata value for SMS; +// when boundaries are absorbing #define NSTAGES 10 // maximum number of stages permitted #define NSEXES 2 // maximum number of sexes permitted #define PARAMDEBUG 0 @@ -85,7 +87,7 @@ typedef unsigned long long intptr; #else typedef unsigned int intptr; #endif -#endif +#endif // RS_RCPP #if RS_RCPP #ifndef R_EXT_CONSTANTS_H_ // the R headers define PI as a macro, so that the 'else' line results in an error @@ -116,6 +118,63 @@ const string Float2Str(const float); const string Double2Str(const double); const rgb draw_wheel(int); +//-------------------------------------------------------------------------- + +/** Trait types **/ + +enum TraitType { + SNP, + ADAPTIVE, ADAPTIVE1, ADAPTIVE2, ADAPTIVE3, ADAPTIVE4, ADAPTIVE5, + + E_D0_F, E_ALPHA_F, E_BETA_F, + S_S0_F, S_ALPHA_F, S_BETA_F, + + E_D0_M, E_ALPHA_M, E_BETA_M, + S_S0_M, S_ALPHA_M, S_BETA_M, + + CRW_STEPLENGTH_F, CRW_STEPCORRELATION_F, + CRW_STEPLENGTH_M, CRW_STEPCORRELATION_M, + + KERNEL_MEANDIST_1_F, KERNEL_MEANDIST_2_F, KERNEL_PROBABILITY_F, + KERNEL_MEANDIST_1_M, KERNEL_MEANDIST_2_M, KERNEL_PROBABILITY_M, + + SMS_DP, SMS_GB, SMS_ALPHADB, SMS_BETADB +}; + +typedef std::string parameter_t; + +constexpr auto MEAN = "mean"; +constexpr auto SDEV = "sd"; +constexpr auto MIN = "min"; +constexpr auto MAX = "max"; +constexpr auto SHAPE = "shape"; +constexpr auto SCALE = "scale"; +//enums + +//enum GeneType { SNP, MICROSATELLITE, QTL, DELETERIOUS }; + +enum DistributionType { UNIFORM, NORMAL, GAMMA, NEGEXP, SCALED, KAM, SSM, NONE }; + +enum ExpressionType { AVERAGE, ADDITIVE, NEUTRAL, MULTIPLICATIVE }; + +/** Param's types **/ +typedef enum { KERNEL, SMS, CRW} movement_t; + +//GeneType convertToGeneType(const string& ); + +float convertParameters(string, string); +bool iequals(std::string_view lhs, std::string_view rhs); +set convertStringToSet(string); +set convertStringToPatches(string, int, Landscape*); +set convertStringToStages(string); +set convertStringToChromosomeEnds(string, int); + +//sex types +typedef enum { + FEM = 0, MAL = 1, BOTH = 2 +} sex_t; + +const sex_t stringToSex(const std::string& str); //--------------------------------------------------------------------------- // Environmental gradient parameters @@ -282,14 +341,13 @@ struct simParams { int simulation; int reps; int years; // int outStartRange; // int outStartOcc; - int outStartPop; int outStartInd; int outStartGenetic; + int outStartPop; int outStartInd; int outStartTraitCell; int outStartTraitRow; int outStartConn; - int outIntRange; int outIntOcc; int outIntPop; int outIntInd; int outIntGenetic; + int outIntRange; int outIntOcc; int outIntPop; int outIntInd; int outIntTraitCell; int outIntTraitRow; int outIntConn; int mapInt; int traitInt; bool batchMode; bool absorbing; bool outRange; bool outOccup; bool outPop; bool outInds; - bool outGenetics; short outGenType; bool outGenXtab; bool outTraitsCells; bool outTraitsRows; bool outConnect; bool saveMaps; bool drawLoaded; bool saveTraitMaps; @@ -298,6 +356,11 @@ struct simParams { int outStartPaths; int outIntPaths; bool outPaths; bool ReturnPopRaster; bool CreatePopFile; #endif + int fionaOptions; + int storeIndsYr; + bool fixReplicateSeed; + bool outputWCFstat, outputPerLocusWCFstat, outputPairwiseFst; + int outputGeneticInterval; }; struct simView { @@ -312,6 +375,7 @@ class paramSim { paramSim(void); ~paramSim(void); void setSim(simParams); + void setGeneticSim(bool outputWCFstat, bool outputPerLocusWCFstat, bool outputPairwiseFst, int outputGeneticInterval); simParams getSim(void); int getSimNum(void); void setViews(simView); @@ -332,7 +396,6 @@ class paramSim { // int outStartOcc; // output start year for occupancy file int outStartPop; // output start year for population file int outStartInd; // output start year for individuals file - int outStartGenetic; // output start year for genetics file int outStartTraitCell; // output start year for traits by cell file int outStartTraitRow; // output start year for traits by row file int outStartConn; // output start year for connectivity matrix @@ -340,7 +403,6 @@ class paramSim { int outIntOcc; // output interval for occupancy file int outIntPop; // output interval for population file int outIntInd; // output interval for individuals file - int outIntGenetic; // output interval for genetics file int outIntTraitCell; // output interval for traits by cell file int outIntTraitRow; // output interval for traits by row file int outIntConn; // output interval for connectivity matrix @@ -354,10 +416,6 @@ class paramSim { bool outOccup; // produce output occupancy file? bool outPop; // produce output population file? bool outInds; // produce output individuals file? - bool outGenetics; // produce output genetics file? - short outGenType; // produce output genetics for: 0 = juveniles only - // 1 = all individuals, 2 = adults (i.e. final stage) only - bool outGenXtab; // produce output genetics as a cross table? bool outTraitsCells; // produce output summary traits by cell file? bool outTraitsRows; // produce output summary traits by row (y) file? bool outConnect; // produce output connectivity file? @@ -382,6 +440,13 @@ class paramSim { bool viewGraph; // view population/occupancy graph on screen? string dir; // full name of working directory + int fionaOptions; + int storeIndsYr; + bool fixReplicateSeed; + bool outputWCFstat; + bool outputPerLocusWCFstat; + bool outputPairwiseFst; + int outputGeneticInterval; }; #if RSDEBUG diff --git a/Patch.h b/Patch.h index eccb9d2..32181bb 100644 --- a/Patch.h +++ b/Patch.h @@ -71,16 +71,11 @@ using namespace std; //#if RS_RCPP && !R_CMD #include "../Version.h" //#endif - -//#if !RS_RCPP && R_CMD -//#include "../../Batch/Version.h" -//#endif - #include "Parameters.h" #include "Cell.h" #include "Species.h" -//--------------------------------------------------------------------------- + //--------------------------------------------------------------------------- struct patchLimits { int xMin, xMax, yMin, yMax; diff --git a/Population.cpp b/Population.cpp index 76b4766..5035903 100644 --- a/Population.cpp +++ b/Population.cpp @@ -74,7 +74,6 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) trfrRules trfr = pSpecies->getTrfr(); //trfrSMSTraits sms = pSpecies->getSMSTraits(); settleType sett = pSpecies->getSettle(); - genomeData gen = pSpecies->getGenomeData(); initParams init = paramsInit->getInit(); // determine no. of stages and sexes of species to initialise @@ -206,10 +205,9 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) probmale, trfr.moveModel, trfr.moveType)); #endif sex = inds[nindivs + i]->getSex(); - if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) - { + if (pSpecies->getNTraits() > 0) { // individual variation - set up genetics - inds[nindivs + i]->setGenes(pSpecies, resol); + inds[nindivs + i]->setUpGenes(pSpecies, resol); } nInds[stg][sex]++; } @@ -249,10 +247,10 @@ traitsums Population::getTraits(Species* pSpecies) { ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; ts.sumS0[i] = ts.ssqS0[i] = 0.0; ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; + ts.sumFitness[i] = ts.ssqFitness[i] = 0.0; } //locus loc; - demogrParams dem = pSpecies->getDemogr(); emigRules emig = pSpecies->getEmig(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); @@ -275,29 +273,34 @@ traitsums Population::getTraits(Species* pSpecies) { ts.sumAlpha[g] += e.alpha; ts.ssqAlpha[g] += e.alpha * e.alpha; ts.sumBeta[g] += e.beta; ts.ssqBeta[g] += e.beta * e.beta; // transfer traits - trfrKernTraits k = inds[i]->getKernTraits(); - if (trfr.sexDep) g = sex; else g = 0; - ts.sumDist1[g] += k.meanDist1; ts.ssqDist1[g] += k.meanDist1 * k.meanDist1; - ts.sumDist2[g] += k.meanDist2; ts.ssqDist2[g] += k.meanDist2 * k.meanDist2; - ts.sumProp1[g] += k.probKern1; ts.ssqProp1[g] += k.probKern1 * k.probKern1; - trfrSMSTraits sms = inds[i]->getSMSTraits(); - g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ts.sumDP[g] += sms.dp; ts.ssqDP[g] += sms.dp * sms.dp; - ts.sumGB[g] += sms.gb; ts.ssqGB[g] += sms.gb * sms.gb; - ts.sumAlphaDB[g] += sms.alphaDB; ts.ssqAlphaDB[g] += sms.alphaDB * sms.alphaDB; - ts.sumBetaDB[g] += sms.betaDB; ts.ssqBetaDB[g] += sms.betaDB * sms.betaDB; -#if RSDEBUG - //DEBUGLOG << "Population::getTraits():" - // << " i=" << i << " g=" << g - // << " sms.dp= " << sms.dp << " sms.gb= " << sms.gb - // << " ts.sumDP[g]= " << ts.sumDP[g] << " ts.ssqDP[g]= " << ts.ssqDP[g] - // << " ts.sumGB[g]= " << ts.sumGB[g] << " ts.ssqGB[g]= " << ts.ssqGB[g] - // << endl; -#endif - trfrCRWTraits c = inds[i]->getCRWTraits(); - g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ts.sumStepL[g] += c.stepLength; ts.ssqStepL[g] += c.stepLength * c.stepLength; - ts.sumRho[g] += c.rho; ts.ssqRho[g] += c.rho * c.rho; + + if (trfr.moveModel) { + + switch (trfr.moveType) { + + case 1: // SMS + trfrSMSTraits sms = inds[i]->getSMSTraits(); + g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT + ts.sumDP[g] += sms.dp; ts.ssqDP[g] += sms.dp * sms.dp; + ts.sumGB[g] += sms.gb; ts.ssqGB[g] += sms.gb * sms.gb; + ts.sumAlphaDB[g] += sms.alphaDB; ts.ssqAlphaDB[g] += sms.alphaDB * sms.alphaDB; + ts.sumBetaDB[g] += sms.betaDB; ts.ssqBetaDB[g] += sms.betaDB * sms.betaDB; + break; + case 2: + trfrCRWTraits c = inds[i]->getCRWTraits(); + g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT + ts.sumStepL[g] += c.stepLength; ts.ssqStepL[g] += c.stepLength * c.stepLength; + ts.sumRho[g] += c.rho; ts.ssqRho[g] += c.rho * c.rho; + break; + } + } + else { + trfrKernTraits k = inds[i]->getKernTraits(); + if (trfr.sexDep) g = sex; else g = 0; + ts.sumDist1[g] += k.meanDist1; ts.ssqDist1[g] += k.meanDist1 * k.meanDist1; + ts.sumDist2[g] += k.meanDist2; ts.ssqDist2[g] += k.meanDist2 * k.meanDist2; + ts.sumProp1[g] += k.probKern1; ts.ssqProp1[g] += k.probKern1 * k.probKern1; + } // settlement traits settleTraits s = inds[i]->getSettTraits(); if (sett.sexDep) g = sex; else g = 0; @@ -305,6 +308,10 @@ traitsums Population::getTraits(Species* pSpecies) { ts.sumS0[g] += s.s0; ts.ssqS0[g] += s.s0 * s.s0; ts.sumAlphaS[g] += s.alpha; ts.ssqAlphaS[g] += s.alpha * s.alpha; ts.sumBetaS[g] += s.beta; ts.ssqBetaS[g] += s.beta * s.beta; + + if (NSEXES > 1) g = sex; else g = 0; + ts.sumFitness[g] += inds[i]->getFitness(); ts.ssqFitness[g] += inds[i]->getFitness() * inds[i]->getFitness(); + #if RSDEBUG //DEBUGLOG << "Population::getTraits():" // << " i=" << i << " g=" << g << " a=" << a @@ -320,6 +327,137 @@ traitsums Population::getTraits(Species* pSpecies) { int Population::getNInds(void) { return (int)inds.size(); } +// ---------------------------------------------------------------------------------------- +// reset allele table +// ---------------------------------------------------------------------------------------- +void Population::resetAlleleTable() { + for (auto& entry : alleleTable) { + entry.reset(); + } +} + +// ---------------------------------------------------------------------------------------- +// allele frequency in population of sampled individuals +// ---------------------------------------------------------------------------------------- + +void Population::updateAlleleTable() { + + const int nLoci = pSpecies->getNPositionsForTrait(SNP); + const int nAlleles = (int)pSpecies->getTrait(SNP)->getMutationParameters().find(MAX)->second; + const auto& positions = pSpecies->getTrait(SNP)->getPositions(); + + if (alleleTable.size() != 0) + resetAlleleTable(); + else { + alleleTable.reserve(nLoci); + + for (int l = 0; l < nLoci; l++) { + alleleTable.push_back(NeutralData(nAlleles)); + } + } + + for (Individual* individual : sampledInds) { + + const auto trait = individual->getTrait(SNP); + + int lociCounter = 0; + for (auto position : positions) { + + auto a = (int)trait->getSelectionCoefAtLoci(0, position); + auto b = (int)trait->getSelectionCoefAtLoci(1, position); + + int isHetero = a != b; + alleleTable[lociCounter].incrementHeteroBy(isHetero, a); + alleleTable[lociCounter].incrementHeteroBy(isHetero, b); + + alleleTable[lociCounter].incrementCount(a); + alleleTable[lociCounter].incrementCount(b); + + lociCounter++; + } + + } + + if (sampledInds.size() > 0) { + std::for_each(alleleTable.begin(), + alleleTable.end(), + [&](NeutralData& v) -> void { + v.setFrequencies(sampledInds.size() * 2); + //v->divideHeteros(sampledInds.size()); //weir and cockerham doesn't need this division?? + }); + } +} + +double Population::getAlleleFrequency(int loci, int allele) { + return alleleTable[loci].getFrequency(allele); +} + + +int Population::getAlleleCount(int loci, int allele) { + return alleleTable[loci].getCount(allele); +} + +double Population::getHetero(int loci, int allele) { + return alleleTable[loci].getHetero(allele); +} + +// ---------------------------------------------------------------------------------------- +// Count number of heterozygotes loci in sampled individuals +// ---------------------------------------------------------------------------------------- + +int Population::countHeterozygoteLoci() { + int hetero = 0; + for (Individual* ind : sampledInds) { + const auto trait = ind->getTrait(SNP); + hetero += trait->countHeterozygoteLoci(); + } + return hetero; +} + +// ---------------------------------------------------------------------------------------- +// Count number of heterozygotes per loci loci in sampled individuals +// ---------------------------------------------------------------------------------------- + +vector Population::countLociHeterozyotes() { + const auto& positions = pSpecies->getTrait(SNP)->getPositions(); + vector hetero(positions.size(), 0); + + for (Individual* ind : sampledInds) { + const auto trait = ind->getTrait(SNP); + int counter = 0; + for (auto position : positions) { + hetero[counter] += trait->isHeterozygoteAtLoci(position); + counter++; + } + } + return hetero; +} + +// ---------------------------------------------------------------------------------------- +// compute the expected heterozygosity for population +// ---------------------------------------------------------------------------------------- + +double Population::computeHs() { + int nLoci = pSpecies->getNPositionsForTrait(SNP); + int nAlleles = (int)pSpecies->getTrait(SNP)->getInitialParameters().find(MAX)->second; + double hs = 0; + double freq; + + vectorlocihet(nLoci, 1); + + if (sampledInds.size() > 0) { + for (int loci = 0; loci < nLoci; ++loci) { + for (int allele = 0; allele < nAlleles; ++allele) { + freq = getAlleleFrequency(loci, allele); + freq *= freq; //squared frequencies (expected _homozygosity) + locihet[loci] -= freq; //1 - sum of p2 = expected heterozygosity + } + hs += locihet[loci]; + } + } + return hs; +} + popStats Population::getStats(void) { popStats p; @@ -426,7 +564,8 @@ void Population::extirpate(void) { //--------------------------------------------------------------------------- // Produce juveniles and hold them in the juvs vector -void Population::reproduction(const float localK, const float envval, const int resol) +void Population::reproduction(const float localK, const float envval, const int resol, bool cloneFromColdStorage, + Population* pColdStorage) { // get population size at start of reproduction @@ -457,8 +596,6 @@ void Population::reproduction(const float localK, const float envval, const int emigRules emig = pSpecies->getEmig(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); - genomeData gen = pSpecies->getGenomeData(); - simView v = paramsSim->getViews(); if (dem.repType == 0) nsexes = 1; else nsexes = 2; @@ -594,7 +731,7 @@ void Population::reproduction(const float localK, const float envval, const int } double propBreed; - Individual* father; + Individual* father = nullptr; std::vector fathers; switch (dem.repType) { @@ -629,17 +766,30 @@ void Population::reproduction(const float localK, const float envval, const int nj = (int)juvs.size(); pCell = pPatch->getRandomCell(); for (int j = 0; j < njuvs; j++) { + + Individual* newJuv; + if (cloneFromColdStorage) { + newJuv = pColdStorage->sampleInd()->traitClone(pCell, pPatch, dem.propMales, trfr.moveModel, trfr.moveType); + } + else { #if RSDEBUG - // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... - juvs.push_back(new Individual(pCell, pPatch, 0, 0, 0, 0.0, true, trfr.moveType)); + // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... + newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, true, trfr.moveType); #else - juvs.push_back(new Individual(pCell, pPatch, 0, 0, 0, 0.0, trfr.moveModel, trfr.moveType)); + newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.moveModel, trfr.moveType); #endif - nInds[0][0]++; - if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) - { - // juv inherits genome from parent (mother) - juvs[nj + j]->setGenes(pSpecies, inds[i], 0, resol); + } + + if (pSpecies->getNTraits() > 0) { + newJuv->inheritTraits(pSpecies, inds[i], father, resol); + } + + if (newJuv->getFitness() < pRandom->Random()) { + delete newJuv; + } + else { + juvs.push_back(newJuv); + nInds[0][0]++; } } } @@ -735,18 +885,29 @@ void Population::reproduction(const float localK, const float envval, const int #endif pCell = pPatch->getRandomCell(); for (int j = 0; j < njuvs; j++) { + + Individual* newJuv; + if (cloneFromColdStorage) { + newJuv = pColdStorage->sampleInd()->traitClone(pCell, pPatch, dem.propMales, trfr.moveModel, trfr.moveType); + } + else { #if RSDEBUG - // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... - juvs.push_back(new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, true, trfr.moveType)); + // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... + newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, true, trfr.moveType); #else - juvs.push_back(new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.moveModel, trfr.moveType)); -#endif - sex = juvs[nj + j]->getSex(); - nInds[0][sex]++; - if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) - { - // juv inherits genome from parents - juvs[nj + j]->setGenes(pSpecies, inds[i], father, resol); + newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.moveModel, trfr.moveType); +#endif + } + if (pSpecies->getNTraits() > 0) { + newJuv->inheritTraits(pSpecies, inds[i], father, resol); + } + if (newJuv->getFitness() < pRandom->Random()) { + delete newJuv; + } + else { + juvs.push_back(newJuv); + sex = newJuv->getSex(); + nInds[0][sex]++; } } } @@ -805,6 +966,46 @@ void Population::fledge(void) } +Individual* Population::sampleInd() const { + int index = pRandom->IRandom(0, inds.size() - 1); + return inds[index]; +} + +void Population::sampleIndsWithoutReplacement(string n, const set& sampleStages) { + + sampledInds.clear(); + auto rng = pRandom->getRNG(); + set stagedInds; + + for (int stage : sampleStages) { + auto sInds = getIndividualsInStage(stage); + stagedInds.insert(sInds.begin(), sInds.end()); + } + + if (n == "all" || stagedInds.size() < stoi(n)) + // Sample all individuals in selected stages + sampledInds = stagedInds; + else { + vector out; + // Sample n individuals across selected stages + sample(stagedInds.begin(), stagedInds.end(), std::back_inserter(out), stoi(n), rng); + std::copy(out.begin(), out.end(), std::inserter(sampledInds, sampledInds.end())); + } +} + +int Population::sampleSize() const { + return sampledInds.size(); +} + +set Population::getIndividualsInStage(int stage) { + set filteredInds; + for (auto ind : inds) { + if (ind->getStats().stage == stage) + filteredInds.insert(ind); + } + return filteredInds; +} + // Determine which individuals will disperse void Population::emigration(float localK) { @@ -814,7 +1015,6 @@ void Population::emigration(float localK) stageParams sstruct = pSpecies->getStage(); emigRules emig = pSpecies->getEmig(); emigTraits eparams; - trfrRules trfr = pSpecies->getTrfr(); indStats ind; #if RSDEBUG //DEBUGLOG << "Population::emigration(): this=" << this @@ -896,25 +1096,6 @@ void Population::emigration(float localK) } } - //#if GROUPDISP - //bool newgroup = true; - //int currentsize = 0; - //#endif // GROUPDISP - - //#if PARTMIGRN - //double cumprop[7]; - //cumprop[0] = 0.0; - //for (int i = 1; i < 7; i++) { - // cumprop[i] = cumprop[i-1] + pSpecies->getPropDispMigrn(i); - //#if RSDEBUG - //DEBUGLOG << "Population::emigration(): i=" << i - // << " cumprop[i]=" << cumprop[i] - // << endl; - //#endif - //} - //#endif // PARTMIGRN - // - for (int i = 0; i < ninds; i++) { ind = inds[i]->getStats(); if (ind.status < 1) @@ -985,17 +1166,7 @@ void Population::emigration(float localK) Pdisp = Pemig[0][0]; } } - //#if GROUPDISP - // if (emig.groupdisp) { - // if (Pdisp > 0) { - // - // } - // - // } - //#endif // GROUPDISP } - - } // end of no individual variability disp = pRandom->Bernoulli(Pdisp); @@ -1003,7 +1174,6 @@ void Population::emigration(float localK) //DEBUGLOG << "Population::emigration(): i=" << i << " sex=" << ind.sex << " stage=" << ind.stage // << " Pdisp=" << Pdisp << " disp=" << disp << endl; #endif - if (disp == 1) { // emigrant inds[i]->setStatus(1); } @@ -1041,6 +1211,32 @@ disperser Population::extractDisperser(int ix) { return d; } +Individual* Population::copyForColdStorage(int ix) { + demogrParams dem = pSpecies->getDemogr(); + trfrRules trfr = pSpecies->getTrfr(); + Individual* ind = inds[ix]; + Individual* clone = ind->traitClone(pPatch->getRandomCell(), pPatch, dem.propMales, trfr.moveModel, trfr.moveType); + return clone; +} + +void Population::addEmigTraitsForInd(int ix, emigTraits& avgEmTraits) { + const emigTraits indEmigTraits = inds[ix]->getEmigTraits(); + avgEmTraits.d0 += indEmigTraits.d0; + avgEmTraits.alpha += indEmigTraits.alpha; + avgEmTraits.beta += indEmigTraits.beta; +} + +void Population::addTransferDataForInd(int ix, trfrData* avgTrfrData) { + inds[ix]->getTrfrData()->addMyself(*avgTrfrData); +} + +void Population::addSettleTraitsForInd(int ix, settleTraits& avgSettleTraits) { + const settleTraits settleTraits = inds[ix]->getSettTraits(); + avgSettleTraits.alpha += settleTraits.alpha; + avgSettleTraits.beta += settleTraits.beta; + avgSettleTraits.s0 += settleTraits.s0; +} + // For an individual identified as being in the matrix population: // if it is a settler, return its new location and remove it from the current population // otherwise, leave it in the matrix population for possible reporting before deletion @@ -1248,24 +1444,7 @@ int Population::transfer(Landscape* pLandscape, short landIx) if (localK > 0.0) { // make settlement decision if (settletype.indVar) settDD = inds[i]->getSettTraits(); -#if RS_RCPP else settDD = pSpecies->getSettTraits(ind.stage, ind.sex); -#else - else { - if (settletype.sexDep) { - if (settletype.stgDep) - settDD = pSpecies->getSettTraits(ind.stage, ind.sex); - else - settDD = pSpecies->getSettTraits(0, ind.sex); - } - else { - if (settletype.stgDep) - settDD = pSpecies->getSettTraits(ind.stage, 0); - else - settDD = pSpecies->getSettTraits(0, 0); - } - } -#endif //RS_RCPP settprob = settDD.s0 / (1.0 + exp(-(popsize / localK - (double)settDD.beta) * (double)settDD.alpha)); #if RSDEBUG @@ -1282,15 +1461,6 @@ int Population::transfer(Landscape* pLandscape, short landIx) else { // settlement procluded settle.settleStatus = 1; } -#if RSDEBUG - //DEBUGLOG << "Population::transfer(): 8889: i=" << i - // << " settleStatus=" << settle.settleStatus << " mateOK=" << (int)mateOK; - //if (settle.settleStatus == 2 && mateOK) { - // DEBUGLOG << " SETTLES -"; - // if (ind.sex == 1) DEBUGLOG << " MALE "; else DEBUGLOG << " FEMALE "; - //} - //DEBUGLOG << endl; -#endif settle.pSettPatch = pPatch; } inds[i]->setSettPatch(settle); @@ -1526,11 +1696,6 @@ void Population::survival0(float localK, short option0, short option1) // DEBUGLOG << "Population::survival0(): 2222 " // << " ninds=" << ninds << " localK=" << localK // << " effect of density dependence:" << endl; - // for (int st = 0; st < nStages; st++) { - // for (int sx = 0; sx < nsexes; sx++) { - // DEBUGLOG << "st=" << st << " sx=" << sx << " nInds=" << nInds[st][sx] << endl; - // } - // } #endif // apply density dependence in development and/or survival probabilities for (int stg = 0; stg < nStages; stg++) { @@ -1706,7 +1871,8 @@ void Population::survival1(void) // << endl; #endif if (ind.status > 5) { // doomed to die - delete inds[i]; + if (ind.status != 10) //not going into cold storage + delete inds[i]; inds[i] = NULL; nInds[ind.stage][ind.sex]--; } @@ -1869,7 +2035,7 @@ void Population::outPopulation(int rep, int yr, int gen, float eps, // NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER // ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL demogrParams dem = pSpecies->getDemogr(); - stageParams sstruct = pSpecies->getStage(); + popStats p; outPop << rep << "\t" << yr << "\t" << gen; @@ -2022,6 +2188,7 @@ void Population::outIndsHeaders(int rep, int landNr, bool patchModel) else outInds << "\tNatal_X\tNatal_Y\tX\tY"; if (dem.repType != 0) outInds << "\tSex"; if (dem.stageStruct) outInds << "\tAge\tStage"; + if (pSpecies->getNumberOfAdaptiveTraits() > 0) outInds << "\tFitness"; if (emig.indVar) { if (emig.densDep) outInds << "\tD0\tAlpha\tBeta"; else outInds << "\tEP"; @@ -2126,6 +2293,8 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, if (dem.repType != 0) outInds << "\t" << ind.sex; if (dem.stageStruct) outInds << "\t" << ind.age << "\t" << ind.stage; + if (pSpecies->getNumberOfAdaptiveTraits() > 0) outInds << "\t" << inds[i]->getFitness(); + if (emig.indVar) { emigTraits e = inds[i]->getEmigTraits(); if (emig.densDep) { @@ -2194,56 +2363,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, } } -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// Write records to genetics file -void Population::outGenetics(const int rep, const int year, const int landNr) -{ - - simParams sim = paramsSim->getSim(); - - if (landNr >= 0) { // open file - Genome* pGenome; - genomeData gen = pSpecies->getGenomeData(); - if (gen.trait1Chromosome) { - pGenome = new Genome(pSpecies->getNChromosomes(), pSpecies->getNLoci(0), - pSpecies->isDiploid()); - } - else { - pGenome = new Genome(pSpecies); - } - pGenome->outGenHeaders(rep, landNr, sim.outGenXtab); - delete pGenome; - return; - } - - if (landNr == -999) { // close file - Genome* pGenome = new Genome(); - pGenome->outGenHeaders(rep, landNr, sim.outGenXtab); - delete pGenome; - return; - } - short spNum = pSpecies->getSpNum(); - short nstages = 1; - if (pSpecies->stageStructured()) { - stageParams sstruct = pSpecies->getStage(); - nstages = sstruct.nStages; - } - - - int ninds = (int)inds.size(); - for (int i = 0; i < ninds; i++) { - indStats ind = inds[i]->getStats(); - if (year == 0 || sim.outGenType == 1 - || (sim.outGenType == 0 && ind.stage == 0) - || (sim.outGenType == 2 && ind.stage == nstages - 1)) { - inds[i]->outGenetics(rep, year, spNum, landNr, sim.outGenXtab); - } - } - -} //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- diff --git a/Population.h b/Population.h index 561a429..6a6ab67 100644 --- a/Population.h +++ b/Population.h @@ -41,7 +41,7 @@ Authors: Greta Bocedi & Steve Palmer, University of Aberdeen - Last updated: 22 January 2022 by Steve Palmer + Last updated: 25 June 2021 by Steve Palmer ------------------------------------------------------------------------------*/ @@ -61,6 +61,7 @@ using namespace std; #include "Landscape.h" #include "Patch.h" #include "Cell.h" +#include "NeutralStatsManager.h" //--------------------------------------------------------------------------- @@ -70,6 +71,9 @@ struct popStats { struct disperser { Individual* pInd; Cell* pCell; bool yes; }; +struct zombie { + Individual* pInd; +}; struct traitsums { // sums of trait genes for dispersal int ninds[NSEXES]; // no. of individuals double sumD0[NSEXES]; // sum of maximum emigration probability @@ -102,6 +106,8 @@ struct traitsums { // sums of trait genes for dispersal double ssqAlphaS[NSEXES]; // sum of squares of slope of settlement den-dep reaction norm double sumBetaS[NSEXES]; // sum of inflection point of settlement reaction norm double ssqBetaS[NSEXES]; // sum of squares of inflection point of settlement reaction norm + double sumFitness[NSEXES]; + double ssqFitness[NSEXES]; }; class Population { @@ -127,7 +133,10 @@ class Population { void reproduction( const float, // local carrying capacity const float, // effect of environmental gradient and/or stochasticty - const int // Landscape resolution + const int, // Landscape resolution + bool, + Population* + ); // Following reproduction of ALL species, add juveniles to the population void fledge(void); @@ -145,9 +154,17 @@ class Population { disperser extractSettler( int // index no. to the Individual in the inds vector ); + Individual* copyForColdStorage(int ix); + void addEmigTraitsForInd(int ix, emigTraits&); + void addSettleTraitsForInd(int, settleTraits&); + void addTransferDataForInd(int ix, trfrData* avgTrfrData); void recruit( // Add a specified individual to the population Individual* // pointer to Individual ); + Individual* sampleInd() const; + void sampleIndsWithoutReplacement(string n, const set& sampleStages); + int sampleSize() const; + set getIndividualsInStage(int stage); #if RS_RCPP int transfer( // Executed for the Population(s) in the matrix only Landscape*, // pointer to Landscape @@ -211,13 +228,18 @@ class Population { int, // generation int // Patch number ); - void outGenetics( // Write records to genetics file - const int, // replicate - const int, // year - const int // landscape number - ); + void clean(void); // Remove zero pointers to dead or dispersed individuals + void updateAlleleTable(); + double getAlleleFrequency(int loci, int allele); + int getAlleleCount(int loci, int allele); + double getHetero(int loci, int allele); + int countHeterozygoteLoci(); + vector countLociHeterozyotes(); + double computeHs(); + void updateHeteroTable(); + private: short nStages; short nSexes; @@ -229,6 +251,9 @@ class Population { std::vector juvs; // ... juveniles until reproduction of ALL species // has been completed + std::set sampledInds; + vector alleleTable; + void resetAlleleTable(); }; //--------------------------------------------------------------------------- diff --git a/ProtoTrait.cpp b/ProtoTrait.cpp new file mode 100644 index 0000000..202e88b --- /dev/null +++ b/ProtoTrait.cpp @@ -0,0 +1,172 @@ + +#include "ProtoTrait.h" +#include "Species.h" + +//could be handled in header file but here for now for flexibility +ProtoTrait::ProtoTrait(vector parameters, Species* pSpecies) { + + bool neutralPresent = false; + if (ploidy == 0) this->ploidy = pSpecies->isDiploid() ? 2 : 1; + + this->sex = stringToSex(parameters[2]); + TraitType traitType = stringToTraitType(parameters[1], this->sex); + this->positions = stringToLoci(parameters[3], parameters[4], pSpecies); + this->expressionType = stringToExpressionType(parameters[5]); + this->initialDistribution = stringToDistributionType(parameters[6]); + this->initialParameters = stringToParameterMap(parameters[7]); + this->dominanceDistribution = stringToDistributionType(parameters[8]); + this->dominanceParameters = stringToParameterMap(parameters[9]); + + if (traitType == SNP || traitType == ADAPTIVE) + this->inherited = true; + else + this->inherited = iequals(parameters[10], "true") ? true : false; + + if (this->isInherited()) { + this->mutationDistribution = stringToDistributionType(parameters[11]); + this->mutationParameters = stringToParameterMap(parameters[12]); + this->mutationRate = stof(parameters[13]); + } + + // error outputting for different traits + if (traitType == SNP) { + if (mutationDistribution != KAM && mutationDistribution != SSM) + cout << endl << "Traits file: ERROR - Neutral marker mutation distribution must be KAM or SSM (max = 256))" << endl; + + if (pSpecies->getNumberOfNeutralLoci() > 0) + cout << endl << "Traits file: WARNING - can only have one set of neutral markers, overwriting previous" << endl; + else pSpecies->setNumberOfNeutralLoci(positions.size()); + } +} + +TraitType ProtoTrait::stringToTraitType(const std::string& str, sex_t sex) const { + + if (sex == MAL) { + if (str == "emigration_d0") return E_D0_M; + else if (str == "emigration_alpha") return E_ALPHA_M; + else if (str == "emigration_beta") return E_BETA_M; + else if (str == "settlement_s0") return S_S0_M; + else if (str == "settlement_alpha") return S_ALPHA_M; + else if (str == "settlement_beta") return S_BETA_M; + else if (str == "kernel_meanDistance1") return KERNEL_MEANDIST_1_M; + else if (str == "kernel_meanDistance2") return KERNEL_MEANDIST_2_M; + else if (str == "kernel_probability") return KERNEL_PROBABILITY_M; + else if (str == "crw_stepLength") return CRW_STEPLENGTH_M; + else if (str == "crw_stepCorrelation") return CRW_STEPCORRELATION_M; + } else { + if (str == "emigration_d0") return E_D0_F; + else if (str == "emigration_alpha") return E_ALPHA_F; + else if (str == "emigration_beta") return E_BETA_F; + else if (str == "settlement_s0") return S_S0_F; + else if (str == "settlement_alpha") return S_ALPHA_F; + else if (str == "settlement_beta") return S_BETA_F; + else if (str == "kernel_meanDistance1") return KERNEL_MEANDIST_1_F; + else if (str == "kernel_meanDistance2") return KERNEL_MEANDIST_2_F; + else if (str == "kernel_probability") return KERNEL_PROBABILITY_F; + else if (str == "crw_stepLength") return CRW_STEPLENGTH_F; + else if (str == "crw_stepCorrelation") return CRW_STEPCORRELATION_F; + else if (str == "sms_directionalPersistence") return SMS_DP; + else if (str == "sms_goalBias") return SMS_GB; + else if (str == "sms_alphaDB") return SMS_ALPHADB; + else if (str == "sms_betaDB") return SMS_BETADB; + else if (str == "neutral") return SNP; + else if (str == "adaptive") return ADAPTIVE; + } +} + +ExpressionType ProtoTrait::stringToExpressionType(const std::string& str) const { + if (str == "average") return AVERAGE; + else if (str == "additive") return ADDITIVE; + else if (str == "multiplicative") return MULTIPLICATIVE; + else if (str == "#") return NEUTRAL; +} + +DistributionType ProtoTrait::stringToDistributionType(const std::string& str) const +{ + if (str == "#") return NONE; + else if (str == "uniform") return UNIFORM; + else if (str == "normal") return NORMAL; + else if (str == "gamma") return GAMMA; + else if (str == "scaled") return SCALED; + else if (str == "negExp") return NEGEXP; + else if (str == "KAM") return KAM; + else if (str == "SSM") return SSM; +} + +map ProtoTrait::stringToParameterMap(string parameters) const { + + map paramMap; + if (parameters != "#") { + parameters.erase(remove(parameters.begin(), parameters.end(), '\"'), parameters.end()); + stringstream ss(parameters); + + string value, valueWithin; + while (std::getline(ss, value, ',')) { + stringstream sss(value); + vector paramValue; + while (std::getline(sss, valueWithin, '=')) { + paramValue.push_back(valueWithin); + } + + if (paramValue.size() == 2) { + parameter_t parameterT = paramValue[0]; + float value = stof(paramValue[1]); + paramMap.emplace(parameterT, value); + } + else + cout << endl << "Traits file: ERROR - parameter values for a distribution missing, should be e.g. 'mean=0,standard_deviation=0.5' or if not applicable put #" << endl; + } + } + return paramMap; +} + +set ProtoTrait::selectRandomLociPositions(int noLoci, Species* pSpecies) const { + + int genomeSize = pSpecies->getGenomeSize(); + set positions; + for (int i = 0; i < noLoci; ++i) + positions.insert(pRandom->IRandom(0, genomeSize)); + return positions; +} + + +set ProtoTrait::stringToLoci(string pos, string nLoci, Species* pSpecies) const { + + set positions; + + if (pos != "random") { + //stringstream ss(pos); + + //string value, valueWithin; + //while (std::getline(ss, value, ',')) { + // stringstream sss(value); + // vector minMax; + // while (std::getline(sss, valueWithin, '-')) { + // minMax.push_back(stoi(valueWithin)); + // } + // if (minMax[0] > pSpecies->getGenomeSize() || minMax[1] > pSpecies->getGenomeSize()) { + // cout << endl << "Traits file: ERROR - trait positions must not exceed genome size" << endl; + // } + // else { + // if (minMax.size() > 1) { + // for (int i = minMax[0]; i < minMax[1] + 1; ++i) { + // positions.insert(i); + // } + // } + // else + // positions.insert(minMax[0]); + // } + //} + positions = convertStringToSet(pos); + + for (auto position : positions) { + if (position > pSpecies->getGenomeSize()) + cout << endl << "Traits file: ERROR - trait positions " << position << " must not exceed genome size" << endl; + } + } + else { + positions = selectRandomLociPositions(stoi(nLoci), pSpecies); + } + + return positions; +} diff --git a/ProtoTrait.h b/ProtoTrait.h new file mode 100644 index 0000000..a84949e --- /dev/null +++ b/ProtoTrait.h @@ -0,0 +1,56 @@ +#ifndef PROTOTRAITH +#define PROTOTRAITH + +#include "Parameters.h" +#include +#include +#include +#include + +class Species; + +class ProtoTrait { + +private: + inline static int ploidy = 0; + float mutationRate; + sex_t sex; + set positions; + ExpressionType expressionType; + DistributionType initialDistribution; + map initialParameters; + DistributionType dominanceDistribution; + map dominanceParameters; + bool inherited; + DistributionType mutationDistribution; + map mutationParameters; + +public: + + ProtoTrait(vector parameters, Species* pSpecies); + + // Getters + sex_t getSex() const { return sex; } + float getMutationRate() const { return mutationRate; } + short getPloidy() const { return ploidy; } + set& getPositions() { return positions; } // returning by reference, make sure receiver is const + int getPositionsSize() const { return positions.size(); } + bool isInherited() const { return inherited; } + DistributionType getMutationDistribution() const { return mutationDistribution; }; + map getMutationParameters() const { return mutationParameters; }; + DistributionType getDominanceDistribution() const { return dominanceDistribution; }; + map getDominanceParameters() const { return dominanceParameters; }; + DistributionType getInitialDistribution() const { return initialDistribution; }; + map getInitialParameters() const { return initialParameters; }; + ExpressionType getExpressionType() const { return expressionType; }; + + DistributionType stringToDistributionType(const std::string& str) const; + ExpressionType stringToExpressionType(const std::string& str) const; + map stringToParameterMap(string parameters) const; + + set selectRandomLociPositions(int noLoci, Species* pSpecies) const; + + set stringToLoci(string pos, string nLoci, Species* pSpecies) const; + TraitType stringToTraitType(const std::string& str, sex_t sex) const; +}; +#endif \ No newline at end of file diff --git a/QTLTrait.cpp b/QTLTrait.cpp new file mode 100644 index 0000000..200145a --- /dev/null +++ b/QTLTrait.cpp @@ -0,0 +1,452 @@ +#include "QTLTrait.h" + +// ---------------------------------------------------------------------------------------- +// for initialising population +// ---------------------------------------------------------------------------------------- + +QTLTrait::QTLTrait(ProtoTrait* P) +{ + pProtoTrait = P; + ExpressionType expressionType = pProtoTrait->getExpressionType(); + + if (!pProtoTrait->isInherited()) //there is a trait for individual variation but this isn't inherited variation it's sampled from initial distribution + _inherit_func_ptr = &QTLTrait::inheritInitialParameters; + else { + _inherit_func_ptr = (pProtoTrait->getPloidy() == 1) ? &QTLTrait::inheritHaploid : &QTLTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance + + DistributionType mutationDistribution = pProtoTrait->getMutationDistribution(); + map mutationParameters = pProtoTrait->getMutationParameters(); + + switch (mutationDistribution) { + case UNIFORM: + { + if (!mutationParameters.count(MAX)) + cout << endl << ("Error:: mutation uniform qtl distribution parameter must contain max value (e.g. max= ) \n"); + + if (!mutationParameters.count(MIN)) + cout << endl << ("Error:: mutation uniform qtl distribution parameter must contain min value (e.g. min= ) \n"); + + _mutate_func_ptr = &QTLTrait::mutateUniform; + break; + } + case NORMAL: + { + if (!mutationParameters.count(MEAN)) + cout << endl << ("Error:: qtl mutation distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); + + if (!mutationParameters.count(SDEV)) + cout << endl << ("Error::qtl mutation distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); + + _mutate_func_ptr = &QTLTrait::mutateNormal; + break; + } + + default: + { + cout << endl << ("Error:: wrong parameter value for qtl mutation model, must be uniform/normal \n"); //unless want to add gamma or negative exp + break; //should return false + } + } + } + + DistributionType initialDistribution = pProtoTrait->getInitialDistribution(); + map initialParameters = pProtoTrait->getInitialParameters(); + + switch (initialDistribution) { + case UNIFORM: + { + if (!initialParameters.count(MAX)) + cout << endl << ("Error:: initial uniform qtl distribution parameter must contain max value (e.g. max= ) \n"); + + if (!initialParameters.count(MIN)) + cout << endl << ("Error:: initial uniform qtl distribution parameter must contain min value (e.g. min= ) \n"); + + float maxD = initialParameters.find(MAX)->second; + float minD = initialParameters.find(MIN)->second; + + initialiseUniform(minD, maxD); + break; + } + case NORMAL: + { + if (!initialParameters.count(MEAN)) + cout << endl << ("Error:: initial normal qtl distribution parameter must contain mean value (e.g. mean= ) \n"); + + if (!initialParameters.count(SDEV)) + cout << endl << ("Error:: initial normal qtl distribution parameter must contain sdev value (e.g. sdev= ) \n"); + + float mean = initialParameters.find(MEAN)->second; + float sd = initialParameters.find(SDEV)->second; + + initialiseNormal(mean, sd); + break; + } + + default: + { + cout << endl << ("wrong parameter value for parameter \"initialisation of qtl\", must be uniform/normal \n"); + break; //should return false + } + } + + switch (expressionType) { + case AVERAGE: + { + _express_func_ptr = &QTLTrait::expressAverage; + break; + } + case ADDITIVE: + { + _express_func_ptr = &QTLTrait::expressAdditive; + break; + } + default: + { + cout << endl << ("wrong parameter value for parameter \"expression of qtl\", must be average/additive \n"); + break; //should return false + } + } +} + + +// ---------------------------------------------------------------------------------------- +// for creating new individuals +// ---------------------------------------------------------------------------------------- + +QTLTrait::QTLTrait(const QTLTrait& T) : pProtoTrait(T.pProtoTrait), _mutate_func_ptr(T._mutate_func_ptr), _inherit_func_ptr(T._inherit_func_ptr), _express_func_ptr(T._express_func_ptr) +{} + + + +// ---------------------------------------------------------------------------------------- +// mutate uniform +// ---------------------------------------------------------------------------------------- +void QTLTrait::mutateUniform() +{ + const int positionsSize = pProtoTrait->getPositionsSize(); + const auto& positions = pProtoTrait->getPositions(); + const short ploidy = pProtoTrait->getPloidy(); + const float mutationRate = pProtoTrait->getMutationRate(); + + auto rng = pRandom->getRNG(); + + map mutationParameters = pProtoTrait->getMutationParameters(); + float maxD = mutationParameters.find(MAX)->second; + float minD = mutationParameters.find(MIN)->second; + + for (int p = 0; p < ploidy; p++) { + + unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); + + if (NbMut > 0) { + vector mutationPositions; + sample(positions.begin(), positions.end(), std::back_inserter(mutationPositions), + NbMut, rng); + + for (int m : mutationPositions) { + + auto it = mutations.find(m); + float currentSelCoef = it->second[p].get()->getSelectionCoef();//current + float newSelectionCoef = pRandom->FRandom(minD, maxD) + currentSelCoef; + it->second[p] = make_shared(newSelectionCoef, 1.0); + + } + } + + } + +} + +// ---------------------------------------------------------------------------------------- +// mutate normal +// ---------------------------------------------------------------------------------------- + +void QTLTrait::mutateNormal() +{ + + const int positionsSize = pProtoTrait->getPositionsSize(); + const auto& positions = pProtoTrait->getPositions(); + const short ploidy = pProtoTrait->getPloidy(); + const float mutationRate = pProtoTrait->getMutationRate(); + + auto rng = pRandom->getRNG(); + + + const map mutationParameters = pProtoTrait->getMutationParameters(); + const float mean = mutationParameters.find(MEAN)->second; + const float sd = mutationParameters.find(SDEV)->second; + + + for (int p = 0; p < ploidy; p++) { + + unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); + + if (NbMut > 0) { + vector mutationPositions; + sample(positions.begin(), positions.end(), std::back_inserter(mutationPositions), + NbMut, rng); + + for (int m : mutationPositions) { + + auto it = mutations.find(m); + float currentSelCoef = it->second[p].get()->getSelectionCoef();//current + float newSelectionCoef = pRandom->Normal(mean, sd) + currentSelCoef; + it->second[p] = make_shared(newSelectionCoef, 1.0); + } + } + + + } + +} + +// ---------------------------------------------------------------------------------------- +// inheritance options +// ---------------------------------------------------------------------------------------- + + +void QTLTrait::inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) +{ + + auto parentCast = dynamic_cast (parent); //horrible + + const auto& parent_seq = parentCast->get_mutations(); + if (parent_seq.size() > 0) //else nothing to inherit, should always be something to inherit with QTL + (this->*_inherit_func_ptr) (chromosome, parent_seq, recomPositions, startingChromosome); + + +} + +void QTLTrait::inheritDiploid(sex_t chromosome, map>> const& parentMutations, set const& recomPositions, int parentChromosome) { + + auto it = recomPositions.lower_bound(parentMutations.begin()->first); + + unsigned int nextBreakpoint = *it; + + auto distance = std::distance(recomPositions.begin(), it); + if (distance % 2 != 0) + parentChromosome = !parentChromosome; //switch chromosome + + for (auto const& [key, val] : parentMutations) { + + while (key > nextBreakpoint) { + std::advance(it, 1); + nextBreakpoint = *it; + parentChromosome = !parentChromosome; //switch chromosome + } + + if (key <= nextBreakpoint) { + auto& sp = val[parentChromosome]; + + + auto it = mutations.find(key); + if (it == mutations.end()) { + // not found + vector> vect(2); + vect[chromosome] = sp; + + mutations.insert(make_pair(key, vect)); + } + else { + it->second[chromosome] = sp; + + + } + + + + } + + + + } + + + + + +} + +void QTLTrait::inheritHaploid(sex_t chromosome, map>> const& parentMutations, set const& recomPositions, int parentChromosome) +{ + mutations = parentMutations; +} + +// ---------------------------------------------------------------------------------------- +// 'Inherit' from initialisation parameters, for simulations with individual variation but no inheritance +// ---------------------------------------------------------------------------------------- + +void QTLTrait::inheritInitialParameters(sex_t chromosome, map>> const& parentMutations, set const& recomPositions, int parentChromosome) +{ + DistributionType initialDistribution = pProtoTrait->getInitialDistribution(); + map initialParameters = pProtoTrait->getInitialParameters(); + + + switch (initialDistribution) { + case UNIFORM: + { + if (!initialParameters.count(MAX)) + cout << endl << ("Error:: initial uniform qtl distribution parameter must contain max value (e.g. max= ) \n"); + + if (!initialParameters.count(MIN)) + cout << endl << ("Error:: initial uniform qtl distribution parameter must contain min value (e.g. min= ) \n"); + + float maxD = initialParameters.find(MAX)->second; + float minD = initialParameters.find(MIN)->second; + + initialiseUniform(minD, maxD); + + break; + } + case NORMAL: + { + if (!initialParameters.count(MEAN)) + cout << endl << ("Error:: initial normal qtl distribution parameter must contain mean value (e.g. mean= ) \n"); + + if (!initialParameters.count(SDEV)) + cout << endl << ("Error:: initial normal qtl distribution parameter must contain sdev value (e.g. sdev= ) \n"); + + float mean = initialParameters.find(MEAN)->second; + float sd = initialParameters.find(SDEV)->second; + + initialiseNormal(mean, sd); + + break; + } + + default: + { + cout << endl << ("wrong parameter value for parameter \"initialisation of qtl\", must be uniform/normal \n"); + break; //should return false + } + } +} + + +// ---------------------------------------------------------------------------------------- +// Initialisation options +// ---------------------------------------------------------------------------------------- + + +void QTLTrait::initialiseNormal(float mean, float sd) { + + const auto positions = pProtoTrait->getPositions(); + short ploidy = pProtoTrait->getPloidy(); + + for (auto position : positions) { + vector> vect; + + for (int i = 0; i < ploidy; i++) { + float selectionCoef = pRandom->Normal(mean, sd); + vect.emplace_back(make_shared(selectionCoef, 1.0));//crude here to set dominance to 1 for qtl but can be changed later + } + mutations.insert(make_pair(position, vect)); + } +} + +void QTLTrait::initialiseUniform(float min, float max) { + + const auto positions = pProtoTrait->getPositions(); + short ploidy = pProtoTrait->getPloidy(); + + for (auto position : positions) { + vector> vect; + + for (int i = 0; i < ploidy; i++) { + float selectionCoef = pRandom->FRandom(min, max); + vect.emplace_back(make_shared(selectionCoef, 1.0)); //crude here to set dominance to 1 for qtl but can be changed later + } + mutations.insert(make_pair(position, vect)); + } +} + +// ---------------------------------------------------------------------------------------- +// expression options +// ---------------------------------------------------------------------------------------- + +float QTLTrait::expressAdditive() { + + float phenotype = 0.0; + + for (auto const& [key, val] : mutations) + { + for (auto m : val) + phenotype += m->getSelectionCoef(); + } + + return phenotype; +} + +float QTLTrait::expressAverage() { + + int positionsSize = pProtoTrait->getPositionsSize(); + short ploidy = pProtoTrait->getPloidy(); + float phenotype = 0.0; + + for (auto const& [key, val] : mutations) + { + for (auto& m : val) + phenotype += m->getSelectionCoef(); + } + phenotype = phenotype / (positionsSize * ploidy); + return phenotype; +} + +// ---------------------------------------------------------------------------------------- +// check if particular loci is heterozygote +// ---------------------------------------------------------------------------------------- + + +bool QTLTrait::isHeterozygoteAtLoci(int loci) const { + + auto it = mutations.find(loci); + + if (it == mutations.end()) //not found + return false; + else { + if (it->second.size() == 1) //only one ptr there so must be allele and wildtype at loci (heterozygote) + return true; + else + return(it->second[0].get()->getId() != it->second[1].get()->getId()); + + } +} + +// ---------------------------------------------------------------------------------------- +// count heterozygote loci in genome +// ---------------------------------------------------------------------------------------- + + +int QTLTrait::countHeterozygoteLoci() const { + + int count = 0; + + for (auto const& [key, val] : mutations) { + + if (val.size() == 1) //only one ptr there so must be allele and wildtype at loci (heterozygote) + count++; + + if (val.size() == 2) + count += (val[0].get()->getId() != val[1].get()->getId()); + } + + return count; +} + +// ---------------------------------------------------------------------------------------- +// get allele value at loci +// ---------------------------------------------------------------------------------------- + + +float QTLTrait::getSelectionCoefAtLoci(short chromosome, int position) const { + + auto it = mutations.find(position); + + if (it == mutations.end()) { //no mutations there, should never happen at QTLs should always hold a value + return 0; //must still be wildtype at loci + cout << endl << ("Error:: trying to find QTL at ", position, " but doesn't exist \n"); + } + else + return it->second[chromosome].get()->getSelectionCoef(); + +} \ No newline at end of file diff --git a/QTLTrait.h b/QTLTrait.h new file mode 100644 index 0000000..98cbc00 --- /dev/null +++ b/QTLTrait.h @@ -0,0 +1,56 @@ +#ifndef QTLTRAITH +#define QTLTRAITH + +#include +#include + +#include "TTrait.h" + +using namespace std; + + +class QTLTrait : public TTrait { + +private: + + ProtoTrait* pProtoTrait; // would be better as const so immutable, but means passing positions list is heavy and can't be passed by reference + + map>> mutations; //position > + + void (QTLTrait::* _mutate_func_ptr) (void); + void (QTLTrait::* _inherit_func_ptr) (sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); + float (QTLTrait::* _express_func_ptr) (void); + + void initialiseUniform(float min, float max); + void initialiseNormal(float mean, float sd); + void inheritDiploid(sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); + void inheritHaploid(sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); + void inheritInitialParameters(sex_t chromosome, map>> const& parentMutations, set const& recomPositions, int parentChromosome); + void mutateUniform(); + void mutateNormal(); + float expressAverage(); + float expressAdditive(); + +public: + + //this one for species held trait table, e.g. prototype table, sets static members + QTLTrait(ProtoTrait* P); + QTLTrait(const QTLTrait& T); + virtual unique_ptr clone() const override { return std::make_unique(*this); } + int getNLoci() const override { return pProtoTrait->getPositionsSize(); } + float getMutationRate() const override { return pProtoTrait->getMutationRate(); } + bool isInherited() const override { return pProtoTrait->isInherited(); } + void mutate() override { (this->*_mutate_func_ptr) (); } + float express() override { return (this->*_express_func_ptr) (); } + void inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) override; + map>>& get_mutations() { return mutations; } // returning reference, receiver must be const + + // virtual float getSelectionCoefAtLoci(short chromosome, int i) const override { return (double)mutations[chromosome][i]->getSelectionCoef(); } + + float getSelectionCoefAtLoci(short chromosome, int i) const override; + int countHeterozygoteLoci() const; + bool isHeterozygoteAtLoci(int loci) const override; + virtual ~QTLTrait() { } +}; + +#endif \ No newline at end of file diff --git a/RSrandom.cpp b/RSrandom.cpp index c4c569b..d7153b0 100644 --- a/RSrandom.cpp +++ b/RSrandom.cpp @@ -36,78 +36,99 @@ extern paramSim* paramsSim; int RS_random_seed = 0; // C'tor -RSrandom::RSrandom() -{ +RSrandom::RSrandom() { #if RSDEBUG - // fixed seed - RS_random_seed = 666; + // fixed seed + RS_random_seed = 666; #else - // random seed + // random seed #if LINUX_CLUSTER - std::random_device device; - RS_random_seed = device(); // old versions of g++ on Windows return a constant value within a given Windows - // session; in this case better use time stamp + std::random_device device; + RS_random_seed = device(); // old versions of g++ on Windows return a constant value within a given Windows + // session; in this case better use time stamp #else - RS_random_seed = std::time(NULL); + RS_random_seed = std::time(NULL); #endif #endif // RSDEBUG #if BATCH && RSDEBUG - DEBUGLOG << "RSrandom::RSrandom(): RS_random_seed=" << RS_random_seed << endl; + DEBUGLOG << "RSrandom::RSrandom(): RS_random_seed=" << RS_random_seed << endl; #endif // RSDEBUG - // set up Mersenne Twister RNG - gen = new mt19937(RS_random_seed); + // set up Mersenne Twister RNG + gen = new mt19937(RS_random_seed); - // Set up standard uniform distribution - pRandom01 = new uniform_real_distribution(0.0, 1.0); - // Set up standard normal distribution - pNormal = new normal_distribution(0.0, 1.0); + // Set up standard uniform distribution + pRandom01 = new uniform_real_distribution(0.0, 1.0); + // Set up standard normal distribution + pNormal = new normal_distribution(0.0, 1.0); } -RSrandom::~RSrandom(void) -{ - delete gen; - if (pRandom01 != 0) - delete pRandom01; - if (pNormal != 0) - delete pNormal; +RSrandom::~RSrandom(void) { + delete gen; + if (pRandom01 != 0) + delete pRandom01; + if (pNormal != 0) + delete pNormal; } -mt19937 RSrandom::getRNG(void) -{ - return *gen; +mt19937 RSrandom::getRNG(void) { + return *gen; } -double RSrandom::Random(void) -{ - // return random number between 0 and 1 - return pRandom01->operator()(*gen); +double RSrandom::Random(void) { + // return random number between 0 and 1 + return pRandom01->operator()(*gen); } -int RSrandom::IRandom(int min, int max) -{ - // return random integer in the interval min <= x <= max - uniform_int_distribution unif(min, max); - return unif(*gen); +int RSrandom::IRandom(int min, int max) { + // return random integer in the interval min <= x <= max + if (min == max) + return min; + + uniform_int_distribution unif(min, max); + return unif(*gen); } -int RSrandom::Bernoulli(double p) -{ - return Random() < p; +float RSrandom::FRandom(float min, float max) { + if (min == max) + return min; + // return random double in the interval min <= x <= max + uniform_real_distribution unif(min, max); + return unif(*gen); } -double RSrandom::Normal(double mean, double sd) -{ - return mean + sd * pNormal->operator()(*gen); +int RSrandom::Bernoulli(double p) { + return Random() < p; } -int RSrandom::Poisson(double mean) -{ - poisson_distribution poiss(mean); - return poiss(*gen); +double RSrandom::Normal(double mean, double sd) { + return mean + sd * pNormal->operator()(*gen); +} + +int RSrandom::Poisson(double mean) { + poisson_distribution poiss(mean); + return poiss(*gen); } +double RSrandom::Gamma(double shape, double scale) { //scale = mean/shape, shape must be positive and scale can be positive or negative + + gamma_distribution<> gamma(shape, abs(scale)); + + double x = gamma(*gen); + if (scale < 0) x = -x; + return x; +} + +double RSrandom::NegExp(double mean) { + double r1 = 0.0000001 + this->Random() * (1.0 - 0.0000001); + double x = (-1.0 * mean) * log(r1); // for LINUX_CLUSTER + return x; +} + +void RSrandom::fixNewSeed(int seed) { + gen->seed(seed); +} //-------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------- @@ -185,10 +206,21 @@ double RSrandom::Random(void) { int RSrandom::IRandom(int min, int max) { // return random integer in the interval min <= x <= max + if (min == max) + return min; + uniform_int_distribution unif(min, max); return unif(*gen); } +float RSrandom::FRandom(float min, float max) { + if (min == max) + return min; + // return random double in the interval min <= x <= max + uniform_real_distribution unif(min, max); + return unif(*gen); +} + int RSrandom::Bernoulli(double p) { return Random() < p; } @@ -202,6 +234,24 @@ int RSrandom::Poisson(double mean) { return poiss(*gen); } +double RSrandom::Gamma(double shape, double scale) { //scale = mean/shape, shape must be positive and scale can be positive or negative + + gamma_distribution<> gamma(shape, abs(scale)); + + double x = gamma(*gen); + if (scale < 0) x = -x; + return x; +} + +double RSrandom::NegExp(double mean) { + double r1 = 0.0000001 + this->Random() * (1.0 - 0.0000001); + double x = (-1.0 * mean) * log(r1); // for LINUX_CLUSTER + return x; +} + +void RSrandom::fixNewSeed(int seed) { + gen->seed(seed); +} /* ADDITIONAL DISTRIBUTIONS diff --git a/RSrandom.h b/RSrandom.h index 8ad9a99..4b50ccb 100644 --- a/RSrandom.h +++ b/RSrandom.h @@ -40,14 +40,9 @@ #include //#include - //#if RS_RCPP && !R_CMD +//#if RS_RCPP && !R_CMD #include "../Version.h" //#endif - -//#if !RS_RCPP && R_CMD -//#include "../../Batch/Version.h" -//#endif - using namespace std; #if RSDEBUG @@ -66,6 +61,7 @@ extern ofstream DEBUGLOG; #if !LINUX_CLUSTER #include #endif +#include class RSrandom { @@ -75,10 +71,14 @@ class RSrandom ~RSrandom(void); double Random(void); int IRandom(int, int); + float FRandom(float, float); int Bernoulli(double); double Normal(double, double); + double Gamma(double, double); + double NegExp(double); int Poisson(double); mt19937 getRNG(void); + void fixNewSeed(int); private: mt19937* gen; @@ -103,6 +103,7 @@ class RSrandom #if RSWIN64 #include #endif +#include class RSrandom { @@ -112,9 +113,13 @@ class RSrandom { mt19937 getRNG(void); double Random(void); int IRandom(int, int); + float FRandom(float, float); int Bernoulli(double); double Normal(double, double); + double Gamma(double, double); + double NegExp(double); int Poisson(double); + void fixNewSeed(int); /* ADDITIONAL DISTRIBUTIONS double Beta(double,double); double Gamma(double,double); // !! make sure correct definition is used: using shape and scale (as defined here) OR using shape/alpha and rate/beta (=1/scale) diff --git a/RandomCheck.cpp b/RandomCheck.cpp deleted file mode 100644 index 8468958..0000000 --- a/RandomCheck.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * - * This file is part of RangeShifter. - * - * RangeShifter 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 3 of the License, or - * (at your option) any later version. - * - * RangeShifter is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RangeShifter. If not, see . - * - --------------------------------------------------------------------------*/ - - - //--------------------------------------------------------------------------- - -#include "RandomCheck.h" -//--------------------------------------------------------------------------- - -ifstream inRandom; -ofstream outRandom; -ofstream outBernoulli; -ofstream outNormal; -ofstream outPoisson; -ofstream outIRandom; - -void randomCheck(void) -{ - - int samplesize, irandMin, irandMax; - double bernMean, normMean, normSD, poisMean; - string name, header; - simParams sim = paramsSim->getSim(); - - name = paramsSim->getDir(1) + "RandomCheck.txt"; - inRandom.open(name.c_str()); - if (!inRandom.is_open()) { -#if !RS_RCPP - cout << endl << "***** Error opening input file RandomCheck.txt" << endl; -#endif - inRandom.clear(); - return; - } - for (int i = 0; i < 7; i++) { - inRandom >> header; - } - inRandom >> samplesize >> bernMean >> normMean >> normSD >> poisMean >> irandMin >> irandMax; - - name = paramsSim->getDir(2) + "Random.txt"; - outRandom.open(name.c_str()); - name = paramsSim->getDir(2) + "Bernoulli.txt"; - outBernoulli.open(name.c_str()); - name = paramsSim->getDir(2) + "Normal.txt"; - outNormal.open(name.c_str()); - name = paramsSim->getDir(2) + "Poisson.txt"; - outPoisson.open(name.c_str()); - name = paramsSim->getDir(2) + "IRandom.txt"; - outIRandom.open(name.c_str()); - - for (int i = 0; i < samplesize; i++) { - outRandom << pRandom->Random() << endl; - outBernoulli << pRandom->Bernoulli(bernMean) << endl; - outNormal << pRandom->Normal(normMean, normSD) << endl; - outPoisson << pRandom->Poisson(poisMean) << endl; - outIRandom << pRandom->IRandom(irandMin, irandMax) << endl; - } - - inRandom.close(); - inRandom.clear(); - outRandom.close(); - outRandom.clear(); - outBernoulli.close(); - outBernoulli.clear(); - outNormal.close(); - outNormal.clear(); - outPoisson.close(); - outPoisson.clear(); - outIRandom.close(); - outIRandom.clear(); - -} - -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- diff --git a/RandomCheck.h b/RandomCheck.h deleted file mode 100644 index 69e1128..0000000 --- a/RandomCheck.h +++ /dev/null @@ -1,47 +0,0 @@ -/*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * - * This file is part of RangeShifter. - * - * RangeShifter 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 3 of the License, or - * (at your option) any later version. - * - * RangeShifter is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RangeShifter. If not, see . - * - --------------------------------------------------------------------------*/ - - - //--------------------------------------------------------------------------- - -#ifndef RandomCheckH -#define RandomCheckH - -#include -using namespace std; - -//#if RS_RCPP && !R_CMD -#include "../Version.h" -//#endif - -//#if !RS_RCPP && R_CMD -//#include "../../Batch/Version.h" -//#endif -#include "Parameters.h" -#include "RSrandom.h" - -void randomCheck(void); - -extern paramSim* paramsSim; -extern RSrandom* pRandom; - -//--------------------------------------------------------------------------- -#endif diff --git a/SNPTrait.cpp b/SNPTrait.cpp new file mode 100644 index 0000000..d19b35b --- /dev/null +++ b/SNPTrait.cpp @@ -0,0 +1,326 @@ +#include "SNPTrait.h" + +// ---------------------------------------------------------------------------------------- +// for initialising population +// ---------------------------------------------------------------------------------------- +SNPTrait::SNPTrait(ProtoTrait* P) +{ + pProtoTrait = P; + + DistributionType mutationDistribution = pProtoTrait->getMutationDistribution(); + map mutationParameters = pProtoTrait->getMutationParameters(); + + _inherit_func_ptr = (pProtoTrait->getPloidy() == 1) ? &SNPTrait::inheritHaploid : &SNPTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance + + if (mutationDistribution == SSM) + _mutate_func_ptr = &SNPTrait::mutate_SSM; + + if (mutationDistribution == KAM) + _mutate_func_ptr = &SNPTrait::mutate_KAM; + + if (mutationDistribution != SSM && mutationDistribution != KAM) + cout << endl << ("Error:: wrong mutation distribution for neutral markers, must be KAM or SSM \n"); + + if (!mutationParameters.count(MAX)) + cout << endl << ("Error:: KAM or SSM mutation distribution parameter must contain max value (e.g. max= ), max cannot exceed 256 \n"); + + if (wildType == -999) + wildType = (int)mutationParameters.find(MAX)->second - 1; + + if (wildType > 255) + cout << endl << ("Error:: max number of alleles cannot exceed 256 \n"); + + DistributionType initialDistribution = pProtoTrait->getInitialDistribution(); + map initialParameters = pProtoTrait->getInitialParameters(); + + if (mutationDistribution == SSM && initialDistribution != UNIFORM) + cout << endl << ("Error:: If using SSM mutation model must initialise genome with alleles (microsats) \n"); + + switch (initialDistribution) { + case UNIFORM: + { + if (!initialParameters.count(MAX)) + cout << endl << ("Error:: initial SNP/Microsat distribution parameter must contain max value if set to UNIFORM (e.g. max= ), max cannot exceed 256 \n"); + + float maxD = initialParameters.find(MAX)->second; + if (maxD > 256) { + cout << endl << ("Warning:: initial SNP/Microsat distribution parameter max cannot exceed 256, resetting to 256 \n"); + + maxD = 256; //reserve 255 for wildtype + } + initialiseFull(maxD); + + break; + } + case NONE: + { + break; + } + default: + { + cout << endl << ("wrong parameter value for parameter \"initialisation of snp/microsat\", must be left as default (#) or uniform \n"); + break; //should return false + } + } +} + +// ---------------------------------------------------------------------------------------- +// for creating new individuals +// ---------------------------------------------------------------------------------------- + +SNPTrait::SNPTrait(const SNPTrait& T) : + pProtoTrait(T.pProtoTrait), _mutate_func_ptr(T._mutate_func_ptr), _inherit_func_ptr(T._inherit_func_ptr) { + +} + + +// ---------------------------------------------------------------------------------------- +// mutate options +// ---------------------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------------------- +// mutate_KAM +// ---------------------------------------------------------------------------------------- +void SNPTrait::mutate_KAM() +{ + + const int positionsSize = pProtoTrait->getPositionsSize(); + const auto& positions = pProtoTrait->getPositions(); + const short ploidy = pProtoTrait->getPloidy(); + const float mutationRate = pProtoTrait->getMutationRate(); + auto rng = pRandom->getRNG(); + unsigned char mut; + + map mutationParameters = pProtoTrait->getMutationParameters(); + + + int maxD = (int)mutationParameters.find(MAX)->second; + + if (maxD > 256) maxD = 256; //reserve max value -1 for wildtype + + for (int p = 0; p < ploidy; p++) { + + unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); + + if (NbMut > 0) { + vector mutationPositions; + sample(positions.begin(), positions.end(), std::back_inserter(mutationPositions), + NbMut, rng); + + for (int m : mutationPositions) { + + mut = (unsigned char)pRandom->IRandom(0, maxD - 1); //draw new mutation, could draw wildtype + auto it = mutations.find(m); //find if position in map already has mutations there + + if (it == mutations.end()) { // not found so create new entry in map with wildtype as char default + + vector vect(2, wildType); + vect[p] = mut; //put new mutation value in + + mutations.insert(make_pair(m, vect)); + } + else { //position found, already mutations there + + auto currentChar = it->second[p]; //current mutation + do { + mut = (unsigned char)pRandom->IRandom(0, maxD - 1); //make sure new value differs from old , could be a problem here with infinite loops + } while (mut == currentChar); + + it->second[p] = mut; //overwrite with new value + + } + + + } + } + + + } + + +} + + +// ---------------------------------------------------------------------------------------- +// mutate_SSM +// ---------------------------------------------------------------------------------------- +void SNPTrait::mutate_SSM() +{ + const int positionsSize = pProtoTrait->getPositionsSize(); + const auto& positions = pProtoTrait->getPositions(); + const short ploidy = pProtoTrait->getPloidy(); + const float mutationRate = pProtoTrait->getMutationRate(); + auto rng = pRandom->getRNG(); + + map mutationParameters = pProtoTrait->getMutationParameters(); + + int maxD = (int)mutationParameters.find(MAX)->second; + if (maxD > 256) maxD = 256; //reserved max value for wildtype + + for (int p = 0; p < ploidy; p++) { + + unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); + + if (NbMut > 0) { + vector mutationPositions; + sample(positions.begin(), positions.end(), std::back_inserter(mutationPositions), + NbMut, rng); + + for (int m : mutationPositions) { + + int mutateForward = pRandom->Bernoulli(0.5); + auto it = mutations.find(m); + auto currentAllele = it->second[p];//current + //alleles values are from 0 to maxD - 1 + if (mutateForward && currentAllele < maxD - 1) + it->second[p] += 1; //one step to the right + else if (currentAllele > 0) // !direction || all==_allele_num + it->second[p] -= 1; //one step to the left + else //!direction && all == 0 + it->second[p] += 1; + + + } + + } + } + +} + +// ---------------------------------------------------------------------------------------- +// inheritance options +// ---------------------------------------------------------------------------------------- + +void SNPTrait::inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) +{ + + auto parentCast = dynamic_cast (parent); //horrible + + const auto& parent_seq = parentCast->get_mutations(); + if (parent_seq.size() > 0) //else nothing to inherit + (this->*_inherit_func_ptr) (chromosome, parent_seq, recomPositions, startingChromosome); + +} + + + +void SNPTrait::inheritDiploid(sex_t chromosome, map> const& parentMutations, set const& recomPositions, int parentChromosome) { + + if (parentMutations.size() > 0) { + auto it = recomPositions.lower_bound(parentMutations.begin()->first); + + unsigned int nextBreakpoint = *it; + + auto distance = std::distance(recomPositions.begin(), it); + if (distance - 1 % 2 != 0) + parentChromosome = !parentChromosome; //switch chromosome + + + for (auto const& [key, val] : parentMutations) { + + while (key > nextBreakpoint) { + std::advance(it, 1); + nextBreakpoint = *it; + parentChromosome = !parentChromosome; //switch chromosome + } + + if (key <= nextBreakpoint) { + unsigned char sp = val[parentChromosome]; + + + auto it = mutations.find(key); + if (it == mutations.end()) { + // not found + vector vect(2, wildType); + vect[chromosome] = sp; + mutations.insert(make_pair(key, vect)); + + } + else { + it->second[chromosome] = sp; + } + + + } + + + + } + } +} + +void SNPTrait::inheritHaploid(sex_t chromosome, map> const& parentMutations, set const& recomPositions, int parentChromosome) +{ + mutations = parentMutations; +} + +// ---------------------------------------------------------------------------------------- +// Initialise neutral loci +// ---------------------------------------------------------------------------------------- + +void SNPTrait::initialiseFull(int max) +{ + + const auto& positions = pProtoTrait->getPositions(); + short ploidy = pProtoTrait->getPloidy(); + + for (auto position : positions) { + vector vect; + + for (int i = 0; i < ploidy; i++) { + + auto mut = (unsigned char)pRandom->IRandom(0, max - 1); // allele values span 0 - max (255 ceiling) inclusive, max == wildtype + vect.emplace_back(mut); + } + mutations.insert(make_pair(position, vect)); + + + } +} + + +// ---------------------------------------------------------------------------------------- +// check if particular loci is heterozygote +// ---------------------------------------------------------------------------------------- + + +bool SNPTrait::isHeterozygoteAtLoci(int loci) const { + + auto it = mutations.find(loci); + + if (it == mutations.end()) //not found + return false; + else + return(it->second[0] != it->second[1]); +} + +// ---------------------------------------------------------------------------------------- +// count heterozygote loci in genome +// ---------------------------------------------------------------------------------------- + +int SNPTrait::countHeterozygoteLoci() const { + + int count = 0; + + for (auto const& [key, val] : mutations) { + count += (val[0] != val[1]); + } + + return count; +} + +// ---------------------------------------------------------------------------------------- +// get allele value at loci +// ---------------------------------------------------------------------------------------- + + +float SNPTrait::getSelectionCoefAtLoci(short chromosome, int position) const { + + auto it = mutations.find(position); + + if (it == mutations.end()) //no mutations there + return wildType; //must still be wildtype at loci + else + return it->second[chromosome]; + +} \ No newline at end of file diff --git a/SNPTrait.h b/SNPTrait.h new file mode 100644 index 0000000..405442c --- /dev/null +++ b/SNPTrait.h @@ -0,0 +1,79 @@ +#ifndef SNPTRAITH +#define SNPTRAITH + + + +#include +#include + +#include "TTrait.h" + +using namespace std; + +class SNPTrait : public TTrait { + +private: + + inline static int wildType = -999; + + ProtoTrait* pProtoTrait; + + //vector> mutations; + + map> mutations; //position > + + + void (SNPTrait::* _mutate_func_ptr) (void); + void (SNPTrait::* _inherit_func_ptr) (sex_t chromosome, map> const& parent, set const& recomPositions, int parentChromosome); + + + void inheritDiploid(sex_t chromosome, map> const&, set const& recomPositions, int parentChromosome); + + void inheritHaploid(sex_t chromosome, map> const& parentMutations, set const& recomPositions, int parentChromosome); + + void initialiseFull(int max); //other option is that mutations map is empty until a mutation happens, default when empty is to return a 0 value for wildtype + + void mutate_KAM(); + void mutate_SSM(); + + + + +public: + + //this one for species held trait table, e.g. prototype table, sets static members + + SNPTrait(ProtoTrait* P); + + //this one for individuals, static members are not reset + SNPTrait(const SNPTrait& T); + + + virtual unique_ptr clone() const override { return std::make_unique(*this); } + + + virtual void inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) override; + + + virtual void mutate() override { (this->*_mutate_func_ptr) (); } + + virtual int getNLoci() const override { return pProtoTrait->getPositionsSize(); } + + + float getMutationRate() const override { return pProtoTrait->getMutationRate(); } + + bool isInherited() const override { return pProtoTrait->isInherited(); } + + map>& get_mutations() { return mutations; } //returning reference, reciever must be const + + virtual float getSelectionCoefAtLoci(short chromosome, int position) const override; + + virtual int countHeterozygoteLoci() const; + + virtual bool isHeterozygoteAtLoci(int loci) const override; + + virtual float express() { return -9999; } + + virtual ~SNPTrait() { } +}; +#endif \ No newline at end of file diff --git a/Species.cpp b/Species.cpp index 75e9b92..3ee450b 100644 --- a/Species.cpp +++ b/Species.cpp @@ -48,24 +48,6 @@ Species::Species(void) habK = 0; habDimK = 0; minRK = 1.0; maxRK = 2.0; - // initialise genome attributes - nChromosomes = nTraits = 0; - emigTrait[0] = 0; emigTrait[1] = 0; - movtTrait[0] = 0; movtTrait[1] = 0; - settTrait[0] = 0; settTrait[1] = 0; - //genomeCanRecombine = false; - diploid = true; - neutralMarkers = false; - pleiotropic = false; - trait1Chromosome = true; - probMutn = 0.0001f; - probCrossover = 0.0001f; - alleleSD = mutationSD = 0.1f; - nNLoci = 0; - nLoci = NULL; - traitdata = NULL; - traitnames = NULL; - nTraitNames = 0; // initialise emigration parameters densDepEmig = false; stgDepEmig = false; sexDepEmig = false; indVarEmig = false; @@ -75,11 +57,6 @@ Species::Species(void) d0[i][j] = 0.0; alphaEmig[i][j] = 0.0; betaEmig[i][j] = 1.0; } } - for (int j = 0; j < NSEXES; j++) { - d0Mean[0][j] = 0.0; alphaMean[0][j] = 0.0; betaMean[0][j] = 1.0; - d0SD[0][j] = 0.0; alphaSD[0][j] = 0.0; betaSD[0][j] = 1.0; - } - d0Scale = alphaScale = betaScale = 0.0; // initialise transfer parameters moveModel = false; stgDepTrfr = false; sexDepTrfr = false; distMort = false; @@ -93,25 +70,12 @@ Species::Species(void) meanDist1[i][j] = 100.0f; meanDist2[i][j] = 1000.0f; probKern1[i][j] = 0.99f; } } - for (int j = 0; j < NSEXES; j++) { - dist1Mean[0][j] = 100.0; dist1SD[0][j] = 10.0; - dist2Mean[0][j] = 1000.0; dist2SD[0][j] = 100.0; - PKern1Mean[0][j] = 0.9f; PKern1SD[0][j] = 0.01f; - stepLgthMean[0][j] = 10.0; stepLgthSD[0][j] = 1.0; - rhoMean[0][j] = 0.9f; rhoSD[0][j] = 0.01f; - dpMean[0][j] = 1.0; dpSD[0][j] = 0.1f; - gbMean[0][j] = 1.0; gbSD[0][j] = 0.1f; - alphaDBMean[0][j] = 1.0; alphaDBSD[0][j] = 0.1f; - betaDBMean[0][j] = 10.0; betaDBSD[0][j] = 1.0; - } pr = 1; prMethod = 1; memSize = 1; goalType = 0; dp = 1.0; gb = 1.0; alphaDB = 1.0; betaDB = 100000; stepMort = 0.0; stepLength = 10.0; rho = 0.9f; habStepMort = 0; habCost = 0; //costMapFile = "NULL"; fixedMort = 0.0; mortAlpha = 0.0; mortBeta = 1.0; - dist1Scale = dist2Scale = PKern1Scale = stepLScale = rhoScale = 0.0; - dpScale = 0.1f; gbScale = 0.1f; alphaDBScale = 0.1f; betaDBScale = 1.0; habDimTrfr = 0; straigtenPath = false; fullKernel = false; @@ -126,16 +90,10 @@ Species::Species(void) s0[i][j] = 1.0; alphaS[i][j] = 0.0; betaS[i][j] = 1.0; } } - for (int j = 0; j < NSEXES; j++) { - alphaSMean[0][j] = 0.0; alphaSSD[0][j] = 0.0; - betaSMean[0][j] = 0.0; betaSSD[0][j] = 0.0; - s0Mean[0][j] = 0.0; s0SD[0][j] = 0.0; - } - alphaSScale = 0.0; betaSScale = 0.0; s0Scale = 0.0; - // initialise attributes + // initialise attribute defaults spNum = 0; - + resetGeneticParameters(); } Species::~Species() { @@ -146,9 +104,6 @@ Species::~Species() { if (ddwtSurv != 0) deleteDDwtSurv(); // transfer parameters if (habCost != 0 || habStepMort != 0) deleteHabCostMort(); - if (nLoci != NULL) deleteLoci(); - if (traitdata != NULL) deleteTraitData(); - if (traitnames != NULL) deleteTraitNames(); } short Species::getSpNum(void) { return spNum; } @@ -159,6 +114,7 @@ short Species::getSpNum(void) { return spNum; } void Species::setDemogr(const demogrParams d) { if (d.repType >= 0 && d.repType <= 2) repType = d.repType; + if (d.repType >= 1) isDiploid = true; if (d.repSeasons >= 1) repSeasons = d.repSeasons; stageStruct = d.stageStruct; if (d.propMales > 0.0 && d.propMales < 1.0) propMales = d.propMales; @@ -419,537 +375,137 @@ float Species::getMinMax(short opt) { //--------------------------------------------------------------------------- -// Genome functions +// Genetic functions -void Species::setGenomeData(genomeData d) { - diploid = d.diploid; - neutralMarkers = d.neutralMarkers; - trait1Chromosome = d.trait1Chromosome; - if (trait1Chromosome) { - if (d.nLoci > 0) nLoci[0] = d.nLoci; - } - if (d.probMutn >= 0.0 && d.probMutn <= 1.0) probMutn = d.probMutn; - if (d.probCrossover >= 0.0 && d.probCrossover <= 1.0) probCrossover = d.probCrossover; - if (d.alleleSD > 0.0) alleleSD = d.alleleSD; - if (d.mutationSD > 0.0) mutationSD = d.mutationSD; -} - -genomeData Species::getGenomeData(void) { - genomeData d; - d.diploid = diploid; - d.neutralMarkers = neutralMarkers; - d.pleiotropic = pleiotropic; - d.trait1Chromosome = trait1Chromosome; - if (nLoci != NULL) d.nLoci = nLoci[0]; - else d.nLoci = 0; - d.probMutn = probMutn; - d.probCrossover = probCrossover; - d.alleleSD = alleleSD; - d.mutationSD = mutationSD; - return d; +void Species::turnOffMutations(void) { + mutationsOn = false; } -bool Species::isDiploid(void) { return diploid; } - -// Chromosome functions - -void Species::setNChromosomes(int c) { - if (nLoci != NULL) deleteLoci(); - if (c > 0) { - nChromosomes = nNLoci = c; - nLoci = new short[c]; - for (int i = 0; i < nNLoci; i++) nLoci[i] = 0; - } - else nChromosomes = nNLoci = 0; +bool Species::areMutationsOn(void) { + return mutationsOn; } -int Species::getNChromosomes(void) { return nChromosomes; } +void Species::resetGeneticParameters() { + mutationsOn = true; + numberOfNeutralLoci = -9999; + numberOfAdaptiveTraits = 0; + genomeSize = -9999; + recombinationRate = -9999; + nSampleCellsFst = -9999; + nIndsToSample = -9999; + chromosomeEnds.clear(); + samplePatchList.clear(); + stagesToSampleFrom.clear(); -void Species::setNLoci(const short chr, const short nloc) { - if (chr >= 0 && chr < nNLoci) { - if (nloc > 0) nLoci[chr] = nloc; - else nLoci[chr] = 0; - } } -int Species::getNLoci(const short chr) { - if (chr >= 0 && chr < nChromosomes) return nLoci[chr]; - else return 0; +bool Species::isDiploid() const { + return isDiploid; } -void Species::deleteLoci(void) { - if (nLoci != NULL) { delete[] nLoci; nLoci = NULL; } +void Species::setNumberOfNeutralLoci(int nN) +{ + numberOfNeutralLoci = nN; } -// Trait functions +int Species::getNumberOfNeutralLoci() const +{ + return numberOfNeutralLoci; +} -// Set 1:1 mapping of trait to chromosome -void Species::set1ChromPerTrait(const int nloc) { - nChromosomes = nTraits; - if (nLoci != NULL) deleteLoci(); - nLoci = new short[1]; - if (nloc > 0) nLoci[0] = nloc; - else nLoci[0] = 1; +int Species::incrementAdaptiveTraits() +{ + numberOfAdaptiveTraits++; + return numberOfAdaptiveTraits; } -bool Species::has1ChromPerTrait(void) { return trait1Chromosome; } +int Species::getNumberOfAdaptiveTraits() const +{ + return numberOfAdaptiveTraits; +} -// Set trait attributes for the species -void Species::setTraits(void) { +void Species::addTrait(TraitType traitType, const ProtoTrait& trait) { - emigTrait[0] = 0; emigTrait[1] = 0; - movtTrait[0] = 0; movtTrait[1] = 0; - settTrait[0] = 0; settTrait[1] = 0; - nTraits = 0; -#if RSDEBUG - DebugGUI("Species::setTraits(): 0000 nChromosomes=" + Int2Str(nChromosomes) - + " nTraits=" + Int2Str(nTraits) - + " indVarEmig=" + Int2Str((int)indVarEmig) - + " indVarTrfr=" + Int2Str((int)indVarTrfr) - + " indVarSett=" + Int2Str((int)indVarSett) - ); -#endif - - if (indVarEmig) { - if (sexDepEmig) { - if (densDepEmig) nTraits += 6; else nTraits += 2; - } - else { - if (densDepEmig) nTraits += 3; else nTraits += 1; - } - emigTrait[0] = 0; emigTrait[1] = nTraits; - } -#if RSDEBUG - //DebugGUI("Species::setTraits(): 1111 nTraits=" + Int2Str(nTraits)); -#endif + TraitType traitT = traitType; + //hack to deal with multiple adaptive traits, could be handled better + if (traitType == ADAPTIVE) { + int n = incrementAdaptiveTraits(); - int movttraits = 0; - if (indVarTrfr) { - if (moveModel) { - if (moveType == 1) { // SMS - movttraits = 1; // in contain batch 2 - if (goalType == 2) movttraits += 3; //in contain batch 2 - } - if (moveType == 2) movttraits = 2; + switch (n) { + case 1: + { + traitT = ADAPTIVE1; + break; } - else { - if (sexDepTrfr) { - if (twinKern) movttraits = 6; else movttraits = 2; - } - else { - if (twinKern) movttraits = 3; else movttraits = 1; - } + case 2: + { + traitT = ADAPTIVE2; + break; } - movtTrait[0] = nTraits; movtTrait[1] = movttraits; - nTraits += movttraits; - } -#if RSDEBUG - //DebugGUI("Species::setTraits(): 2222 nTraits=" + Int2Str(nTraits)); -#endif - - int setttraits = 0; - if (indVarSett) { - if (sexDepSett) setttraits = 6; else setttraits = 3; - settTrait[0] = nTraits; settTrait[1] = setttraits; - nTraits += setttraits; - } - - setTraitNames(); - - //if (trait1Chromosome) { - // nChromosomes = nTraits; - //} -#if RSDEBUG - DebugGUI("Species::setTraits(): 9999 nChromosomes=" + Int2Str(nChromosomes) - + " nTraits=" + Int2Str(nTraits)); -#endif - -} - -void Species::setTraitNames(void) { -#if RSDEBUG - //DebugGUI("Species::setTraitNames(): nTraits=" + Int2Str(nTraits) - // + " nTraitNames=" + Int2Str(nTraitNames) - // + " traitnames=" + Int2Str((int)traitnames) - // ); - //if (traitnames != NULL) { - // DebugGUI("Species::setTraitNames(): traitnames[0]=" + traitnames[0] - // ); - // if (nTraits > 1) { - // DebugGUI("Species::setTraitNames(): traitnames[1]=" + traitnames[1] - // ); - // } - //} -#endif - deleteTraitNames(); - nTraitNames = nTraits; - traitnames = new string[nTraitNames]; - int trait = 0; - if (indVarEmig) { - if (sexDepEmig) { - if (densDepEmig) { - traitnames[trait++] = "d0_F"; - traitnames[trait++] = "d0_M"; - traitnames[trait++] = "alpha_F"; - traitnames[trait++] = "alpha_M"; - traitnames[trait++] = "beta_F"; - traitnames[trait++] = "beta_M"; - } - else { - traitnames[trait++] = "d0_F"; - traitnames[trait++] = "d0_M"; - } + case 3: + { + traitT = ADAPTIVE3; + break; } - else { - traitnames[trait++] = "d0"; - if (densDepEmig) { - traitnames[trait++] = "alpha"; - traitnames[trait++] = "beta"; - } + case 4: + { + traitT = ADAPTIVE4; + break; } - } - - if (indVarTrfr) { - if (moveModel) { - if (moveType == 1) { // SMS - traitnames[trait++] = "DP"; - if (goalType == 2) { - traitnames[trait++] = "GB"; - traitnames[trait++] = "alphaDB"; - traitnames[trait++] = "betaDB"; - } - } - if (moveType == 2) { // CRW - traitnames[trait++] = "stepL"; - traitnames[trait++] = "rho"; - } + case 5: + { + traitT = ADAPTIVE5; + break; } - else { - if (sexDepTrfr) { - if (twinKern) - { - traitnames[trait++] = "meanDistI_F"; - traitnames[trait++] = "meanDistI_M"; - traitnames[trait++] = "meanDistII_F"; - traitnames[trait++] = "meanDistII_M"; - traitnames[trait++] = "probKernI_F"; - traitnames[trait++] = "probKernI_M"; - } - else { - traitnames[trait++] = "meanDistI_F"; - traitnames[trait++] = "meanDistI_M"; - } - } - else { - traitnames[trait++] = "meanDistI"; - if (twinKern) - { - traitnames[trait++] = "meanDistII"; - traitnames[trait++] = "probKernI"; - } - } + default: + { + cout << endl << ("Error:: Too many adaptive traits in Traits file, max = 5 \n"); + break; //should return false } - } - - if (indVarSett) { - if (sexDepSett) { - traitnames[trait++] = "s0_F"; - traitnames[trait++] = "s0_M"; - traitnames[trait++] = "alphaS_F"; - traitnames[trait++] = "alphaS_M"; - traitnames[trait++] = "betaS_F"; - traitnames[trait++] = "betaS_M"; - } - else { - traitnames[trait++] = "s0"; - traitnames[trait++] = "alphaS"; - traitnames[trait++] = "betaS"; } } + traitTable.emplace(traitT, make_unique(trait)); } -void Species::deleteTraitNames(void) { - if (traitnames != NULL) { -#if RSDEBUG - //DebugGUI("Species::deleteTraitNames(): traitnames=" + Int2Str((int)traitnames) - // ); -#endif - delete[] traitnames; - traitnames = NULL; - } +ProtoTrait* Species::getTrait(TraitType trait) const { + return traitTable.find(trait)->second.get(); } -string Species::getTraitName(const int trait) { - string name = "not used"; - if (traitnames != NULL) { - if (trait >= 0 && trait < nTraits) { - name = traitnames[trait]; - } - } - return name; +void Species::clearTraitTable() { + traitTable.clear(); } -int Species::getNTraits(void) { return nTraits; } +//map>& Species::getTraitTable(void) +//{ +// return traitTable; +//} -void Species::setTraitData(const int ntraits) { -#if RSDEBUG - //DebugGUI(("Species::setTraitData(): traitdata=" + Int2Str((int)traitdata) - // + " ntraits=" + Int2Str(ntraits) - // ).c_str()); -#endif - deleteTraitData(); - traitdata = new traitData; - if (ntraits > 0) { - traitdata->nTraitMaps = ntraits; - traitdata->traitmaps = new traitMap * [ntraits]; - for (int i = 0; i < ntraits; i++) { - traitdata->traitmaps[i] = new traitMap; - } - } - else { // neutral markers only - traitdata->nTraitMaps = 0; - } - traitdata->neutralloci = new traitMap; - traitdata->neutralloci->nAlleles = 0; -#if RSDEBUG - //DebugGUI(("Species::setTraitData(): traitdata=" + Int2Str((int)traitdata) - // + " nTraitMaps=" + Int2Str(traitdata->nTraitMaps) - // ).c_str()); -#endif +set Species::getTraitTypes() { + auto kv = views::keys(traitTable); + set keys{ kv.begin(), kv.end() }; + return keys; } -void Species::deleteTraitData(void) { - if (traitdata != NULL) { -#if RSDEBUG - //DebugGUI(("Species::deleteTraitData(): traitdata=" + Int2Str((int)traitdata) - // + " nTraitMaps=" + Int2Str(traitdata->nTraitMaps) - // ).c_str()); -#endif - for (int i = 0; i < traitdata->nTraitMaps; i++) { - if (traitdata->traitmaps[i]->traitalleles != 0) { - for (int j = 0; j < traitdata->traitmaps[i]->nAlleles; j++) { - delete traitdata->traitmaps[i]->traitalleles[j]; - } - } - delete[] traitdata->traitmaps[i]; - } - deleteNeutralLoci(); - delete traitdata; - traitdata = NULL; - } +int Species::getNTraits() const { + return traitTable.size(); } -int Species::getNTraitMaps(void) { - if (traitdata == NULL) return 0; - else return traitdata->nTraitMaps; +int Species::getNPositionsForTrait(const TraitType trait) const { + return this->getTrait(trait)->getPositionsSize(); } -void Species::setTraitMap(const short trait, const short nalleles) { - traitdata->traitmaps[trait]->nAlleles = nalleles; - traitdata->traitmaps[trait]->traitalleles = new traitAllele * [nalleles]; - for (int i = 0; i < nalleles; i++) { - traitdata->traitmaps[trait]->traitalleles[i] = new traitAllele; - } +int Species::getGenomeSize() const { + return genomeSize; } -int Species::getNTraitAlleles(const int trait) { - int nalleles = 0; - if (traitdata != NULL) { - if (trait >= 0 && trait < traitdata->nTraitMaps) { - nalleles = traitdata->traitmaps[trait]->nAlleles; - } - } - return nalleles; +float Species::getRecombinationRate() const { + return recombinationRate; } -void Species::setTraitAllele(const short trait, const short allele, - const short chr, const short loc) -{ - traitdata->traitmaps[trait]->traitalleles[allele] = new traitAllele; - if (chr >= 0 && loc >= 0) { - traitdata->traitmaps[trait]->traitalleles[allele]->chromo = chr; - traitdata->traitmaps[trait]->traitalleles[allele]->locus = loc; - } - else { - traitdata->traitmaps[trait]->traitalleles[allele]->chromo = 0; - traitdata->traitmaps[trait]->traitalleles[allele]->locus = 0; - } +set Species::getChromosomeEnds() const { + return chromosomeEnds; } -traitAllele Species::getTraitAllele(const short trait, const short allele) { - traitAllele a; a.chromo = 0; a.locus = 0; - if (traitdata != NULL) { - if (trait >= 0 && trait < traitdata->nTraitMaps) { - if (allele >= 0 && allele < traitdata->traitmaps[trait]->nAlleles) { - a = *traitdata->traitmaps[trait]->traitalleles[allele]; - } - } - } - return a; -} - -// Neutral loci functions - -// Identify neutral loci and determine whether there is pleiotropy -void Species::setNeutralLoci(bool neutralMarkersOnly) { - bool neutral; - int nneutral = 0; - // find minimum of no. of defined / applied traits - int ntraits; - if (traitdata == 0) ntraits = 0; - else ntraits = traitdata->nTraitMaps; - if (ntraits > nTraits) ntraits = nTraits; -#if RSDEBUG - //DebugGUI("Species::setNeutralLoci(): neutralMarkersOnly=" + Int2Str((int)neutralMarkersOnly) - // + " nNLoci=" + Int2Str(nNLoci) - // + " nTraits=" + Int2Str(nTraits) + " ntraits=" + Int2Str(ntraits) - //); -#endif - -// determine no. of neutral loci - deleteNeutralLoci(); - for (int i = 0; i < nNLoci; i++) { // each chromosome - for (int j = 0; j < nLoci[i]; j++) { // each locus - neutral = true; - for (int t = 0; t < ntraits; t++) { // each trait - for (int a = 0; a < traitdata->traitmaps[t]->nAlleles; a++) { -#if RSDEBUG - //DebugGUI("Species::setNeutralLoci(): i=" + Int2Str(i) - // + " j=" + Int2Str(j) + " t=" + Int2Str(t) + " a=" + Int2Str(a) - // + " chromo=" + Int2Str(traitdata->traitmaps[t]->traitalleles[a]->chromo) - // + " locus=" + Int2Str(traitdata->traitmaps[t]->traitalleles[a]->locus) - //); -#endif - if (i == traitdata->traitmaps[t]->traitalleles[a]->chromo - && j == traitdata->traitmaps[t]->traitalleles[a]->locus) { -#if RSDEBUG - //DebugGUI("Species::setNeutralLoci(): FALSE"); -#endif - neutral = false; // as locus contributes to a trait - a = 999999; - } - } - if (!neutral) t = 999999; - } - if (neutral) nneutral++; - } - } - - traitdata->neutralloci = new traitMap; - traitdata->neutralloci->nAlleles = nneutral; - if (nneutral < 1) return; - - // record neutral markers - traitdata->neutralloci->traitalleles = new traitAllele * [nneutral]; - nneutral = 0; - for (int i = 0; i < nNLoci; i++) { // each chromosome - for (int j = 0; j < nLoci[i]; j++) { // each locus - neutral = true; - for (int t = 0; t < ntraits; t++) { // each trait - for (int a = 0; a < traitdata->traitmaps[t]->nAlleles; a++) { - if (i == traitdata->traitmaps[t]->traitalleles[a]->chromo - && j == traitdata->traitmaps[t]->traitalleles[a]->locus) { - neutral = false; // as locus contributes to a trait - a = 999999; - } - } - if (!neutral) t = 999999; - } - if (neutral) { - traitdata->neutralloci->traitalleles[nneutral] = new traitAllele; - traitdata->neutralloci->traitalleles[nneutral]->chromo = i; - traitdata->neutralloci->traitalleles[nneutral]->locus = j; - nneutral++; - } - } - } - - pleiotropic = false; - if (neutralMarkersOnly) return; // pleiotropy cannot apply - - // determine whether there is pleiotropy - int chr, loc; - int nloci = 0; // maximum no. of loci on any one chromosome - for (int i = 0; i < nNLoci; i++) { - if (nloci < nLoci[i]) nloci = nLoci[i]; - } - int*** locfreq; - locfreq = new int** [nNLoci]; - for (int i = 0; i < nNLoci; i++) { - locfreq[i] = new int* [nloci]; - for (int j = 0; j < nloci; j++) { - locfreq[i][j] = new int[ntraits]; - for (int t = 0; t < ntraits; t++) locfreq[i][j][t] = 0; - } - } - for (int t = 0; t < ntraits; t++) { // each trait - for (int a = 0; a < traitdata->traitmaps[t]->nAlleles; a++) { - chr = traitdata->traitmaps[t]->traitalleles[a]->chromo; - loc = traitdata->traitmaps[t]->traitalleles[a]->locus; - locfreq[chr][loc][t]++; - } - } -#if RSDEBUG - //for (int i = 0; i < nNLoci; i++) { - // for (int j = 0; j < nloci; j++) - // for (int t = 0; t < ntraits; t++) - // DebugGUI("locfreq[" + Int2Str(i) + "][" + Int2Str(j) + "][" + Int2Str(t) - // + "]=" + Int2Str(locfreq[i][j][t])); - //} -#endif - for (int i = 0; i < nNLoci; i++) { - for (int j = 0; j < nloci; j++) { - // remove multiple contributions of a locus to a particular trait - // (i.e. prevent recording of pseudo-pleiotropy) - for (int t = 0; t < ntraits; t++) { - if (locfreq[i][j][t] > 0) locfreq[i][j][t] = 1; - } - // sum at level of chromosome/locus - for (int t = 1; t < ntraits; t++) { - locfreq[i][j][0] += locfreq[i][j][t]; - } - if (locfreq[i][j][0] > 1) pleiotropic = true; - } - } - for (int i = 0; i < nNLoci; i++) { - for (int j = 0; j < nloci; j++) { - delete[] locfreq[i][j]; - } - delete[] locfreq[i]; - } - delete[] locfreq; - -} - -void Species::deleteNeutralLoci(void) { - if (traitdata->neutralloci != NULL) { - for (int i = 0; i < traitdata->neutralloci->nAlleles; i++) { - delete traitdata->neutralloci->traitalleles[i]; - } - delete[] traitdata->neutralloci; - } - traitdata->neutralloci = NULL; -} - -int Species::getNNeutralLoci(void) { - int nn = 0; - if (traitdata != NULL) { - if (traitdata->neutralloci != NULL) { - nn = traitdata->neutralloci->nAlleles; - } - } - return nn; -} - -traitAllele Species::getNeutralAllele(const short allele) { - traitAllele a; a.chromo = 0; a.locus = 0; - if (traitdata != NULL) { - if (allele >= 0 && allele < traitdata->neutralloci->nAlleles) { - a = *traitdata->neutralloci->traitalleles[allele]; - } - } - return a; -} //--------------------------------------------------------------------------- @@ -969,7 +525,6 @@ emigRules Species::getEmig(void) { emigRules e; e.densDep = densDepEmig; e.stgDep = stgDepEmig; e.sexDep = sexDepEmig; e.indVar = indVarEmig; e.emigStage = emigStage; - e.emigTrait[0] = emigTrait[0]; e.emigTrait[1] = emigTrait[1]; return e; } @@ -1000,54 +555,7 @@ float Species::getEmigD0(short stg, short sex) { } } -void Species::setEmigParams(const short stg, const short sex, const emigParams e) { - //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only - { - if (e.d0Mean >= 0.0 && e.d0Mean < 1.0) d0Mean[stg][sex] = e.d0Mean; - if (e.d0SD > 0.0 && e.d0SD < 1.0) d0SD[stg][sex] = e.d0SD; - // if (e.d0MutnSize > 0.0 && e.d0MutnSize < 1.0) d0MutnSize = e.d0MutnSize; - alphaMean[stg][sex] = e.alphaMean; - if (e.alphaSD > 0.0) alphaSD[stg][sex] = e.alphaSD; - // if (e.alphaMutnSize > 0.0) alphaMutnSize = e.alphaMutnSize; - betaMean[stg][sex] = e.betaMean; - if (e.betaSD > 0.0) betaSD[stg][sex] = e.betaSD; - // if (e.betaMutnSize > 0.0) betaMutnSize = e.betaMutnSize; - } -} -emigParams Species::getEmigParams(short stg, short sex) { - emigParams e; - //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only - { - e.d0Mean = d0Mean[stg][sex]; e.d0SD = d0SD[stg][sex]; - e.d0Scale = d0Scale; - e.alphaMean = alphaMean[stg][sex]; e.alphaSD = alphaSD[stg][sex]; - e.alphaScale = alphaScale; - e.betaMean = betaMean[stg][sex]; e.betaSD = betaSD[stg][sex]; - e.betaScale = betaScale; - } - else { - e.d0Mean = e.alphaMean = e.betaMean = e.d0SD = e.alphaSD = e.betaSD = 0.0; - e.d0Scale = d0Scale; - e.alphaScale = alphaScale; - e.betaScale = betaScale; - } - return e; -} - -void Species::setEmigScales(const emigScales s) { - if (s.d0Scale >= 0.0 && s.d0Scale < 1.0) d0Scale = s.d0Scale; - if (s.alphaScale >= 0.0) alphaScale = s.alphaScale; - if (s.betaScale >= 0.0) betaScale = s.betaScale; -} - -emigScales Species::getEmigScales(void) { - emigScales s; - s.d0Scale = d0Scale; s.alphaScale = alphaScale; s.betaScale = betaScale; - return s; -} //--------------------------------------------------------------------------- @@ -1072,7 +580,6 @@ trfrRules Species::getTrfr(void) { t.twinKern = twinKern; t.habMort = habMort; t.moveType = moveType; t.costMap = costMap; - t.movtTrait[0] = movtTrait[0]; t.movtTrait[1] = movtTrait[1]; return t; } @@ -1155,132 +662,6 @@ trfrSMSTraits Species::getSMSTraits(void) { return m; } -void Species::setKernParams(const short stg, const short sex, - const trfrKernParams k, const double resol) -{ - //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only - { - if (k.dist1Mean > 0.0 && k.dist1Mean >= resol && k.dist1SD > 0.0) { - dist1Mean[stg][sex] = k.dist1Mean; dist1SD[stg][sex] = k.dist1SD; - } - if (k.dist2Mean > 0.0 && k.dist2Mean >= resol && k.dist2SD > 0.0) { - dist2Mean[stg][sex] = k.dist2Mean; dist2SD[stg][sex] = k.dist2SD; - } - if (k.PKern1Mean > 0.0 && k.PKern1Mean < 1.0 && k.PKern1SD > 0.0 && k.PKern1SD < 1.0) { - PKern1Mean[stg][sex] = k.PKern1Mean; PKern1SD[stg][sex] = k.PKern1SD; - } - } -} - -trfrKernParams Species::getKernParams(short stg, short sex) { - trfrKernParams k; - //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only - { - k.dist1Mean = dist1Mean[stg][sex]; k.dist1SD = dist1SD[stg][sex]; - k.dist2Mean = dist2Mean[stg][sex]; k.dist2SD = dist2SD[stg][sex]; - k.PKern1Mean = PKern1Mean[stg][sex]; k.PKern1SD = PKern1SD[stg][sex]; - k.dist1Scale = dist1Scale; k.dist2Scale = dist2Scale; k.PKern1Scale = PKern1Scale; - } - else { - k.dist1Mean = 100000.0; k.dist1SD = 0.001f; k.dist1Scale = 1.0; - k.dist2Mean = 100000.0; k.dist2SD = 0.001f; k.dist2Scale = 1.0; - k.PKern1Mean = 0.5; k.PKern1SD = 0.1f; k.PKern1Scale = 0.1f; - } - return k; -} - -void Species::setSMSParams(const short stg, const short sex, const trfrSMSParams s) { - //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only - { - if (s.dpMean >= 1.0 && s.dpSD > 0.0) { - dpMean[stg][sex] = s.dpMean; dpSD[stg][sex] = s.dpSD; - } - if (s.gbMean >= 1.0 && s.gbSD > 0.0) { - gbMean[stg][sex] = s.gbMean; gbSD[stg][sex] = s.gbSD; - } - if (s.alphaDBMean > 0.0 && s.alphaDBSD > 0.0) { - alphaDBMean[stg][sex] = s.alphaDBMean; alphaDBSD[stg][sex] = s.alphaDBSD; - } - if (s.betaDBMean >= 1.0 && s.betaDBSD > 0.0) { - betaDBMean[stg][sex] = s.betaDBMean; betaDBSD[stg][sex] = s.betaDBSD; - } - } -} - -trfrSMSParams Species::getSMSParams(short stg, short sex) { - trfrSMSParams s; - //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only - { - s.dpMean = dpMean[stg][sex]; s.dpSD = dpSD[stg][sex]; - s.gbMean = gbMean[stg][sex]; s.gbSD = gbSD[stg][sex]; - s.alphaDBMean = alphaDBMean[stg][sex]; s.alphaDBSD = alphaDBSD[stg][sex]; - s.betaDBMean = betaDBMean[stg][sex]; s.betaDBSD = betaDBSD[stg][sex]; - s.dpScale = dpScale; s.gbScale = gbScale; - s.alphaDBScale = alphaDBScale; s.betaDBScale = betaDBScale; - } - else { - s.dpMean = 1.0; s.dpSD = 0.1f; s.dpScale = 0.1f; - s.gbMean = 1.0; s.gbSD = 0.1f; s.gbScale = 0.1f; - s.alphaDBMean = 1.0; s.alphaDBSD = 0.1f; s.alphaDBScale = 0.1f; - s.betaDBMean = 10.0; s.betaDBSD = 1.0; s.betaDBScale = 1.0; - } - return s; -} - -void Species::setCRWParams(const short stg, const short sex, const trfrCRWParams m) { - //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only - { - if (m.stepLgthMean > 0.0 && m.stepLgthSD > 0.0) { - stepLgthMean[stg][sex] = m.stepLgthMean; stepLgthSD[stg][sex] = m.stepLgthSD; - } - if (m.rhoMean > 0.0 && m.rhoMean < 1.0 && m.rhoSD > 0.0 && m.rhoSD < 1.0) { - rhoMean[stg][sex] = m.rhoMean; rhoSD[stg][sex] = m.rhoSD; - } - } -} - -trfrCRWParams Species::getCRWParams(short stg, short sex) { - trfrCRWParams m; - //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only - { - m.stepLgthMean = stepLgthMean[stg][sex]; m.stepLgthSD = stepLgthSD[stg][sex]; - m.rhoMean = rhoMean[stg][sex]; m.rhoSD = rhoSD[stg][sex]; - m.stepLScale = stepLScale; m.rhoScale = rhoScale; - } - else { - m.stepLgthMean = 1.0; m.stepLgthSD = 0.1f; m.stepLScale = 0.1f; - m.rhoMean = 0.5; m.rhoSD = 0.1f; m.rhoScale = 0.1f; - } - return m; -} - -void Species::setTrfrScales(const trfrScales s) { - if (s.dist1Scale >= 0.0) dist1Scale = s.dist1Scale; - if (s.dist2Scale >= 0.0) dist2Scale = s.dist2Scale; - if (s.PKern1Scale > 0.0 && s.PKern1Scale < 1.0) PKern1Scale = s.PKern1Scale; - if (s.dpScale > 0.0) dpScale = s.dpScale; - if (s.gbScale > 0.0) gbScale = s.gbScale; - if (s.alphaDBScale > 0.0) alphaDBScale = s.alphaDBScale; - if (s.betaDBScale > 0.0) betaDBScale = s.betaDBScale; - if (s.stepLScale > 0.0) stepLScale = s.stepLScale; - if (s.rhoScale > 0.0 && s.rhoScale < 1.0) rhoScale = s.rhoScale; -} - -trfrScales Species::getTrfrScales(void) { - trfrScales s; - s.dist1Scale = dist1Scale; s.dist2Scale = dist2Scale; s.PKern1Scale = PKern1Scale; - s.dpScale = dpScale; s.gbScale = gbScale; - s.alphaDBScale = alphaDBScale; s.betaDBScale = betaDBScale; - s.stepLScale = stepLScale; s.rhoScale = rhoScale; - return s; -} - short Species::getMovtHabDim() { return habDimTrfr; } void Species::createHabCostMort(short nhab) { @@ -1339,7 +720,6 @@ void Species::setSettle(const settleType s) { settleType Species::getSettle(void) { settleType s; s.stgDep = stgDepSett; s.sexDep = sexDepSett; s.indVar = indVarSett; - s.settTrait[0] = settTrait[0]; s.settTrait[1] = settTrait[1]; return s; } @@ -1392,6 +772,27 @@ void Species::setSettTraits(const short stg, const short sex, const settleTraits } } +void Species::setGeneticParameters(const set& chromosomeEnds, const int genomeSize, const float recombinationRate, + const set& samplePatchList, const string nIndsToSample, const set& stagesToSampleFrom, string nSampleCellsFst) +{ + this->genomeSize = genomeSize; + for (auto position : chromosomeEnds) { + if (position > this->getGenomeSize() - 1) + cout << endl << "Genetics file: ERROR - chromosome ends " << position << " must not exceed genome size" << endl; + } + this->chromosomeEnds = chromosomeEnds; + this->recombinationRate = recombinationRate; + this->samplePatchList = samplePatchList; + this->nSampleCellsFst = nSampleCellsFst; + this->nIndsToSample = nIndsToSample; + this->stagesToSampleFrom = stagesToSampleFrom; +} + +//only called for cell based landscape +void Species::setSamplePatchList(const set& samplePatchList) { + this->samplePatchList = samplePatchList; +} + settleTraits Species::getSettTraits(short stg, short sex) { settleTraits dd; if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { @@ -1401,53 +802,8 @@ settleTraits Species::getSettTraits(short stg, short sex) { return dd; } -void Species::setSettParams(const short stg, const short sex, const settParams s) { - //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only - { - if (s.s0Mean >= 0.0 && s.s0Mean < 1.0) s0Mean[stg][sex] = s.s0Mean; - if (s.s0SD > 0.0 && s.s0SD < 1.0) s0SD[stg][sex] = s.s0SD; - alphaSMean[stg][sex] = s.alphaSMean; - if (s.alphaSSD > 0.0) alphaSSD[stg][sex] = s.alphaSSD; - betaSMean[stg][sex] = s.betaSMean; - if (s.betaSSD > 0.0) betaSSD[stg][sex] = s.betaSSD; - if (sex == 0) { - if (s.s0Scale > 0.0 && s.s0Scale < 1.0) s0Scale = s.s0Scale; - if (s.alphaSScale > 0.0) alphaSScale = s.alphaSScale; - if (s.betaSScale > 0.0) betaSScale = s.betaSScale; - } - } -} - -settParams Species::getSettParams(short stg, short sex) { - settParams s; - //if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only - { - s.s0Mean = s0Mean[stg][sex]; s.s0SD = s0SD[stg][sex]; - s.alphaSMean = alphaSMean[stg][sex]; s.alphaSSD = alphaSSD[stg][sex]; - s.betaSMean = betaSMean[stg][sex]; s.betaSSD = betaSSD[stg][sex]; - } - else { - s.s0Mean = s.alphaSMean = s.betaSMean = s.s0SD = s.alphaSSD = s.betaSSD = 0.0; - } - s.s0Scale = s0Scale; - s.alphaSScale = alphaSScale; - s.betaSScale = betaSScale; - return s; -} -void Species::setSettScales(const settScales s) { - if (s.s0Scale >= 0.0 && s.s0Scale < 1.0) s0Scale = s.s0Scale; - if (s.alphaSScale >= 0.0) alphaSScale = s.alphaSScale; - if (s.betaSScale >= 0.0) betaSScale = s.betaSScale; -} -settScales Species::getSettScales(void) { - settScales s; - s.s0Scale = s0Scale; s.alphaSScale = alphaSScale; s.betaSScale = betaSScale; - return s; -} //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- diff --git a/Species.h b/Species.h index 7cf3613..5efbaf8 100644 --- a/Species.h +++ b/Species.h @@ -45,16 +45,16 @@ #ifndef SpeciesH #define SpeciesH +#include //#if RS_RCPP && !R_CMD #include "../Version.h" //#endif - -//#if !RS_RCPP && R_CMD -//#include "../../Batch/Version.h" -//#endif #include "Parameters.h" +#include "ProtoTrait.h" +#include "TTrait.h" +#include -// structures for demographic parameters + // structures for demographic parameters struct demogrParams { short repType; @@ -72,29 +72,6 @@ struct densDepParams { float devCoeff; float survCoeff; }; -// structures for genetics - -struct genomeData { - int nLoci; - bool diploid; bool neutralMarkers; bool pleiotropic; bool trait1Chromosome; - double probMutn, probCrossover, alleleSD, mutationSD; -}; - -struct traitAllele { - short chromo; short locus; -}; - -struct traitMap { - short nAlleles; - traitAllele** traitalleles; -}; - -struct traitData { - short nTraitMaps; - traitMap** traitmaps; - traitMap* neutralloci; -}; - // structures for emigration parameters struct emigRules { @@ -104,14 +81,19 @@ struct emigRules { }; struct emigTraits { float d0; float alpha; float beta; -}; -struct emigParams { - double d0Mean; double d0SD; double d0Scale; - double alphaMean; double alphaSD; double alphaScale; - double betaMean; double betaSD; double betaScale; -}; -struct emigScales { - double d0Scale; double alphaScale; double betaScale; + + emigTraits() : d0(0.0), alpha(0.0), beta(0.0) {}; + + emigTraits(const emigTraits& e) : d0(e.d0), alpha(e.alpha), beta(e.beta) {}; + + emigTraits* clone() { return new emigTraits(*this); } + + void divideTraitsBy(int i) { + + d0 /= i; + alpha /= i; + beta /= i; + } }; // structures for transfer parameters @@ -125,7 +107,9 @@ struct trfrRules { short movtTrait[2]; }; struct trfrKernTraits { - float meanDist1; float meanDist2; float probKern1; + float meanDist1; + float meanDist2; + float probKern1; }; struct trfrMortParams { float fixedMort; float mortAlpha; float mortBeta; @@ -137,32 +121,16 @@ struct trfrMovtTraits { bool straigtenPath; }; struct trfrCRWTraits { - float stepMort; float stepLength; float rho; bool straigtenPath; + float stepMort; + float stepLength; + float rho; + bool straigtenPath; }; struct trfrSMSTraits { short pr; short prMethod; short memSize; short goalType; float dp; float gb; float alphaDB; int betaDB; float stepMort; bool straigtenPath; }; -struct trfrKernParams { - double dist1Mean; double dist1SD; double dist1Scale; - double dist2Mean; double dist2SD; double dist2Scale; - double PKern1Mean; double PKern1SD; double PKern1Scale; -}; -struct trfrSMSParams { - double dpMean; double dpSD; double gbMean; double gbSD; - double alphaDBMean; double alphaDBSD; double betaDBMean; double betaDBSD; - double dpScale; double gbScale; double alphaDBScale; double betaDBScale; -}; -struct trfrCRWParams { - double stepLgthMean; double stepLgthSD; double stepLScale; - double rhoMean; double rhoSD; double rhoScale; -}; -struct trfrScales { - float dist1Scale; float dist2Scale; float PKern1Scale; - float dpScale; float gbScale; float alphaDBScale; float betaDBScale; - float stepLScale; float rhoScale; -}; // structures for settlement parameters @@ -178,14 +146,16 @@ struct settleSteps { }; struct settleTraits { float s0; float alpha; float beta; -}; -struct settParams { - double s0Mean; double s0SD; double s0Scale; - double alphaSMean; double alphaSSD; double alphaSScale; - double betaSMean; double betaSSD; double betaSScale; -}; -struct settScales { - double s0Scale; double alphaSScale; double betaSScale; + + settleTraits() : s0(0.0), alpha(0.0), beta(0.0) {}; + + settleTraits(const settleTraits& e) : s0(e.s0), alpha(e.alpha), beta(e.beta) {}; + + void divideTraitsBy(int i) { + s0 /= i; + alpha /= i; + beta /= i; + } }; @@ -314,63 +284,31 @@ class Species { short // option: 0 = return minimum, otherwise = return maximum ); + set& getSamplePatches() { + return samplePatchList; + }; - // genome functions + string getNIndsToSample() { + return nIndsToSample; + }; - void setGenomeData(genomeData); - genomeData getGenomeData(void); - bool isDiploid(void); - void setNChromosomes( // Set no. of chromosomes - int // no. of chromosomes - ); - int getNChromosomes(void); - void setNLoci( - const short, // chromosome no. - const short // locus no. - ); - int getNLoci( - const short // chromosome no. - ); - void deleteLoci(void); - void set1ChromPerTrait( // Set 1:1 mapping of trait to chromosome - const int // no. of loci on each chromosome - ); - bool has1ChromPerTrait(void); - void setTraits(void); // Set trait attributes for the species - void setTraitNames(void); - void deleteTraitNames(void); - string getTraitName( - const int // trait no. - ); - int getNTraits(void); - void setTraitData( - const int // no. of traits - ); - void deleteTraitData(void); - int getNTraitMaps(void); - void setTraitMap( - const short, // trait no. - const short // no. of alleles - ); - int getNTraitAlleles( - const int // trait no. - ); - void setTraitAllele( - const short, // trait no. - const short, // trait allele no. - const short, // chromosome no. - const short // chromosome locus no. - ); - traitAllele getTraitAllele( - const short, // trait no. - const short // trait allele no. - ); - void setNeutralLoci(bool); - void deleteNeutralLoci(void); - int getNNeutralLoci(void); - traitAllele getNeutralAllele( - const short // allele no. - ); + set& getStagesToSample() { + return stagesToSampleFrom; + } + + string getNSampleCellsFst() { + return nSampleCellsFst; + } + + // Genetic functions + void turnOffMutations(void); + void resetGeneticParameters(); + bool areMutationsOn(void); + bool isDiploid() const; + void setNumberOfNeutralLoci(int); + int getNumberOfNeutralLoci() const; + int incrementAdaptiveTraits(); + int getNumberOfAdaptiveTraits() const; // emigration parameter functions @@ -391,19 +329,6 @@ class Species { short, // stage short // sex ); - void setEmigParams( // Set emigration initialisation parameters - const short, // stage (NB implemented for stage 0 only) - const short, // sex - const emigParams // structure holding parameters - ); - emigParams getEmigParams( // Get emigration initialisation parameters - short, // stage (NB implemented for stage 0 only) - short // sex - ); - void setEmigScales( // Set emigration mutation parameters - const emigScales // structure holding emigration mutation parameters - ); - emigScales getEmigScales(void); // Get emigration mutation parameters // transfer parameter functions @@ -435,38 +360,6 @@ class Species { trfrMovtTraits getMovtTraits(void); // Get transfer movement model traits trfrCRWTraits getCRWTraits(void); // Get CRW traits trfrSMSTraits getSMSTraits(void); // Get SMS traits - void setKernParams( // Set initial transfer by kernel parameter limits - const short, // stage (NB implemented for stage 0 only) - const short, // sex - const trfrKernParams, // structure holding min and max values - const double // Landscape resolution - ); - trfrKernParams getKernParams( // Get initial transfer by kernel parameter limits - short, // stage (NB implemented for stage 0 only) - short // sex - ); - void setSMSParams( // Set initial transfer by SMS parameter limits - const short, // stage (NB implemented for stage 0 only) - const short, // sex (NB implemented for sex 0 only) - const trfrSMSParams // structure holding min and max values - ); - trfrSMSParams getSMSParams( // Get initial transfer by SMS parameter limits - short, // stage (NB implemented for stage 0 only) - short // sex (NB implemented for sex 0 only) - ); - void setCRWParams( // Set initial transfer by CRW parameter limits - const short, // stage (NB implemented for stage 0 only) - const short, // sex (NB implemented for sex 0 only) - const trfrCRWParams // structure holding min and max values - ); - trfrCRWParams getCRWParams( // Get initial transfer by CRW parameter limits - short, // stage (NB implemented for stage 0 only) - short // sex (NB implemented for sex 0 only) - ); - void setTrfrScales( // Set transfer mutation parameters - const trfrScales // structure holding transfer mutation parameters - ); - trfrScales getTrfrScales(void); // Get transfer mutation parameters // Return dimension of habitat-dependent step mortality and costs matrices short getMovtHabDim(void); void createHabCostMort( // Create habitat-dependent costs and mortality matrices @@ -521,19 +414,28 @@ class Species { short, // stage short // sex ); - void setSettParams( // Set settlement initialisation parameters - const short, // stage (NB implemented for stage 0 only) - const short, // sex - const settParams // structure holding parameters - ); - settParams getSettParams( // Get settlement initialisation parameters - short, // stage (NB implemented for stage 0 only) - short // sex - ); - void setSettScales( // Set settlement mutation parameters - const settScales // structure holding settlement mutation parameters - ); - settScales getSettScales(void); // Get settlement mutation parameters + + void addTrait(TraitType traitType, const ProtoTrait& trait); + + void clearTraitTable(); + + ProtoTrait* getTrait(TraitType trait) const; + + //map>& getTraitTable(void); //return by reference so ensure variable recieving is const + + set getTraitTypes(); + + int getNTraits() const; + int getNPositionsForTrait(const TraitType trait) const; + int getGenomeSize() const; + void setGenomeSize(int); + float getRecombinationRate() const; + void setRecombinationRate(float); + set getChromosomeEnds() const; + void setChromosomeEnds(const set& ends); + void setGeneticParameters(const set& chromosomeEnds, const int genomeSize, const float recombinationRate, + const set& samplePatchList, const string nIndsToSample, const set& stagesToSampleFrom, string nSampleCellsFst); + void setSamplePatchList(const set& samplePatchList); private: @@ -585,24 +487,19 @@ class Species { // genome parameters - short nTraits; // no. of inheritable traits - short emigTrait[2]; // to record first and no. of emigration traits - short movtTrait[2]; // to record first and no. of transfer traits - short settTrait[2]; // to record first and no. of settlement traits - bool diploid; - bool neutralMarkers; // neutral markers in absence of any adaptive traits - bool pleiotropic; - bool trait1Chromosome; // 1:1 mapping of chromosome to trait - short nChromosomes; // no. of chromosomes - double probMutn; // allelic mutation probability - double probCrossover; // crossover probability at meiosis - double alleleSD; // s.d. of initial allelic values around phenotypic value - double mutationSD; // s.d. of mutation magnitude - short nNLoci; // no. of nLoci set - short* nLoci; // no. of loci per chromosome - short nTraitNames; // no. of trait names set - traitData* traitdata; // for mapping of chromosome loci to traits - string* traitnames; // trait names for parameter output + /**The traits table.*/ + map> traitTable; + set chromosomeEnds; + int genomeSize; + bool isDiploid; + bool mutationsOn; + int numberOfNeutralLoci; + int numberOfAdaptiveTraits; + float recombinationRate; + set samplePatchList; + string nSampleCellsFst; //for cell based landscape + set stagesToSampleFrom; + string nIndsToSample; //could be integer or 'all', all means in in selected patches not necessarily all in population // emigration parameters @@ -618,17 +515,6 @@ class Species { float betaEmig[NSTAGES][NSEXES]; // inflection point of reaction norm (in terms of N/K) // NB Initialisation parameters are made double to avoid conversion errors (reason unclear) // on traits maps using FloatToStr() - // As evolving traits are not stage-dependent, no. of rows can be 1 - // Indeed, they could be 1-D arrays - double d0Mean[1][NSEXES]; - double d0SD[1][NSEXES]; - double alphaMean[1][NSEXES]; - double alphaSD[1][NSEXES]; - double betaMean[1][NSEXES]; - double betaSD[1][NSEXES]; - double d0Scale; // scaling factor for d0 - double alphaScale; // scaling factor for alpha - double betaScale; // scaling factor for beta // transfer parameters @@ -645,17 +531,6 @@ class Species { // NB INITIAL limits are made double to avoid conversion errors (reason unclear) // on traits maps using FloatToStr() // As evolving traits are are not stage-dependent, no. of rows can be 1 - // Indeed, as they are INITIAL limits, which may subsequently be exceeded, they could be - // 1-D arrays - double dist1Mean[1][NSEXES]; // mean of initial mean of the 1st dispersal kernel (m) - double dist1SD[1][NSEXES]; // s.d. of initial mean of the 1st dispersal kernel (m) - double dist2Mean[1][NSEXES]; // mean of initial mean of the 2nd dispersal kernel (m) - double dist2SD[1][NSEXES]; // s.d. of initial mean of the 2nd dispersal kernel (m) - double PKern1Mean[1][NSEXES]; // mean of initial prob. of dispersing with 1st kernel - double PKern1SD[1][NSEXES]; // s.d. of initial prob. of dispersing with 1st kernel - float dist1Scale; // scaling factor for mean of 1st dispersal kernel (m) - float dist2Scale; // scaling factor for mean of 2nd dispersal kernel (m) - float PKern1Scale; // scaling factor for prob. of dispersing with 1st kernel float fixedMort; // constant mortality probability float mortAlpha; // slope for mortality distance dependence function float mortBeta; // inflection point for mortality distance dependence function @@ -673,24 +548,6 @@ class Species { double* habStepMort; // habitat-dependent per-step mortality probability float stepLength; // CRW step length (m) float rho; // CRW correlation coefficient - double dpMean[1][NSEXES]; // mean of initial SMS directional persistence - double dpSD[1][NSEXES]; // s.d. of initial SMS directional persistence - double gbMean[1][NSEXES]; // mean of initial SMS goal bias - double gbSD[1][NSEXES]; // s.d. of initial SMS goal bias - double alphaDBMean[1][NSEXES]; // mean of initial SMS dispersal bias decay rate - double alphaDBSD[1][NSEXES]; // s.d. of initial SMS dispersal bias decay rate - double betaDBMean[1][NSEXES]; // mean of initial SMS dispersal bias decay infl. pt. - double betaDBSD[1][NSEXES]; // s.d. of initial SMS dispersal bias decay infl. pt. - float dpScale; // scaling factor for SMS directional persistence - float gbScale; // scaling factor for SMS goal bias - float alphaDBScale; // scaling factor for SMS dispersal bias decay rate - float betaDBScale; // scaling factor for SMS dispersal bias decay infl. pt. - double stepLgthMean[1][NSEXES]; // mean of initial step length (m) - double stepLgthSD[1][NSEXES]; // s.d. of initial step length (m) - double rhoMean[1][NSEXES]; // mean of initial correlation coefficient - double rhoSD[1][NSEXES]; // s.d. of initial correlation coefficient - float stepLScale; // scaling factor for step length (m) - float rhoScale; // scaling factor for correlation coefficient short habDimTrfr; // dimension of habitat-dependent step mortality and costs matrices int* habCost; // habitat costs bool costMap; // import cost map from file? @@ -714,15 +571,6 @@ class Species { float s0[NSTAGES][NSEXES]; // maximum settlement probability float alphaS[NSTAGES][NSEXES]; // slope of the settlement reaction norm to density float betaS[NSTAGES][NSEXES]; // inflection point of the settlement reaction norm to density - double s0Mean[1][NSEXES]; // mean of initial maximum settlement probability - double s0SD[1][NSEXES]; // s.d. of initial maximum settlement probability - double alphaSMean[1][NSEXES]; // mean of initial settlement reaction norm slope - double alphaSSD[1][NSEXES]; // s.d. of initial settlement reaction norm slope - double betaSMean[1][NSEXES]; // mean of initial settlement reaction norm inflection point - double betaSSD[1][NSEXES]; // s.d. of initial settlement reaction norm inflection point - float s0Scale; // scaling factor for maximum settlement probability - float alphaSScale; // scaling factor for settlement reaction norm slope - float betaSScale; // scaling factor for settlement reaction norm inflection point // other attributes @@ -730,19 +578,6 @@ class Species { }; -/* IMPORTANT NOTE: -At the time of writing (24/4/14) the stage- and sex-dependent parameters for emigration -and dispersal (e.g. d0[NSTAGES][NSEXES]) are set according to the appropriate stage- and -sex-dependent settings; thus a species could be structured and sexual, but parameter values -are set for elements [0][0] only if emigration/transfer is stage- and sex-independent. -However, the parameters for settlement are set for ALL stages and sexes appropriate to the -species, regardless of settlement dependency. The rationale for this is that settlement -parameters need to be accessed many more times for a movement model (at each step) than -emigration or transfer parameters, and therefore there will be a performance gain in -avoiding nested if statements in Individual::moveStep() which would otherwise be required -to get the correct parameter values from the settlement arrays. Whether that particular -rationale is justified remains to be tested! -*/ //--------------------------------------------------------------------------- diff --git a/SubCommunity.cpp b/SubCommunity.cpp index e09ceda..f0deddd 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -123,7 +123,6 @@ void SubCommunity::initialInd(Landscape* pLandscape, Species* pSpecies, emigRules emig = pSpecies->getEmig(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); - genomeData gen = pSpecies->getGenomeData(); short stg, age, repInt; Individual* pInd; float probmale; @@ -162,11 +161,11 @@ void SubCommunity::initialInd(Landscape* pLandscape, Species* pSpecies, // NB THIS WILL NEED TO BE CHANGED FOR MULTIPLE SPECIES... popns[0]->recruit(pInd); - if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) + if (pSpecies->getNTraits() > 0) { // individual variation - set up genetics landData land = pLandscape->getLandData(); - pInd->setGenes(pSpecies, land.resol); + pInd->setUpGenes(pSpecies, land.resol); } } @@ -291,7 +290,7 @@ void SubCommunity::patchChange(void) { } } -void SubCommunity::reproduction(int resol, float epsGlobal, short rasterType, bool patchModel) +void SubCommunity::reproduction(int resol, float epsGlobal, short rasterType, bool patchModel, bool cloneFromColdStorage, Population* pColdStorage) { if (subCommNum == 0) return; // no reproduction in the matrix float localK, envval; @@ -329,7 +328,7 @@ void SubCommunity::reproduction(int resol, float epsGlobal, short rasterType, bo } } for (int i = 0; i < npops; i++) { // all populations - popns[i]->reproduction(localK, envval, resol); + popns[i]->reproduction(localK, envval, resol, cloneFromColdStorage, pColdStorage); popns[i]->fledge(); } } @@ -421,6 +420,56 @@ void SubCommunity::initiateDispersal(SubCommunity* matrix) { } +void SubCommunity::copyIndividualsForColdStorage(Population* pColdStorage) { + int npops = (int)popns.size(); + popStats pop; + Individual* clone; + for (int i = 0; i < npops; i++) { // all populations + pop = popns[i]->getStats(); + for (int j = 0; j < pop.nInds; j++) { +#if RSDEBUG + //DEBUGLOG << "SubCommunity::initiateDispersal(): i = " << i + // << " j " << j + // << endl; +#endif + + clone = popns[i]->copyForColdStorage(j); + pColdStorage->recruit(clone); + } + } + +} + + +int SubCommunity::addEmigrationAndSettlementTraitValues(emigTraits& avgEmTraits, settleTraits& avgSettleTraits) { + int npops = (int)popns.size(); + int totalInds = 0; + popStats pop; + for (int i = 0; i < npops; i++) { // all populations + pop = popns[i]->getStats(); + for (int j = 0; j < pop.nInds; j++) { + popns[i]->addEmigTraitsForInd(j, avgEmTraits); + popns[i]->addSettleTraitsForInd(j, avgSettleTraits); + totalInds++; + } + } + return totalInds; +} + +void SubCommunity::addTransferDataForInd(trfrData* avgTrfrData) { + int npops = (int)popns.size(); + popStats pop; + for (int i = 0; i < npops; i++) { // all populations + pop = popns[i]->getStats(); + for (int j = 0; j < pop.nInds; j++) { + popns[i]->addTransferDataForInd(j, avgTrfrData); + } + } +} + + + + // Add an individual into the local population of its species in the patch void SubCommunity::recruit(Individual* pInd, Species* pSpecies) { #if RSDEBUG @@ -745,12 +794,18 @@ void SubCommunity::outPop(Landscape* pLandscape, int rep, int yr, int gen) // Write records to individuals file void SubCommunity::outInds(Landscape* pLandscape, int rep, int yr, int gen, int landNr) { landParams ppLand = pLandscape->getLandParams(); + Population* pPop; if (landNr >= 0) { // open the file popns[0]->outIndsHeaders(rep, landNr, ppLand.patchModel); return; } if (landNr == -999) { // close the file - popns[0]->outIndsHeaders(rep, -999, ppLand.patchModel); + + // as all populations may have been deleted, set up a dummy one + // species is not necessary + pPop = new Population(); + pPop->outIndsHeaders(rep, -999, ppLand.patchModel); + delete pPop; return; } // generate output for each population within the sub-community (patch) @@ -760,24 +815,6 @@ void SubCommunity::outInds(Landscape* pLandscape, int rep, int yr, int gen, int } } -// Write records to individuals file -void SubCommunity::outGenetics(int rep, int yr, int gen, int landNr) -{ - //landParams ppLand = pLandscape->getLandParams(); - if (landNr >= 0) { // open the file - popns[0]->outGenetics(rep, yr, landNr); - return; - } - if (landNr == -999) { // close the file - popns[0]->outGenetics(rep, yr, landNr); - return; - } - // generate output for each population within the sub-community (patch) - int npops = (int)popns.size(); - for (int i = 0; i < npops; i++) { // all populations - popns[i]->outGenetics(rep, yr, landNr); - } -} // Population size of a specified stage int SubCommunity::stagePop(int stage) { @@ -894,6 +931,15 @@ bool SubCommunity::outTraitsHeaders(Landscape* pLandscape, Species* pSpecies, in outtraits << "\tmeanBetaS\tstdBetaS"; } } + if (pSpecies->getNumberOfAdaptiveTraits() > 0) { + if (NSEXES > 1) { + outtraits << "\tF_meanFitness\tF_stdFitness\tM_meanFitness\tM_stdFitness"; + } + else { + outtraits << "\tmeanFitness\tstdFitness"; + } + } + outtraits << endl; return outtraits.is_open(); @@ -923,6 +969,7 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; ts.sumS0[i] = ts.ssqS0[i] = 0.0; ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; + ts.sumFitness[i] = ts.ssqFitness[i] = 0.0; } // generate output for each population within the sub-community (patch) @@ -1158,6 +1205,39 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, } } } + if (pSpecies->getNumberOfAdaptiveTraits() > 0) { + ngenes = pSpecies->isDiploid() + 1; + double mnFitness[2], sdFitness[2]; + for (int g = 0; g < ngenes; g++) { + mnFitness[g] = sdFitness[g] = 0.0; + + if (ngenes == 2) popsize = poptraits.ninds[g]; + else popsize = poptraits.ninds[0] + poptraits.ninds[1]; + if (popsize > 0) { + mnFitness[g] = poptraits.sumFitness[g] / (double)popsize; + if (popsize > 1) { + sdFitness[g] = poptraits.ssqFitness[g] / (double)popsize - mnFitness[g] * mnFitness[g]; + if (sdFitness[g] > 0.0) sdFitness[g] = sqrt(sdFitness[g]); else sdFitness[g] = 0.0; + } + else { + sdFitness[g] = 0.0; + } + } + } + if (writefile) { + if (NSEXES > 1) { + outtraits << "\t" << mnFitness[0] << "\t" << sdFitness[0]; + outtraits << "\t" << mnFitness[1] << "\t" << sdFitness[1]; + } + else { // sex-independent + outtraits << "\t" << mnFitness[0] << "\t" << sdFitness[0]; + } + } + } + + // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT +// ngenes = 1; + double mnS0[2], mnAlpha[2], mnBeta[2], sdS0[2], sdAlpha[2], sdBeta[2]; if (writefile) outtraits << endl; @@ -1178,6 +1258,7 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, ts.sumS0[s] += poptraits.sumS0[s]; ts.ssqS0[s] += poptraits.ssqS0[s]; ts.sumAlphaS[s] += poptraits.sumAlphaS[s]; ts.ssqAlphaS[s] += poptraits.ssqAlphaS[s]; ts.sumBetaS[s] += poptraits.sumBetaS[s]; ts.ssqBetaS[s] += poptraits.ssqBetaS[s]; + ts.sumFitness[s] += poptraits.sumFitness[s]; ts.ssqFitness[s] += poptraits.ssqFitness[s]; #if RSDEBUG //DEBUGLOG << "SubCommunity::outTraits(): i=" << i << " popns[i]=" << popns[i] // << " s=" << s diff --git a/SubCommunity.h b/SubCommunity.h index e818284..57a58d9 100644 --- a/SubCommunity.h +++ b/SubCommunity.h @@ -39,7 +39,7 @@ Authors: Greta Bocedi & Steve Palmer, University of Aberdeen - Last updated: 26 October 2021 by Steve Palmer + Last updated: 25 June 2021 by Greta Bocedi ------------------------------------------------------------------------------*/ @@ -50,14 +50,7 @@ #include using namespace std; -//#if RS_RCPP && !R_CMD #include "../Version.h" -//#endif - -//#if !RS_RCPP && R_CMD -//#include "../../Batch/Version.h" -//#endif - #include "Parameters.h" #include "Landscape.h" #include "Population.h" @@ -99,7 +92,9 @@ class SubCommunity { int, // Landscape resolution float, // epsilon - global stochasticity value short, // raster type (see Landscape) - bool // TRUE for a patch-based model, FALSE for a cell-based model + bool, // TRUE for a patch-based model, FALSE for a cell-based model + bool, // TRUE if cloning from cold storage + Population* //cold storage ); void emigration(void); // Remove emigrants from their natal patch and add to patch 0 (matrix) @@ -139,8 +134,16 @@ class SubCommunity { // 1 - development and survival ); void ageIncrement(void); + void copyIndividualsForColdStorage(Population*); + + int addEmigrationAndSettlementTraitValues(emigTraits& avgEmTraits, settleTraits& avgSettleTraits); + + void addTransferDataForInd(trfrData* avgTrfrData); + // Find the population of a given species in a given patch Population* findPop(Species*, Patch*); + + int getPopulationCountForStage(int stage); void createOccupancy( int // no. of rows = (no. of years / interval) + 1 ); @@ -172,13 +175,6 @@ class SubCommunity { int // Landscape number (>= 0 to open the file, -999 to close the file // -1 to write data records) ); - void outGenetics( // Write records to genetics file - int, // replicate - int, // year - int, // generation - int // Landscape number (>= 0 to open the file, -999 to close the file - // -1 to write data records) - ); bool outTraitsHeaders( // Open traits file and write header record Landscape*, // pointer to Landscape Species*, // pointer to Species diff --git a/TTrait.h b/TTrait.h new file mode 100644 index 0000000..9e5d8ae --- /dev/null +++ b/TTrait.h @@ -0,0 +1,44 @@ +#ifndef TRAITTH +#define TRAITTH + +#include +#include + +#include "parameters.h" +#include "Mutation.h" +#include "ProtoTrait.h" + +using namespace std; + +class TTrait { +public: + /** Mutation procedure, perform mutations on the genes sequence. **/ + virtual void mutate() = 0; + + virtual unique_ptr clone() const = 0; //copies parameters (if not static) not gene seqeunces + + /** Inheritance procedure, creates a new trait from mother's and father's traits + * @param mother the mother's trait + * @param father the father's trait + **/ + virtual void inherit(TTrait*, set const& , sex_t, int ) = 0; + + /** sequence accessor. + * @return the sequence pointer + **/ + // virtual void** get_sequence() const = 0; + virtual int getNLoci() const = 0; + virtual float getMutationRate() const = 0; + virtual bool isInherited() const = 0; + //virtual vector>> get_mutations() const = 0; + //virtual vector> get_mutations() const = 0; + virtual float getSelectionCoefAtLoci(short chromosome, int i) const = 0; + virtual int countHeterozygoteLoci() const = 0; + virtual bool isHeterozygoteAtLoci(int loci) const = 0; + virtual float express() = 0; + virtual ~TTrait() { } +}; + +extern RSrandom* pRandom; + +#endif \ No newline at end of file diff --git a/TraitFactory.h b/TraitFactory.h new file mode 100644 index 0000000..da806f3 --- /dev/null +++ b/TraitFactory.h @@ -0,0 +1,27 @@ +#ifndef TRAITFACTORYH +#define TRAITFACTORYH + +#include "ProtoTrait.h" +#include "SNPTrait.h" +#include "QTLTrait.h" +#include "AdaptiveTrait.h" + +class TraitFactory +{ +public: + TraitFactory() {}; + + unique_ptr Create(const TraitType traitType, ProtoTrait* protoTrait) + { + if (traitType == SNP) { + return make_unique(protoTrait); + } + else if (traitType == ADAPTIVE1 || traitType == ADAPTIVE2 || traitType == ADAPTIVE3 || traitType == ADAPTIVE4 || traitType == ADAPTIVE5) { + return make_unique(protoTrait); + } + else { + return make_unique(protoTrait); + } + } +}; +#endif \ No newline at end of file From bfd833b27d938f1b6cb028c587cc2d816135a553 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 1 Feb 2024 11:46:35 +0000 Subject: [PATCH 024/332] renaming variables and classes --- Allele.h | 16 +++ Community.cpp | 14 +-- GeneticLoad.cpp | 119 ++++++++---------- GeneticLoad.h | 24 ++-- Individual.cpp | 17 ++- Individual.h | 2 +- Mutation.h | 16 --- NeutralStatsManager.cpp | 53 +++----- NeutralStatsManager.h | 5 - Parameters.h | 2 +- Population.cpp | 30 ++--- Population.h | 6 +- QTLTrait.cpp | 196 ++++++++++++----------------- QTLTrait.h | 26 ++-- SNPTrait.cpp | 115 +++++++---------- SNPTrait.h | 13 +- Species.cpp | 16 +-- Species.h | 8 +- ProtoTrait.cpp => SpeciesTrait.cpp | 19 ++- ProtoTrait.h => SpeciesTrait.h | 8 +- TTrait.h | 8 +- TraitFactory.h | 4 +- 22 files changed, 310 insertions(+), 407 deletions(-) create mode 100644 Allele.h delete mode 100644 Mutation.h rename ProtoTrait.cpp => SpeciesTrait.cpp (89%) rename ProtoTrait.h => SpeciesTrait.h (93%) diff --git a/Allele.h b/Allele.h new file mode 100644 index 0000000..7f8a0a8 --- /dev/null +++ b/Allele.h @@ -0,0 +1,16 @@ +#ifndef ALLELEH +#define ALLELEH + +class Allele { + const int id; + const float value; + const float dominance; + inline static int counter = 0; +public: + Allele(float alleleValue, float alleleDominance) : value(alleleValue), dominance(alleleDominance), id(counter) { ++counter; } + ~Allele() {} + float getAlleleValue() const { return value; }; + float getDominanceCoef() const { return dominance; }; + float getId() const { return id; } +}; +#endif \ No newline at end of file diff --git a/Community.cpp b/Community.cpp index 10cbcc0..c05e023 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1963,14 +1963,14 @@ void Community::writeWCFstatFile(int rep, int yr, int gen) { void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList) { - const set positions = pSpecies->getTrait(SNP)->getPositions(); + const set positions = pSpecies->getSpTrait(SNP)->getPositions(); - int loci = 0; + int thisLocus = 0; for (int position : positions) { outperlocusfstat << yr << "\t" << gen << "\t" << position << "\t"; - outperlocusfstat << pNeutralStatistics->get_fst_WC_loc(loci) << "\t" << pNeutralStatistics->get_fis_WC_loc(loci) << - "\t" << pNeutralStatistics->get_fit_WC_loc(loci) << "\t" << pNeutralStatistics->get_ho_loc(loci); + outperlocusfstat << pNeutralStatistics->get_fst_WC_loc(thisLocus) << "\t" << pNeutralStatistics->get_fis_WC_loc(thisLocus) << + "\t" << pNeutralStatistics->get_fit_WC_loc(thisLocus) << "\t" << pNeutralStatistics->get_ho_loc(thisLocus); for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); @@ -1978,11 +1978,11 @@ void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const int popSize = pPop->sampleSize(); int het = 0; for (unsigned int a = 0; a < nAlleles; ++a) { - het += pPop->getHetero(loci, a); + het += pPop->getHetero(thisLocus, a); } outperlocusfstat << "\t" << het / (2.0 * popSize); } - ++loci; + ++thisLocus; outperlocusfstat << endl; } } @@ -2022,7 +2022,7 @@ void Community::writePairwiseFSTFile(Species* pSpecies, const int yr, const int void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool perLocus, bool pairwise) { - const int nAlleles = (int)(pSpecies->getTrait(SNP)->getMutationParameters().find(MAX)->second); + const int nAlleles = (int)(pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second); const int nLoci = (int)pSpecies->getNPositionsForTrait(SNP); const set patchList = pSpecies->getSamplePatches(); int nInds = 0; diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index 6699a69..7e45c19 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -4,20 +4,19 @@ // for initialising population // ---------------------------------------------------------------------------------------- -GeneticLoad::GeneticLoad(ProtoTrait* P) +GeneticLoad::GeneticLoad(SpeciesTrait* P) { - - pProtoTrait = P; + pSpeciesTrait = P; if (wildType.get() == nullptr) - wildType = make_shared(0.0, 0.0); + wildType = make_shared(0.0, 0.0); - ExpressionType expressionType = pProtoTrait->getExpressionType(); + ExpressionType expressionType = pSpeciesTrait->getExpressionType(); - _inherit_func_ptr = (pProtoTrait->getPloidy() == 1) ? &GeneticLoad::inheritHaploid : &GeneticLoad::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance + _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &GeneticLoad::inheritHaploid : &GeneticLoad::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance - DistributionType mutationDistribution = pProtoTrait->getMutationDistribution(); - map mutationParameters = pProtoTrait->getMutationParameters(); + DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); + map mutationParameters = pSpeciesTrait->getMutationParameters(); switch (mutationDistribution) { case UNIFORM: @@ -56,7 +55,6 @@ GeneticLoad::GeneticLoad(ProtoTrait* P) if (!mutationParameters.count(MEAN)) cout << endl << ("Error:: adaptive mutation distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); - break; } @@ -66,8 +64,8 @@ GeneticLoad::GeneticLoad(ProtoTrait* P) } } - DistributionType dominanceDistribution = pProtoTrait->getDominanceDistribution(); - map dominanceParameters = pProtoTrait->getDominanceParameters(); + DistributionType dominanceDistribution = pSpeciesTrait->getDominanceDistribution(); + map dominanceParameters = pSpeciesTrait->getDominanceParameters(); switch (dominanceDistribution) { case UNIFORM: @@ -120,8 +118,8 @@ GeneticLoad::GeneticLoad(ProtoTrait* P) } } - DistributionType initialDistribution = pProtoTrait->getInitialDistribution(); - map initialParameters = pProtoTrait->getInitialParameters(); + DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); + map initialParameters = pSpeciesTrait->getInitialParameters(); //switch (expressionType) { //case MULTIPLICATIVE: @@ -144,7 +142,7 @@ GeneticLoad::GeneticLoad(ProtoTrait* P) // for creating new individuals // ---------------------------------------------------------------------------------------- -GeneticLoad::GeneticLoad(const GeneticLoad& T) : pProtoTrait(T.pProtoTrait), _inherit_func_ptr(T._inherit_func_ptr) +GeneticLoad::GeneticLoad(const GeneticLoad& T) : pSpeciesTrait(T.pSpeciesTrait), _inherit_func_ptr(T._inherit_func_ptr) {} // ---------------------------------------------------------------------------------------- @@ -152,10 +150,10 @@ GeneticLoad::GeneticLoad(const GeneticLoad& T) : pProtoTrait(T.pProtoTrait), _in // ---------------------------------------------------------------------------------------- void GeneticLoad::mutate() { - const int positionsSize = pProtoTrait->getPositionsSize(); - const auto& positions = pProtoTrait->getPositions(); - const short ploidy = pProtoTrait->getPloidy(); - const float mutationRate = pProtoTrait->getMutationRate(); + const int positionsSize = pSpeciesTrait->getPositionsSize(); + const auto& positions = pSpeciesTrait->getPositions(); + const short ploidy = pSpeciesTrait->getPloidy(); + const float mutationRate = pSpeciesTrait->getMutationRate(); auto rng = pRandom->getRNG(); @@ -175,15 +173,15 @@ void GeneticLoad::mutate() float newSelectionCoef = drawSelectionCoef(); float newDominanceCoef = drawDominance(newSelectionCoef); - auto it = mutations.find(m); //find if position in map already has mutations there + auto it = genes.find(m); //find if position in map already has mutations there - if (it == mutations.end()) { // not found so create new entry in map with wildtype as char default - vector> newAllelePair(2); - newAllelePair[p] = make_shared(newSelectionCoef, newDominanceCoef); //put new mutation value in - mutations.insert(make_pair(m, newAllelePair)); + if (it == genes.end()) { // not found so create new entry in map with wildtype as char default + vector> newAllelePair(2); + newAllelePair[p] = make_shared(newSelectionCoef, newDominanceCoef); //put new mutation value in + genes.insert(make_pair(m, newAllelePair)); } else { //position found, already mutations there - it->second[p] = make_shared(newSelectionCoef, newDominanceCoef); + it->second[p] = make_shared(newSelectionCoef, newDominanceCoef); } } } @@ -196,8 +194,8 @@ void GeneticLoad::mutate() float GeneticLoad::drawDominance(float selCoef) { - DistributionType dominanceDistribution = pProtoTrait->getDominanceDistribution(); - map dominanceParameters = pProtoTrait->getDominanceParameters(); + DistributionType dominanceDistribution = pSpeciesTrait->getDominanceDistribution(); + map dominanceParameters = pSpeciesTrait->getDominanceParameters(); float h = 1.0; //default dominance is 1 @@ -254,8 +252,8 @@ float GeneticLoad::drawDominance(float selCoef) { float GeneticLoad::drawSelectionCoef() { - DistributionType mutationDistribution = pProtoTrait->getMutationDistribution(); - map mutationParameters = pProtoTrait->getMutationParameters(); + DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); + map mutationParameters = pSpeciesTrait->getMutationParameters(); float s = 0.0; //default selection coefficient is 0 @@ -304,21 +302,18 @@ float GeneticLoad::drawSelectionCoef() { // ---------------------------------------------------------------------------------------- -void GeneticLoad::inherit(TTrait* parent, set const& recomPositions, sex_t whichChromosome, int startingChromosome) +void GeneticLoad::inherit(TTrait* parentTrait, set const& recomPositions, sex_t whichChromosome, int startingChromosome) { - - auto parentCast = dynamic_cast (parent); //horrible + auto parentCast = dynamic_cast (parentTrait); //horrible const auto& parent_seq = parentCast->get_mutations(); if (parent_seq.size() > 0) //else nothing to inherit (this->*_inherit_func_ptr) (whichChromosome, parent_seq, recomPositions, startingChromosome); - - } -void GeneticLoad::inheritDiploid(sex_t whichChromosome, map>> const& parentMutations, set const& recomPositions, int parentChromosome) { +void GeneticLoad::inheritDiploid(sex_t whichChromosome, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { - auto it = recomPositions.lower_bound(parentMutations.begin()->first); + auto it = recomPositions.lower_bound(parentGenes.begin()->first); unsigned int nextBreakpoint = *it; @@ -327,7 +322,7 @@ void GeneticLoad::inheritDiploid(sex_t whichChromosome, map nextBreakpoint) { std::advance(it, 1); @@ -337,16 +332,15 @@ void GeneticLoad::inheritDiploid(sex_t whichChromosome, map> newAllelePair(2); + vector> newAllelePair(2); newAllelePair[whichChromosome] = allele; - mutations.insert(make_pair(locus, newAllelePair)); + genes.insert(make_pair(locus, newAllelePair)); } else { // locus already exists - // presumably bc already inherited from other parent // set corresponding allele it->second[whichChromosome] = allele; } @@ -354,9 +348,9 @@ void GeneticLoad::inheritDiploid(sex_t whichChromosome, map>> const& parentMutations, set const& recomPositions, int parentChromosome) +void GeneticLoad::inheritHaploid(sex_t chromosome, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { - mutations = parentMutations; + genes = parentGenes; } // ---------------------------------------------------------------------------------------- @@ -367,40 +361,39 @@ float GeneticLoad::express() { float phenotype = 1.0; - for (auto const& [locus, pAllelePair] : mutations) + for (auto const& [locus, pAllelePair] : genes) { auto pAlleleLeft = (!pAllelePair[0]) ? wildType : pAllelePair[0]; auto pAlleleRight = (!pAllelePair[1]) ? wildType : pAllelePair[1]; if (pAlleleLeft.get()->getId() != pAlleleRight.get()->getId()) // heterozygote { - phenotype *= 1 + pAlleleLeft->getSelectionCoef() * pAlleleLeft->getDominanceCoef(); - phenotype *= 1 + pAlleleRight->getSelectionCoef() * pAlleleRight->getDominanceCoef(); + phenotype *= 1 + pAlleleLeft->getAlleleValue() * pAlleleLeft->getDominanceCoef(); + phenotype *= 1 + pAlleleRight->getAlleleValue() * pAlleleRight->getDominanceCoef(); } else { // homozygote - phenotype *= 1 + pAlleleLeft->getSelectionCoef(); - phenotype *= 1 + pAlleleRight->getSelectionCoef(); + phenotype *= 1 + pAlleleLeft->getAlleleValue(); + phenotype *= 1 + pAlleleRight->getAlleleValue(); } } return phenotype; } // ---------------------------------------------------------------------------------------- -// check if particular loci is heterozygote +// check if particular locus is heterozygote // ---------------------------------------------------------------------------------------- -bool GeneticLoad::isHeterozygoteAtLoci(int loci) const { +bool GeneticLoad::isHeterozygoteAtLocus(int locus) const { - auto it = mutations.find(loci); + auto it = genes.find(locus); - if (it == mutations.end()) //not found so must be wildtype homozygous + if (it == genes.end()) //not found so must be wildtype homozygous return false; else { auto a = (!it->second[0]) ? wildType : it->second[0]; auto b = (!it->second[1]) ? wildType : it->second[1]; return a != b; - } } @@ -413,13 +406,11 @@ int GeneticLoad::countHeterozygoteLoci() const { int count = 0; - for (auto const& [key, val] : mutations) { - - auto a = (!val[0]) ? wildType : val[0]; - auto b = (!val[1]) ? wildType : val[1]; - count += a != b; + for (auto const& [locus, allelePair] : genes) { + auto alleleLeft = (!allelePair[0]) ? wildType : allelePair[0]; + auto alleleRight = (!allelePair[1]) ? wildType : allelePair[1]; + count += alleleLeft != alleleRight; } - return count; } @@ -428,13 +419,13 @@ int GeneticLoad::countHeterozygoteLoci() const { // ---------------------------------------------------------------------------------------- -float GeneticLoad::getSelectionCoefAtLoci(short chromosome, int position) const { +float GeneticLoad::getSelectionCoefAtLoci(short whichChromosome, int position) const { - auto it = mutations.find(position); + auto it = genes.find(position); - if (it == mutations.end()) { - return wildType->getSelectionCoef(); //must still be wildtype at loci + if (it == genes.end()) { + return wildType->getAlleleValue(); //must still be wildtype at loci } else - return (!it->second[chromosome]) ? wildType->getSelectionCoef() : it->second[chromosome]->getSelectionCoef(); + return (!it->second[whichChromosome]) ? wildType->getAlleleValue() : it->second[whichChromosome]->getAlleleValue(); } \ No newline at end of file diff --git a/GeneticLoad.h b/GeneticLoad.h index c55b246..ae0a585 100644 --- a/GeneticLoad.h +++ b/GeneticLoad.h @@ -12,18 +12,18 @@ class GeneticLoad : public TTrait { private: - ProtoTrait* pProtoTrait; + SpeciesTrait* pSpeciesTrait; - map>> mutations; // position > + map>> genes; // position > - inline static shared_ptr wildType; + inline static shared_ptr wildType; // void (AdaptiveTrait::* _mutate_func_ptr) (void); - void (GeneticLoad::* _inherit_func_ptr) (sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); + void (GeneticLoad::* _inherit_func_ptr) (sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); //float (AdaptiveTrait::* _express_func_ptr) (void); - void inheritDiploid(sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); - void inheritHaploid(sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); + void inheritDiploid(sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); + void inheritHaploid(sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); float drawDominance(float); float drawSelectionCoef(); @@ -32,7 +32,7 @@ class GeneticLoad : public TTrait { //this one for species held trait table, e.g. prototype table, sets static members - GeneticLoad(ProtoTrait* P); + GeneticLoad(SpeciesTrait* P); //this one for individuals, static members are not reset GeneticLoad(const GeneticLoad& T); @@ -43,19 +43,19 @@ class GeneticLoad : public TTrait { virtual void mutate() override; - virtual int getNLoci() const override { return pProtoTrait->getPositionsSize(); } + virtual int getNLoci() const override { return pSpeciesTrait->getPositionsSize(); } - float getMutationRate() const override { return pProtoTrait->getMutationRate(); } + float getMutationRate() const override { return pSpeciesTrait->getMutationRate(); } - bool isInherited() const override { return pProtoTrait->isInherited(); } + bool isInherited() const override { return pSpeciesTrait->isInherited(); } - map>>& get_mutations() { return mutations; } //returning reference, reciever must be const + map>>& get_mutations() { return genes; } //returning reference, reciever must be const virtual float getSelectionCoefAtLoci(short chromosome, int position) const override; virtual int countHeterozygoteLoci() const; - virtual bool isHeterozygoteAtLoci(int loci) const override; + virtual bool isHeterozygoteAtLocus(int locus) const override; virtual float express(); diff --git a/Individual.cpp b/Individual.cpp index 411ffdc..25dc99f 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -118,9 +118,8 @@ void Individual::setSettleTraits(const settleTraits& settle) { pSettleTraits = make_unique(settle); } - TTrait* Individual::getTrait(TraitType trait) const { - return this->traitTable.find(trait)->second.get(); + return this->spTraitTable.find(trait)->second.get(); } //map> Individual::getTraitTable(void) const @@ -129,7 +128,7 @@ TTrait* Individual::getTrait(TraitType trait) const { //} set Individual::getTraitTypes() { - auto kv = std::views::keys(this->traitTable); + auto kv = std::views::keys(this->spTraitTable); set< TraitType > keys{ kv.begin(), kv.end() }; return keys; } @@ -197,7 +196,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi if (trait == ADAPTIVE1 || trait == ADAPTIVE2 || trait == ADAPTIVE3 || trait == ADAPTIVE4 || trait == ADAPTIVE5) fitness *= newTrait->express(); - traitTable.insert(make_pair(trait, move(newTrait))); + spTraitTable.insert(make_pair(trait, move(newTrait))); } } @@ -222,7 +221,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother) { if (trait == ADAPTIVE1 || trait == ADAPTIVE2 || trait == ADAPTIVE3 || trait == ADAPTIVE4 || trait == ADAPTIVE5) fitness *= newTrait->express(); - traitTable.insert(make_pair(trait, move(newTrait))); + spTraitTable.insert(make_pair(trait, move(newTrait))); } } @@ -231,12 +230,12 @@ void Individual::setUpGenes(Species* pSpecies, int resol) { // this way to keep spp trait table immutable i.e. not able to call getTraitTable, // could pass it back by value (copy) instead but could be heavy if large map - const auto& speciesTraits = pSpecies->getTraitTypes(); + const auto& traitTypes = pSpecies->getTraitTypes(); - for (auto const& trait : speciesTraits) + for (auto const& traitType : traitTypes) { - const auto spTrait = pSpecies->getTrait(trait); - this->traitTable.emplace(trait, traitFactory.Create(trait, spTrait)); + const auto spTrait = pSpecies->getSpTrait(traitType); + this->spTraitTable.emplace(traitType, traitFactory.Create(traitType, spTrait)); } setQTLPhenotypes(pSpecies, resol); } diff --git a/Individual.h b/Individual.h index 412ba1c..bd43de0 100644 --- a/Individual.h +++ b/Individual.h @@ -416,7 +416,7 @@ class Individual { std::unique_ptr pSettleTraits; // pointer to settlement traits std::unique_ptr pTrfrData; //can be sms, kernel, crw std::queue memory; // memory of last N squares visited for SMS - map> traitTable; + map> spTraitTable; }; diff --git a/Mutation.h b/Mutation.h deleted file mode 100644 index a9ea4fc..0000000 --- a/Mutation.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef MUTATIONH -#define MUTATIONH - -class Mutation { - const int id; - const float selCoef; - const float dominance; - inline static int counter = 0; -public: - Mutation(float selCoefA, float dominanceA) : selCoef(selCoefA), dominance(dominanceA), id(counter) { ++counter; } - ~Mutation() {} - float getSelectionCoef() const { return selCoef; }; - float getDominanceCoef() const { return dominance; }; - float getId() const { return id; } -}; -#endif \ No newline at end of file diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 141eb03..bcd59b5 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -21,21 +21,16 @@ * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . * - * File Created by RH March 2023. Code adapted from NEMO (https://nemo2.sourceforge.io/) + * File Created by Roslyn Henry March 2023. Code adapted from NEMO (https://nemo2.sourceforge.io/) --------------------------------------------------------------------------*/ // ---------------------------------------------------------------------------------------- // Cstor // ---------------------------------------------------------------------------------------- - - NeutralStatsManager::NeutralStatsManager(set const& patchList, const int nLoci) { - this->_fst_matrix = PatchMatrix(patchList.size(), patchList.size()); - globalAlleleTable.reserve(nLoci); //don't have to be pointers, not shared or moved - } // ---------------------------------------------------------------------------------------- @@ -46,7 +41,7 @@ NeutralStatsManager::NeutralStatsManager(set const& patchList, const int nL void NeutralStatsManager::updateAlleleTables(Species* pSpecies, Landscape* pLandscape, set const& patchList) { const int nLoci = pSpecies->getNPositionsForTrait(SNP); - const int nAlleles = (int)pSpecies->getTrait(SNP)->getMutationParameters().find(MAX)->second; + const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; const int chromosomes = (pSpecies->isDiploid() ? 2 : 1); if (!globalAlleleTable.empty()) @@ -60,16 +55,16 @@ void NeutralStatsManager::updateAlleleTables(Species* pSpecies, Landscape* pLand pPop->updateAlleleTable(); populationSize += pPop->sampleSize(); - for (int loci = 0; loci < nLoci; loci++) { + for (int thisLocus = 0; thisLocus < nLoci; thisLocus++) { for (int allele = 0; allele < nAlleles; allele++) { - int patchAlleleCount = pPop->getAlleleCount(loci, allele); + int patchAlleleCount = pPop->getAlleleCount(thisLocus, allele); - if (globalAlleleTable.size() <= loci) { //if first allele of new loci (should only happen in first calculation step) + if (globalAlleleTable.size() <= thisLocus) { //if first allele of new loci (should only happen in first calculation step) NeutralData n = NeutralData(nAlleles, allele, patchAlleleCount); globalAlleleTable.push_back(n); } - else globalAlleleTable[loci].incrementCountBy(patchAlleleCount, allele); + else globalAlleleTable[thisLocus].incrementCountBy(patchAlleleCount, allele); } } } @@ -102,7 +97,7 @@ void NeutralStatsManager::setLociDiversityCounter(set const& patchList, con { unsigned int i, j, k; const int nLoci = pSpecies->getNPositionsForTrait(SNP); - const int nAlleles = (int)pSpecies->getTrait(SNP)->getMutationParameters().find(MAX)->second; + const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; const int chromosomes = (pSpecies->isDiploid() ? 2 : 1); unsigned int nbpatch = 0; double patch_mean, pop_mean = 0; @@ -128,7 +123,7 @@ void NeutralStatsManager::setLociDiversityCounter(set const& patchList, con for (i = 0; i < nLoci; ++i) for (j = 0; j < nAlleles; ++j) { patch_mean += (pPop->getAlleleCount(i, j) != 0); - pop_div[i][j] |= (pPop->getAlleleCount(i, j) != 0); + pop_div[i][j] |= (pPop->getAlleleCount(i, j) != 0); // OR } // add mean nb of alleles per locus for Patch k to the pop mean pop_mean += patch_mean / nLoci; @@ -223,18 +218,18 @@ void NeutralStatsManager::calculateHt(Species* pSpecies, Landscape* pLandscape, vectorlocihet(nLoci, 1); double freq; - for (int loci = 0; loci < nLoci; ++loci) { + for (int thisLocus = 0; thisLocus < nLoci; ++thisLocus) { for (int allele = 0; allele < nAlleles; ++allele) { - freq = globalAlleleTable[loci].getFrequency(allele); + freq = globalAlleleTable[thisLocus].getFrequency(allele); freq *= freq; //squared frequencies - locihet[loci] -= freq; //1 - sum of p2 = expected heterozygosity + locihet[thisLocus] -= freq; //1 - sum of p2 = expected heterozygosity } - ht += locihet[loci]; + ht += locihet[thisLocus]; } _ht = ht / nLoci; @@ -307,7 +302,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int double a = 0, b = 0, c = 0, x; - for (unsigned int loci = 0; loci < nLoci; ++loci) { + for (unsigned int thisLocus = 0; thisLocus < nLoci; ++thisLocus) { for (unsigned int allele = 0; allele < nAlleles; ++allele) { @@ -317,18 +312,18 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - var = pPop->getAlleleFrequency(loci, allele) - globalAlleleTable[loci].getFrequency(allele); //(p_liu - pbar_u)^2 + var = pPop->getAlleleFrequency(thisLocus, allele) - globalAlleleTable[thisLocus].getFrequency(allele); //(p_liu - pbar_u)^2 var *= var; s2 += var * pPop->sampleSize(); - h_bar += pPop->getHetero(loci, allele); + h_bar += pPop->getHetero(thisLocus, allele); }//end for pop s2 *= s2_denom; - p_bar = globalAlleleTable[loci].getFrequency(allele); + p_bar = globalAlleleTable[thisLocus].getFrequency(allele); h_bar *= inverse_n_total; x = p_bar * (1 - p_bar) - r * s2; @@ -371,7 +366,6 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i nc = (nInds - sum_weights) / (extantPs - 1); - unsigned int npl = extantPs; //all loci typed in all patches //p = _alleleFreqTable @@ -451,17 +445,13 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i SSP[all_cntr] += 2 * popSize * var; } - all_cntr++; } - } - if (all_cntr != tot_num_allele) cout << endl << ("Error:: allele counter and total number of alleles differ in WC mean squared Fstat calculation \n"); - //these shouldn't have to be dynamically allocated manually, if using a vector from stl then would do allocation for you vector MSG(tot_num_allele); @@ -505,9 +495,6 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i SIGB += sigb[i]; SIGW += sigw[i]; } - - - double lsiga, lsigb, lsigw; // cout<<" computing sigma per locus\n"; @@ -517,13 +504,10 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i lsiga = lsigb = lsigw = 0; for (unsigned int l = 0; l < alploc[i]; ++l) { - lsiga += siga[allcntr]; lsigb += sigb[allcntr]; lsigw += sigw[allcntr]; - allcntr++; - } _fst_WC_loc[i] = lsiga / (lsiga + lsigb + lsigw); @@ -560,7 +544,7 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape) { - const int nAlleles = (int)pSpecies->getTrait(SNP)->getMutationParameters().find(MAX)->second; + const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; vector patchVect; @@ -571,7 +555,6 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd //initialise if (_fst_matrix.length() != nPatches * nPatches) - _fst_matrix = PatchMatrix(nPatches, nPatches); //reset table @@ -589,7 +572,6 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd tot_size = nInds * 2; //diploid - for (unsigned int i = 0; i < nPatches; ++i) { const auto patch = pLandscape->findPatch(patchVect[i]); @@ -683,7 +665,6 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd } } - for (unsigned int i = 0; i < nPatches - 1; ++i) { if (!pop_sizes[i]) continue; for (unsigned int j = i + 1; j < nPatches; ++j) { diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index 5385314..23ce1bb 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -4,7 +4,6 @@ #include "Species.h" #include "Landscape.h" - using namespace std; /**Creates an array of doubles of size = rows*cols, taken from NEMO**/ @@ -99,10 +98,6 @@ struct NeutralData { void incrementHeteroBy(int count, int allele) { this->heteros[allele] += count; } - - - - }; diff --git a/Parameters.h b/Parameters.h index bef43e3..171a0a5 100644 --- a/Parameters.h +++ b/Parameters.h @@ -171,7 +171,7 @@ set convertStringToChromosomeEnds(string, int); //sex types typedef enum { - FEM = 0, MAL = 1, BOTH = 2 + FEM = 0, MAL = 1 } sex_t; const sex_t stringToSex(const std::string& str); diff --git a/Population.cpp b/Population.cpp index 5035903..a198a0c 100644 --- a/Population.cpp +++ b/Population.cpp @@ -343,8 +343,8 @@ void Population::resetAlleleTable() { void Population::updateAlleleTable() { const int nLoci = pSpecies->getNPositionsForTrait(SNP); - const int nAlleles = (int)pSpecies->getTrait(SNP)->getMutationParameters().find(MAX)->second; - const auto& positions = pSpecies->getTrait(SNP)->getPositions(); + const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; + const auto& positions = pSpecies->getSpTrait(SNP)->getPositions(); if (alleleTable.size() != 0) resetAlleleTable(); @@ -388,17 +388,17 @@ void Population::updateAlleleTable() { } } -double Population::getAlleleFrequency(int loci, int allele) { - return alleleTable[loci].getFrequency(allele); +double Population::getAlleleFrequency(int locus, int allele) { + return alleleTable[locus].getFrequency(allele); } -int Population::getAlleleCount(int loci, int allele) { - return alleleTable[loci].getCount(allele); +int Population::getAlleleCount(int locus, int allele) { + return alleleTable[locus].getCount(allele); } -double Population::getHetero(int loci, int allele) { - return alleleTable[loci].getHetero(allele); +double Population::getHetero(int locus, int allele) { + return alleleTable[locus].getHetero(allele); } // ---------------------------------------------------------------------------------------- @@ -419,14 +419,14 @@ int Population::countHeterozygoteLoci() { // ---------------------------------------------------------------------------------------- vector Population::countLociHeterozyotes() { - const auto& positions = pSpecies->getTrait(SNP)->getPositions(); + const auto& positions = pSpecies->getSpTrait(SNP)->getPositions(); vector hetero(positions.size(), 0); for (Individual* ind : sampledInds) { const auto trait = ind->getTrait(SNP); int counter = 0; for (auto position : positions) { - hetero[counter] += trait->isHeterozygoteAtLoci(position); + hetero[counter] += trait->isHeterozygoteAtLocus(position); counter++; } } @@ -439,20 +439,20 @@ vector Population::countLociHeterozyotes() { double Population::computeHs() { int nLoci = pSpecies->getNPositionsForTrait(SNP); - int nAlleles = (int)pSpecies->getTrait(SNP)->getInitialParameters().find(MAX)->second; + int nAlleles = (int)pSpecies->getSpTrait(SNP)->getInitialParameters().find(MAX)->second; double hs = 0; double freq; vectorlocihet(nLoci, 1); if (sampledInds.size() > 0) { - for (int loci = 0; loci < nLoci; ++loci) { + for (int thisLocus = 0; thisLocus < nLoci; ++thisLocus) { for (int allele = 0; allele < nAlleles; ++allele) { - freq = getAlleleFrequency(loci, allele); + freq = getAlleleFrequency(thisLocus, allele); freq *= freq; //squared frequencies (expected _homozygosity) - locihet[loci] -= freq; //1 - sum of p2 = expected heterozygosity + locihet[thisLocus] -= freq; //1 - sum of p2 = expected heterozygosity } - hs += locihet[loci]; + hs += locihet[thisLocus]; } } return hs; diff --git a/Population.h b/Population.h index 6a6ab67..c7743b1 100644 --- a/Population.h +++ b/Population.h @@ -232,9 +232,9 @@ class Population { void clean(void); // Remove zero pointers to dead or dispersed individuals void updateAlleleTable(); - double getAlleleFrequency(int loci, int allele); - int getAlleleCount(int loci, int allele); - double getHetero(int loci, int allele); + double getAlleleFrequency(int locus, int allele); + int getAlleleCount(int locus, int allele); + double getHetero(int locus, int allele); int countHeterozygoteLoci(); vector countLociHeterozyotes(); double computeHs(); diff --git a/QTLTrait.cpp b/QTLTrait.cpp index 200145a..6c9d451 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -4,18 +4,18 @@ // for initialising population // ---------------------------------------------------------------------------------------- -QTLTrait::QTLTrait(ProtoTrait* P) +QTLTrait::QTLTrait(SpeciesTrait* P) { - pProtoTrait = P; - ExpressionType expressionType = pProtoTrait->getExpressionType(); + pSpeciesTrait = P; + ExpressionType expressionType = pSpeciesTrait->getExpressionType(); - if (!pProtoTrait->isInherited()) //there is a trait for individual variation but this isn't inherited variation it's sampled from initial distribution + if (!pSpeciesTrait->isInherited()) //there is a trait for individual variation but this isn't inherited variation it's sampled from initial distribution _inherit_func_ptr = &QTLTrait::inheritInitialParameters; else { - _inherit_func_ptr = (pProtoTrait->getPloidy() == 1) ? &QTLTrait::inheritHaploid : &QTLTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance + _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &QTLTrait::inheritHaploid : &QTLTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance - DistributionType mutationDistribution = pProtoTrait->getMutationDistribution(); - map mutationParameters = pProtoTrait->getMutationParameters(); + DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); + map mutationParameters = pSpeciesTrait->getMutationParameters(); switch (mutationDistribution) { case UNIFORM: @@ -49,8 +49,8 @@ QTLTrait::QTLTrait(ProtoTrait* P) } } - DistributionType initialDistribution = pProtoTrait->getInitialDistribution(); - map initialParameters = pProtoTrait->getInitialParameters(); + DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); + map initialParameters = pSpeciesTrait->getInitialParameters(); switch (initialDistribution) { case UNIFORM: @@ -113,7 +113,7 @@ QTLTrait::QTLTrait(ProtoTrait* P) // for creating new individuals // ---------------------------------------------------------------------------------------- -QTLTrait::QTLTrait(const QTLTrait& T) : pProtoTrait(T.pProtoTrait), _mutate_func_ptr(T._mutate_func_ptr), _inherit_func_ptr(T._inherit_func_ptr), _express_func_ptr(T._express_func_ptr) +QTLTrait::QTLTrait(const QTLTrait& T) : pSpeciesTrait(T.pSpeciesTrait), _mutate_func_ptr(T._mutate_func_ptr), _inherit_func_ptr(T._inherit_func_ptr), _express_func_ptr(T._express_func_ptr) {} @@ -123,14 +123,14 @@ QTLTrait::QTLTrait(const QTLTrait& T) : pProtoTrait(T.pProtoTrait), _mutate_func // ---------------------------------------------------------------------------------------- void QTLTrait::mutateUniform() { - const int positionsSize = pProtoTrait->getPositionsSize(); - const auto& positions = pProtoTrait->getPositions(); - const short ploidy = pProtoTrait->getPloidy(); - const float mutationRate = pProtoTrait->getMutationRate(); + const int positionsSize = pSpeciesTrait->getPositionsSize(); + const auto& positions = pSpeciesTrait->getPositions(); + const short ploidy = pSpeciesTrait->getPloidy(); + const float mutationRate = pSpeciesTrait->getMutationRate(); auto rng = pRandom->getRNG(); - map mutationParameters = pProtoTrait->getMutationParameters(); + map mutationParameters = pSpeciesTrait->getMutationParameters(); float maxD = mutationParameters.find(MAX)->second; float minD = mutationParameters.find(MIN)->second; @@ -144,17 +144,13 @@ void QTLTrait::mutateUniform() NbMut, rng); for (int m : mutationPositions) { - - auto it = mutations.find(m); - float currentSelCoef = it->second[p].get()->getSelectionCoef();//current - float newSelectionCoef = pRandom->FRandom(minD, maxD) + currentSelCoef; - it->second[p] = make_shared(newSelectionCoef, 1.0); - + auto it = genes.find(m); + float currentAlleleVal = it->second[p].get()->getAlleleValue();//current + float newAlleleVal = pRandom->FRandom(minD, maxD) + currentAlleleVal; + it->second[p] = make_shared(newAlleleVal, 1.0); } } - } - } // ---------------------------------------------------------------------------------------- @@ -164,19 +160,18 @@ void QTLTrait::mutateUniform() void QTLTrait::mutateNormal() { - const int positionsSize = pProtoTrait->getPositionsSize(); - const auto& positions = pProtoTrait->getPositions(); - const short ploidy = pProtoTrait->getPloidy(); - const float mutationRate = pProtoTrait->getMutationRate(); + const int positionsSize = pSpeciesTrait->getPositionsSize(); + const auto& positions = pSpeciesTrait->getPositions(); + const short ploidy = pSpeciesTrait->getPloidy(); + const float mutationRate = pSpeciesTrait->getMutationRate(); auto rng = pRandom->getRNG(); - const map mutationParameters = pProtoTrait->getMutationParameters(); + const map mutationParameters = pSpeciesTrait->getMutationParameters(); const float mean = mutationParameters.find(MEAN)->second; const float sd = mutationParameters.find(SDEV)->second; - for (int p = 0; p < ploidy; p++) { unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); @@ -187,17 +182,13 @@ void QTLTrait::mutateNormal() NbMut, rng); for (int m : mutationPositions) { - - auto it = mutations.find(m); - float currentSelCoef = it->second[p].get()->getSelectionCoef();//current - float newSelectionCoef = pRandom->Normal(mean, sd) + currentSelCoef; - it->second[p] = make_shared(newSelectionCoef, 1.0); + auto it = genes.find(m); + float currentAlleleVal = it->second[p].get()->getAlleleValue();//current + float newAlleleVal = pRandom->Normal(mean, sd) + currentAlleleVal; + it->second[p] = make_shared(newAlleleVal, 1.0); } } - - } - } // ---------------------------------------------------------------------------------------- @@ -205,21 +196,18 @@ void QTLTrait::mutateNormal() // ---------------------------------------------------------------------------------------- -void QTLTrait::inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) +void QTLTrait::inherit(TTrait* parentTrait, set const& recomPositions, sex_t whichChromosome, int startingChromosome) { - - auto parentCast = dynamic_cast (parent); //horrible + auto parentCast = dynamic_cast (parentTrait); //horrible const auto& parent_seq = parentCast->get_mutations(); if (parent_seq.size() > 0) //else nothing to inherit, should always be something to inherit with QTL - (this->*_inherit_func_ptr) (chromosome, parent_seq, recomPositions, startingChromosome); - - + (this->*_inherit_func_ptr) (whichChromosome, parent_seq, recomPositions, startingChromosome); } -void QTLTrait::inheritDiploid(sex_t chromosome, map>> const& parentMutations, set const& recomPositions, int parentChromosome) { +void QTLTrait::inheritDiploid(sex_t whichChromosome, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { - auto it = recomPositions.lower_bound(parentMutations.begin()->first); + auto it = recomPositions.lower_bound(parentGenes.begin()->first); unsigned int nextBreakpoint = *it; @@ -227,60 +215,45 @@ void QTLTrait::inheritDiploid(sex_t chromosome, map nextBreakpoint) { + while (locus > nextBreakpoint) { std::advance(it, 1); nextBreakpoint = *it; parentChromosome = !parentChromosome; //switch chromosome } - if (key <= nextBreakpoint) { - auto& sp = val[parentChromosome]; + if (locus <= nextBreakpoint) { + auto& sp = allelePair[parentChromosome]; - - auto it = mutations.find(key); - if (it == mutations.end()) { + auto it = genes.find(locus); + if (it == genes.end()) { // not found - vector> vect(2); - vect[chromosome] = sp; + vector> newAllelePair(2); + newAllelePair[whichChromosome] = sp; - mutations.insert(make_pair(key, vect)); + genes.insert(make_pair(locus, newAllelePair)); } else { - it->second[chromosome] = sp; - - + it->second[whichChromosome] = sp; } - - - } - - - } - - - - - } -void QTLTrait::inheritHaploid(sex_t chromosome, map>> const& parentMutations, set const& recomPositions, int parentChromosome) +void QTLTrait::inheritHaploid(sex_t chromosome, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { - mutations = parentMutations; + genes = parentGenes; } // ---------------------------------------------------------------------------------------- // 'Inherit' from initialisation parameters, for simulations with individual variation but no inheritance // ---------------------------------------------------------------------------------------- -void QTLTrait::inheritInitialParameters(sex_t chromosome, map>> const& parentMutations, set const& recomPositions, int parentChromosome) +void QTLTrait::inheritInitialParameters(sex_t whichChromosome, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { - DistributionType initialDistribution = pProtoTrait->getInitialDistribution(); - map initialParameters = pProtoTrait->getInitialParameters(); - + DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); + map initialParameters = pSpeciesTrait->getInitialParameters(); switch (initialDistribution) { case UNIFORM: @@ -330,33 +303,31 @@ void QTLTrait::inheritInitialParameters(sex_t chromosome, mapgetPositions(); - short ploidy = pProtoTrait->getPloidy(); + const auto positions = pSpeciesTrait->getPositions(); + short ploidy = pSpeciesTrait->getPloidy(); for (auto position : positions) { - vector> vect; - + vector> newAllelePair; for (int i = 0; i < ploidy; i++) { - float selectionCoef = pRandom->Normal(mean, sd); - vect.emplace_back(make_shared(selectionCoef, 1.0));//crude here to set dominance to 1 for qtl but can be changed later + float alleleVal = pRandom->Normal(mean, sd); + newAllelePair.emplace_back(make_shared(alleleVal, QTLDominanceFactor)); } - mutations.insert(make_pair(position, vect)); + genes.insert(make_pair(position, newAllelePair)); } } void QTLTrait::initialiseUniform(float min, float max) { - const auto positions = pProtoTrait->getPositions(); - short ploidy = pProtoTrait->getPloidy(); + const auto positions = pSpeciesTrait->getPositions(); + short ploidy = pSpeciesTrait->getPloidy(); for (auto position : positions) { - vector> vect; - + vector> newAllelePair; for (int i = 0; i < ploidy; i++) { - float selectionCoef = pRandom->FRandom(min, max); - vect.emplace_back(make_shared(selectionCoef, 1.0)); //crude here to set dominance to 1 for qtl but can be changed later + float alleleVal = pRandom->FRandom(min, max); + newAllelePair.emplace_back(make_shared(alleleVal, QTLDominanceFactor)); } - mutations.insert(make_pair(position, vect)); + genes.insert(make_pair(position, newAllelePair)); } } @@ -368,27 +339,26 @@ float QTLTrait::expressAdditive() { float phenotype = 0.0; - for (auto const& [key, val] : mutations) + for (auto const& [locus, allelePair] : genes) { - for (auto m : val) - phenotype += m->getSelectionCoef(); + for (auto m : allelePair) + phenotype += m->getAlleleValue(); } - return phenotype; } float QTLTrait::expressAverage() { - int positionsSize = pProtoTrait->getPositionsSize(); - short ploidy = pProtoTrait->getPloidy(); + int positionsSize = pSpeciesTrait->getPositionsSize(); + short ploidy = pSpeciesTrait->getPloidy(); float phenotype = 0.0; - for (auto const& [key, val] : mutations) + for (auto const& [locus, allelePair] : genes) { - for (auto& m : val) - phenotype += m->getSelectionCoef(); + for (auto& m : allelePair) + phenotype += m->getAlleleValue(); } - phenotype = phenotype / (positionsSize * ploidy); + phenotype /= positionsSize * ploidy; return phenotype; } @@ -396,19 +366,17 @@ float QTLTrait::expressAverage() { // check if particular loci is heterozygote // ---------------------------------------------------------------------------------------- +bool QTLTrait::isHeterozygoteAtLocus(int locus) const { -bool QTLTrait::isHeterozygoteAtLoci(int loci) const { + auto it = genes.find(locus); - auto it = mutations.find(loci); - - if (it == mutations.end()) //not found + if (it == genes.end()) //not found return false; else { if (it->second.size() == 1) //only one ptr there so must be allele and wildtype at loci (heterozygote) return true; else return(it->second[0].get()->getId() != it->second[1].get()->getId()); - } } @@ -416,20 +384,17 @@ bool QTLTrait::isHeterozygoteAtLoci(int loci) const { // count heterozygote loci in genome // ---------------------------------------------------------------------------------------- - int QTLTrait::countHeterozygoteLoci() const { int count = 0; + for (auto const& [locus, allelePair] : genes) { - for (auto const& [key, val] : mutations) { - - if (val.size() == 1) //only one ptr there so must be allele and wildtype at loci (heterozygote) + if (allelePair.size() == 1) //only one ptr there so must be allele and wildtype at loci (heterozygote) count++; - if (val.size() == 2) - count += (val[0].get()->getId() != val[1].get()->getId()); + if (allelePair.size() == 2) + count += (allelePair[0].get()->getId() != allelePair[1].get()->getId()); } - return count; } @@ -437,16 +402,15 @@ int QTLTrait::countHeterozygoteLoci() const { // get allele value at loci // ---------------------------------------------------------------------------------------- +float QTLTrait::getSelectionCoefAtLoci(short whichChromosome, int position) const { -float QTLTrait::getSelectionCoefAtLoci(short chromosome, int position) const { - - auto it = mutations.find(position); + auto it = genes.find(position); - if (it == mutations.end()) { //no mutations there, should never happen at QTLs should always hold a value + if (it == genes.end()) { //no mutations there, should never happen at QTLs should always hold a value return 0; //must still be wildtype at loci cout << endl << ("Error:: trying to find QTL at ", position, " but doesn't exist \n"); } else - return it->second[chromosome].get()->getSelectionCoef(); + return it->second[whichChromosome].get()->getAlleleValue(); } \ No newline at end of file diff --git a/QTLTrait.h b/QTLTrait.h index 98cbc00..8840abe 100644 --- a/QTLTrait.h +++ b/QTLTrait.h @@ -13,19 +13,21 @@ class QTLTrait : public TTrait { private: - ProtoTrait* pProtoTrait; // would be better as const so immutable, but means passing positions list is heavy and can't be passed by reference + constexpr double QTLDominanceFactor = 1.0; // that is, no dominance - map>> mutations; //position > + SpeciesTrait* pSpeciesTrait; // would be better as const so immutable, but means passing positions list is heavy and can't be passed by reference + + map>> genes; //position > void (QTLTrait::* _mutate_func_ptr) (void); - void (QTLTrait::* _inherit_func_ptr) (sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); + void (QTLTrait::* _inherit_func_ptr) (sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); float (QTLTrait::* _express_func_ptr) (void); void initialiseUniform(float min, float max); void initialiseNormal(float mean, float sd); - void inheritDiploid(sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); - void inheritHaploid(sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); - void inheritInitialParameters(sex_t chromosome, map>> const& parentMutations, set const& recomPositions, int parentChromosome); + void inheritDiploid(sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); + void inheritHaploid(sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); + void inheritInitialParameters(sex_t chromosome, map>> const& parentMutations, set const& recomPositions, int parentChromosome); void mutateUniform(); void mutateNormal(); float expressAverage(); @@ -34,22 +36,22 @@ class QTLTrait : public TTrait { public: //this one for species held trait table, e.g. prototype table, sets static members - QTLTrait(ProtoTrait* P); + QTLTrait(SpeciesTrait* P); QTLTrait(const QTLTrait& T); virtual unique_ptr clone() const override { return std::make_unique(*this); } - int getNLoci() const override { return pProtoTrait->getPositionsSize(); } - float getMutationRate() const override { return pProtoTrait->getMutationRate(); } - bool isInherited() const override { return pProtoTrait->isInherited(); } + int getNLoci() const override { return pSpeciesTrait->getPositionsSize(); } + float getMutationRate() const override { return pSpeciesTrait->getMutationRate(); } + bool isInherited() const override { return pSpeciesTrait->isInherited(); } void mutate() override { (this->*_mutate_func_ptr) (); } float express() override { return (this->*_express_func_ptr) (); } void inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) override; - map>>& get_mutations() { return mutations; } // returning reference, receiver must be const + map>>& get_mutations() { return genes; } // returning reference, receiver must be const // virtual float getSelectionCoefAtLoci(short chromosome, int i) const override { return (double)mutations[chromosome][i]->getSelectionCoef(); } float getSelectionCoefAtLoci(short chromosome, int i) const override; int countHeterozygoteLoci() const; - bool isHeterozygoteAtLoci(int loci) const override; + bool isHeterozygoteAtLocus(int locus) const override; virtual ~QTLTrait() { } }; diff --git a/SNPTrait.cpp b/SNPTrait.cpp index d19b35b..ebda79a 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -3,7 +3,7 @@ // ---------------------------------------------------------------------------------------- // for initialising population // ---------------------------------------------------------------------------------------- -SNPTrait::SNPTrait(ProtoTrait* P) +SNPTrait::SNPTrait(SpeciesTrait* P) { pProtoTrait = P; @@ -27,8 +27,8 @@ SNPTrait::SNPTrait(ProtoTrait* P) if (wildType == -999) wildType = (int)mutationParameters.find(MAX)->second - 1; - if (wildType > 255) - cout << endl << ("Error:: max number of alleles cannot exceed 256 \n"); + if (wildType > maxSNPAlleles - 1) + cout << endl << ("Error:: max number of alleles cannot exceed " << maxSNPAlleles << ".\n"); DistributionType initialDistribution = pProtoTrait->getInitialDistribution(); map initialParameters = pProtoTrait->getInitialParameters(); @@ -40,13 +40,13 @@ SNPTrait::SNPTrait(ProtoTrait* P) case UNIFORM: { if (!initialParameters.count(MAX)) - cout << endl << ("Error:: initial SNP/Microsat distribution parameter must contain max value if set to UNIFORM (e.g. max= ), max cannot exceed 256 \n"); + cout << endl << ("Error:: initial SNP/Microsat distribution parameter must contain max value if set to UNIFORM (e.g. max= ), max cannot exceed " << maxSNPAlleles << "\n"); float maxD = initialParameters.find(MAX)->second; - if (maxD > 256) { - cout << endl << ("Warning:: initial SNP/Microsat distribution parameter max cannot exceed 256, resetting to 256 \n"); + if (maxD > maxSNPAlleles) { + cout << endl << ("Warning:: initial SNP/Microsat distribution parameter max cannot exceed " << maxSNPAlleles << ", resetting to " << maxSNPAlleles << "\n"); - maxD = 256; //reserve 255 for wildtype + maxD = maxSNPAlleles; //reserve 255 for wildtype } initialiseFull(maxD); @@ -96,7 +96,7 @@ void SNPTrait::mutate_KAM() int maxD = (int)mutationParameters.find(MAX)->second; - if (maxD > 256) maxD = 256; //reserve max value -1 for wildtype + if (maxD > maxSNPAlleles) maxD = maxSNPAlleles; //reserve max value -1 for wildtype for (int p = 0; p < ploidy; p++) { @@ -110,14 +110,14 @@ void SNPTrait::mutate_KAM() for (int m : mutationPositions) { mut = (unsigned char)pRandom->IRandom(0, maxD - 1); //draw new mutation, could draw wildtype - auto it = mutations.find(m); //find if position in map already has mutations there + auto it = genes.find(m); //find if position in map already has mutations there - if (it == mutations.end()) { // not found so create new entry in map with wildtype as char default + if (it == genes.end()) { // not found so create new entry in map with wildtype as char default - vector vect(2, wildType); - vect[p] = mut; //put new mutation value in + vector allelePair(2, wildType); + allelePair[p] = mut; //put new mutation value in - mutations.insert(make_pair(m, vect)); + genes.insert(make_pair(m, allelePair)); } else { //position found, already mutations there @@ -127,17 +127,10 @@ void SNPTrait::mutate_KAM() } while (mut == currentChar); it->second[p] = mut; //overwrite with new value - } - - } } - - } - - } @@ -155,7 +148,7 @@ void SNPTrait::mutate_SSM() map mutationParameters = pProtoTrait->getMutationParameters(); int maxD = (int)mutationParameters.find(MAX)->second; - if (maxD > 256) maxD = 256; //reserved max value for wildtype + if (maxD > maxSNPAlleles) maxD = maxSNPAlleles; //reserved max value for wildtype for (int p = 0; p < ploidy; p++) { @@ -167,9 +160,8 @@ void SNPTrait::mutate_SSM() NbMut, rng); for (int m : mutationPositions) { - int mutateForward = pRandom->Bernoulli(0.5); - auto it = mutations.find(m); + auto it = genes.find(m); auto currentAllele = it->second[p];//current //alleles values are from 0 to maxD - 1 if (mutateForward && currentAllele < maxD - 1) @@ -178,13 +170,9 @@ void SNPTrait::mutate_SSM() it->second[p] -= 1; //one step to the left else //!direction && all == 0 it->second[p] += 1; - - } - } } - } // ---------------------------------------------------------------------------------------- @@ -193,21 +181,19 @@ void SNPTrait::mutate_SSM() void SNPTrait::inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) { - auto parentCast = dynamic_cast (parent); //horrible const auto& parent_seq = parentCast->get_mutations(); if (parent_seq.size() > 0) //else nothing to inherit (this->*_inherit_func_ptr) (chromosome, parent_seq, recomPositions, startingChromosome); - } -void SNPTrait::inheritDiploid(sex_t chromosome, map> const& parentMutations, set const& recomPositions, int parentChromosome) { +void SNPTrait::inheritDiploid(sex_t whichChromosome, map> const& parentGenes, set const& recomPositions, int parentChromosome) { - if (parentMutations.size() > 0) { - auto it = recomPositions.lower_bound(parentMutations.begin()->first); + if (parentGenes.size() > 0) { + auto it = recomPositions.lower_bound(parentGenes.begin()->first); unsigned int nextBreakpoint = *it; @@ -216,65 +202,54 @@ void SNPTrait::inheritDiploid(sex_t chromosome, map> parentChromosome = !parentChromosome; //switch chromosome - for (auto const& [key, val] : parentMutations) { + for (auto const& [locus, allelePair] : parentGenes) { - while (key > nextBreakpoint) { + while (locus > nextBreakpoint) { std::advance(it, 1); nextBreakpoint = *it; parentChromosome = !parentChromosome; //switch chromosome } - if (key <= nextBreakpoint) { - unsigned char sp = val[parentChromosome]; + if (locus <= nextBreakpoint) { + unsigned char sp = allelePair[parentChromosome]; - - auto it = mutations.find(key); - if (it == mutations.end()) { + auto it = genes.find(locus); + if (it == genes.end()) { // not found - vector vect(2, wildType); - vect[chromosome] = sp; - mutations.insert(make_pair(key, vect)); - + vector newAllelePair(2, wildType); + newAllelePair[whichChromosome] = sp; + genes.insert(make_pair(locus, newAllelePair)); } else { - it->second[chromosome] = sp; + it->second[whichChromosome] = sp; } - - } - - - } } } -void SNPTrait::inheritHaploid(sex_t chromosome, map> const& parentMutations, set const& recomPositions, int parentChromosome) +void SNPTrait::inheritHaploid(sex_t chromosome, map> const& parentGenes, set const& recomPositions, int parentChromosome) { - mutations = parentMutations; + genes = parentGenes; } // ---------------------------------------------------------------------------------------- // Initialise neutral loci // ---------------------------------------------------------------------------------------- -void SNPTrait::initialiseFull(int max) +void SNPTrait::initialiseFull(int maxAlleleVal) { - const auto& positions = pProtoTrait->getPositions(); short ploidy = pProtoTrait->getPloidy(); for (auto position : positions) { - vector vect; + vector allelePair; for (int i = 0; i < ploidy; i++) { - - auto mut = (unsigned char)pRandom->IRandom(0, max - 1); // allele values span 0 - max (255 ceiling) inclusive, max == wildtype - vect.emplace_back(mut); + auto alleleVal = (unsigned char)pRandom->IRandom(0, maxAlleleVal - 1); // allele values span 0 - max (255 ceiling) inclusive, max == wildtype + allelePair.emplace_back(alleleVal); } - mutations.insert(make_pair(position, vect)); - - + genes.insert(make_pair(position, allelePair)); } } @@ -284,11 +259,11 @@ void SNPTrait::initialiseFull(int max) // ---------------------------------------------------------------------------------------- -bool SNPTrait::isHeterozygoteAtLoci(int loci) const { +bool SNPTrait::isHeterozygoteAtLocus(int locus) const { - auto it = mutations.find(loci); + auto it = genes.find(locus); - if (it == mutations.end()) //not found + if (it == genes.end()) //not found return false; else return(it->second[0] != it->second[1]); @@ -302,10 +277,9 @@ int SNPTrait::countHeterozygoteLoci() const { int count = 0; - for (auto const& [key, val] : mutations) { - count += (val[0] != val[1]); + for (auto const& [locus, allelePair] : genes) { + count += (allelePair[0] != allelePair[1]); } - return count; } @@ -314,13 +288,12 @@ int SNPTrait::countHeterozygoteLoci() const { // ---------------------------------------------------------------------------------------- -float SNPTrait::getSelectionCoefAtLoci(short chromosome, int position) const { +float SNPTrait::getSelectionCoefAtLoci(short whichChromosome, int position) const { - auto it = mutations.find(position); + auto it = genes.find(position); - if (it == mutations.end()) //no mutations there + if (it == genes.end()) //no mutations there return wildType; //must still be wildtype at loci else - return it->second[chromosome]; - + return it->second[whichChromosome]; } \ No newline at end of file diff --git a/SNPTrait.h b/SNPTrait.h index 405442c..d4dd467 100644 --- a/SNPTrait.h +++ b/SNPTrait.h @@ -15,18 +15,17 @@ class SNPTrait : public TTrait { private: inline static int wildType = -999; + constexpr int maxSNPAlleles = UCHAR_MAX + 1; // allele is char, can take value 0-255 - ProtoTrait* pProtoTrait; + SpeciesTrait* pProtoTrait; //vector> mutations; - map> mutations; //position > - + map> genes; //position > void (SNPTrait::* _mutate_func_ptr) (void); void (SNPTrait::* _inherit_func_ptr) (sex_t chromosome, map> const& parent, set const& recomPositions, int parentChromosome); - void inheritDiploid(sex_t chromosome, map> const&, set const& recomPositions, int parentChromosome); void inheritHaploid(sex_t chromosome, map> const& parentMutations, set const& recomPositions, int parentChromosome); @@ -43,7 +42,7 @@ class SNPTrait : public TTrait { //this one for species held trait table, e.g. prototype table, sets static members - SNPTrait(ProtoTrait* P); + SNPTrait(SpeciesTrait* P); //this one for individuals, static members are not reset SNPTrait(const SNPTrait& T); @@ -64,13 +63,13 @@ class SNPTrait : public TTrait { bool isInherited() const override { return pProtoTrait->isInherited(); } - map>& get_mutations() { return mutations; } //returning reference, reciever must be const + map>& get_mutations() { return genes; } //returning reference, reciever must be const virtual float getSelectionCoefAtLoci(short chromosome, int position) const override; virtual int countHeterozygoteLoci() const; - virtual bool isHeterozygoteAtLoci(int loci) const override; + virtual bool isHeterozygoteAtLocus(int locus) const override; virtual float express() { return -9999; } diff --git a/Species.cpp b/Species.cpp index 3ee450b..81dd845 100644 --- a/Species.cpp +++ b/Species.cpp @@ -424,7 +424,7 @@ int Species::getNumberOfAdaptiveTraits() const return numberOfAdaptiveTraits; } -void Species::addTrait(TraitType traitType, const ProtoTrait& trait) { +void Species::addTrait(TraitType traitType, const SpeciesTrait& trait) { TraitType traitT = traitType; //hack to deal with multiple adaptive traits, could be handled better @@ -464,15 +464,15 @@ void Species::addTrait(TraitType traitType, const ProtoTrait& trait) { } } } - traitTable.emplace(traitT, make_unique(trait)); + spTraitTable.emplace(traitT, make_unique(trait)); } -ProtoTrait* Species::getTrait(TraitType trait) const { - return traitTable.find(trait)->second.get(); +SpeciesTrait* Species::getSpTrait(TraitType trait) const { + return spTraitTable.find(trait)->second.get(); } void Species::clearTraitTable() { - traitTable.clear(); + spTraitTable.clear(); } //map>& Species::getTraitTable(void) @@ -481,17 +481,17 @@ void Species::clearTraitTable() { //} set Species::getTraitTypes() { - auto kv = views::keys(traitTable); + auto kv = views::keys(spTraitTable); set keys{ kv.begin(), kv.end() }; return keys; } int Species::getNTraits() const { - return traitTable.size(); + return spTraitTable.size(); } int Species::getNPositionsForTrait(const TraitType trait) const { - return this->getTrait(trait)->getPositionsSize(); + return this->getSpTrait(trait)->getPositionsSize(); } int Species::getGenomeSize() const { diff --git a/Species.h b/Species.h index 5efbaf8..da7d57c 100644 --- a/Species.h +++ b/Species.h @@ -50,7 +50,7 @@ #include "../Version.h" //#endif #include "Parameters.h" -#include "ProtoTrait.h" +#include "SpeciesTrait.h" #include "TTrait.h" #include @@ -415,11 +415,11 @@ class Species { short // sex ); - void addTrait(TraitType traitType, const ProtoTrait& trait); + void addTrait(TraitType traitType, const SpeciesTrait& trait); void clearTraitTable(); - ProtoTrait* getTrait(TraitType trait) const; + SpeciesTrait* getSpTrait(TraitType trait) const; //map>& getTraitTable(void); //return by reference so ensure variable recieving is const @@ -488,7 +488,7 @@ class Species { // genome parameters /**The traits table.*/ - map> traitTable; + map> spTraitTable; set chromosomeEnds; int genomeSize; bool isDiploid; diff --git a/ProtoTrait.cpp b/SpeciesTrait.cpp similarity index 89% rename from ProtoTrait.cpp rename to SpeciesTrait.cpp index 202e88b..7d5264a 100644 --- a/ProtoTrait.cpp +++ b/SpeciesTrait.cpp @@ -1,9 +1,9 @@ -#include "ProtoTrait.h" +#include "SpeciesTrait.h" #include "Species.h" //could be handled in header file but here for now for flexibility -ProtoTrait::ProtoTrait(vector parameters, Species* pSpecies) { +SpeciesTrait::SpeciesTrait(vector parameters, Species* pSpecies) { bool neutralPresent = false; if (ploidy == 0) this->ploidy = pSpecies->isDiploid() ? 2 : 1; @@ -39,7 +39,7 @@ ProtoTrait::ProtoTrait(vector parameters, Species* pSpecies) { } } -TraitType ProtoTrait::stringToTraitType(const std::string& str, sex_t sex) const { +TraitType SpeciesTrait::stringToTraitType(const std::string& str, sex_t sex) const { if (sex == MAL) { if (str == "emigration_d0") return E_D0_M; @@ -74,14 +74,14 @@ TraitType ProtoTrait::stringToTraitType(const std::string& str, sex_t sex) const } } -ExpressionType ProtoTrait::stringToExpressionType(const std::string& str) const { +ExpressionType SpeciesTrait::stringToExpressionType(const std::string& str) const { if (str == "average") return AVERAGE; else if (str == "additive") return ADDITIVE; else if (str == "multiplicative") return MULTIPLICATIVE; else if (str == "#") return NEUTRAL; } -DistributionType ProtoTrait::stringToDistributionType(const std::string& str) const +DistributionType SpeciesTrait::stringToDistributionType(const std::string& str) const { if (str == "#") return NONE; else if (str == "uniform") return UNIFORM; @@ -93,7 +93,7 @@ DistributionType ProtoTrait::stringToDistributionType(const std::string& str) co else if (str == "SSM") return SSM; } -map ProtoTrait::stringToParameterMap(string parameters) const { +map SpeciesTrait::stringToParameterMap(string parameters) const { map paramMap; if (parameters != "#") { @@ -120,17 +120,17 @@ map ProtoTrait::stringToParameterMap(string parameters) cons return paramMap; } -set ProtoTrait::selectRandomLociPositions(int noLoci, Species* pSpecies) const { +set SpeciesTrait::selectRandomLociPositions(int nbLoci, Species* pSpecies) const { int genomeSize = pSpecies->getGenomeSize(); set positions; - for (int i = 0; i < noLoci; ++i) + for (int i = 0; i < nbLoci; ++i) positions.insert(pRandom->IRandom(0, genomeSize)); return positions; } -set ProtoTrait::stringToLoci(string pos, string nLoci, Species* pSpecies) const { +set SpeciesTrait::stringToLoci(string pos, string nLoci, Species* pSpecies) const { set positions; @@ -167,6 +167,5 @@ set ProtoTrait::stringToLoci(string pos, string nLoci, Species* pSpecies) c else { positions = selectRandomLociPositions(stoi(nLoci), pSpecies); } - return positions; } diff --git a/ProtoTrait.h b/SpeciesTrait.h similarity index 93% rename from ProtoTrait.h rename to SpeciesTrait.h index a84949e..3894207 100644 --- a/ProtoTrait.h +++ b/SpeciesTrait.h @@ -1,5 +1,5 @@ -#ifndef PROTOTRAITH -#define PROTOTRAITH +#ifndef SPECIESTRAITH +#define SPECIESTRAITH #include "Parameters.h" #include @@ -9,7 +9,7 @@ class Species; -class ProtoTrait { +class SpeciesTrait { private: inline static int ploidy = 0; @@ -27,7 +27,7 @@ class ProtoTrait { public: - ProtoTrait(vector parameters, Species* pSpecies); + SpeciesTrait(vector parameters, Species* pSpecies); // Getters sex_t getSex() const { return sex; } diff --git a/TTrait.h b/TTrait.h index 9e5d8ae..9e7228b 100644 --- a/TTrait.h +++ b/TTrait.h @@ -4,9 +4,9 @@ #include #include -#include "parameters.h" -#include "Mutation.h" -#include "ProtoTrait.h" +#include "Parameters.h" +#include "Allele.h" +#include "SpeciesTrait.h" using namespace std; @@ -34,7 +34,7 @@ class TTrait { //virtual vector> get_mutations() const = 0; virtual float getSelectionCoefAtLoci(short chromosome, int i) const = 0; virtual int countHeterozygoteLoci() const = 0; - virtual bool isHeterozygoteAtLoci(int loci) const = 0; + virtual bool isHeterozygoteAtLocus(int loci) const = 0; virtual float express() = 0; virtual ~TTrait() { } }; diff --git a/TraitFactory.h b/TraitFactory.h index da806f3..9cf1dda 100644 --- a/TraitFactory.h +++ b/TraitFactory.h @@ -1,7 +1,7 @@ #ifndef TRAITFACTORYH #define TRAITFACTORYH -#include "ProtoTrait.h" +#include "SpeciesTrait.h" #include "SNPTrait.h" #include "QTLTrait.h" #include "AdaptiveTrait.h" @@ -11,7 +11,7 @@ class TraitFactory public: TraitFactory() {}; - unique_ptr Create(const TraitType traitType, ProtoTrait* protoTrait) + unique_ptr Create(const TraitType traitType, SpeciesTrait* protoTrait) { if (traitType == SNP) { return make_unique(protoTrait); From 825a643cdeb0ace9ff4f05a9ec2798f7d06920c6 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 2 Feb 2024 12:05:33 +0000 Subject: [PATCH 025/332] does git subtree not track CMakeLists? --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 31e59e4..7acb8d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,4 +8,4 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") target_compile_definitions(RScore PRIVATE "RSDEBUG" "RSWIN64" "LINUX_CLUSTER") else() # Windows target_compile_definitions(RScore PRIVATE "RSDEBUG" "RSWIN64") -endif() \ No newline at end of file +endif() From 606f3714753e67f83c073c8a758df4506e60b935 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 2 Feb 2024 14:38:28 +0000 Subject: [PATCH 026/332] add new genetics file to CMake target + drop unused Distribution classes --- CMakeLists.txt | 2 +- Distributions.h | 70 ------------------------------------------------- 2 files changed, 1 insertion(+), 71 deletions(-) delete mode 100644 Distributions.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7acb8d8..a100830 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # Config file for compilation with CMake # Only relevant for Batch mode, but this file needs to live in the RScore folder -add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp) +add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticLoad.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SubCommunity.cpp) # pass config definitions to compiler if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") diff --git a/Distributions.h b/Distributions.h deleted file mode 100644 index ef4e1cb..0000000 --- a/Distributions.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef DISTRIBUTIONSH -#define DISTRIBUTIONSH - - -#include -#include -//#include -using namespace std; - -#include -#include -#if !LINUX_CLUSTER -#include -#endif - -#include "RSRandom.h" - -struct distributionType { - - virtual ~distributionType() {} - -}; - -struct NormalDistribution : distributionType { - - // Set up standard normal distribution - std::normal_distribution<>* pNormal; - - NormalDistribution(float mean, float sd) { - pNormal = new normal_distribution(mean, sd); - } - - float sample(void) { - - - mt19937 gen = pRandom->getRNG(); - return pNormal->operator()(gen); - } - - ~NormalDistribution() { - if (pNormal != 0) delete pNormal; - } -}; - -struct NormalDistribution : distributionType { - - // Set up standard normal distribution - std::normal_distribution<>* pNormal; - - NormalDistribution(float mean, float sd) { - pNormal = new normal_distribution(mean, sd); - } - - float sample(void) { - - - mt19937 gen = pRandom->getRNG(); - return pNormal->operator()(gen); - } - - ~NormalDistribution() { - if (pNormal != 0) delete pNormal; - } -}; - - - -extern RSrandom* pRandom; - -#endif \ No newline at end of file From bfc278c0e8d1eb0455b25bfb337b6e7d01bef9bc Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 5 Feb 2024 19:58:58 +0100 Subject: [PATCH 027/332] fix CRW tests, progress on testing CRW rho --- Individual.cpp | 75 ++++++++++++++++++++++++++++++++------------------ Individual.h | 1 + 2 files changed, 49 insertions(+), 27 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 9bb22c6..8c282dd 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1250,7 +1250,6 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, } // end of single movement step return dispersing; - } //--------------------------------------------------------------------------- @@ -1827,15 +1826,16 @@ void Individual::setCRW(crwParams* pCRW) { crw = pCRW; } -// Force initialisation of path as it sometimes doesn't set?? +// TP: Both functions below are a bad fix to an issue I have for testing +// Smh upon exiting individual initialisation path and CRW get deallocated +// Force initialisation of path void Individual::forceInitPath() { pathData* pPath = new pathData; pPath->out = pPath->year = pPath->total = 0; pPath->pSettPatch = 0; pPath->settleStatus = 0; setPath(pPath); } - -// Force initialisation of crw as it sometimes doesn't set?? +// Force initialisation of crw void Individual::forceInitCRW(const trfrMovtTraits& m) { crwParams* pCRW = new crwParams; pCRW->prevdrn = (float)(pRandom->Random() * 2.0 * PI); @@ -1845,6 +1845,10 @@ void Individual::forceInitCRW(const trfrMovtTraits& m) { setCRW(pCRW); } +void Individual::setInitAngle(const float angle) { + crw->prevdrn = angle; +} + void testIndividual() { @@ -2117,7 +2121,6 @@ void testIndividual() { } } Cell* init_cell = cell_vec[12]; // central - //Cell* final_cell = new Cell(ls_params.dimX - 1, ls_params.dimY - 1, 0, 0); ls.setCellArray(); for (auto c : cell_vec) ls.addCellToLand(c); @@ -2130,7 +2133,6 @@ void testIndividual() { // Habitat-dependent mortality sp.createHabCostMort(1); - // sp.setHabMort(hab_index, 0.0); // Transfer rules trfrRules trfr; @@ -2165,15 +2167,11 @@ void testIndividual() { // Create and set up individual Individual ind(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); - // ind.setYearSteps(); // if needed - // ind.getSteps(); - // Set status assert(ind.getStatus() == 0); // default status, not emigrating int isDispersing = ind.moveStep(&ls, &sp, hab_index, false); assert(ind.getStatus() == 0); // status didn't change assert(ind.getCurrCell() == init_cell); // not emigrating so didn't move - //ind.~Individual(); // Per-step mortality m.stepMort = 1.0; // should die @@ -2205,9 +2203,16 @@ void testIndividual() { // Step size ls = Landscape(); ls.setLandParams(ls_params, true); - // Only two suitable cells in opposite corners - init_cell = new Cell(0, 0, 0, 0); - Cell* final_cell = new Cell(ls_params.dimX - 1, ls_params.dimY - 1, 0, 0); + + sp.createHabK(2); + const int hab_suitable = 0; + const int hab_unsuitable = 1; + sp.setHabK(hab_suitable, 100.0); + sp.setHabK(hab_unsuitable, 0.0); + + // Initial cell unsuitable, suitable cell in opposite corner + init_cell = new Cell(0, 0, 0, hab_unsuitable); + Cell* final_cell = new Cell(ls_params.dimX - 1, ls_params.dimY - 1, 0, hab_suitable); ls.setCellArray(); ls.addCellToLand(init_cell); ls.addCellToLand(final_cell); @@ -2215,8 +2220,10 @@ void testIndividual() { ls.updateCarryingCapacity(&sp, 0, 0); // Init cell is NOT in natal patch Patch* natalPatch = new Patch(0, 0); + init_patch = (Patch*)init_cell->getPatch(); + // Step length too short - m.stepLength = 0.1; // cannot reach final cell + m.stepLength = 0.1; // will not reach final cell m.rho = 0.0; // random angle sp.setMovtTraits(m); steps.minSteps = 1; @@ -2227,7 +2234,7 @@ void testIndividual() { ind.setStatus(1); // dispersing ind.forceInitPath(); ind.forceInitCRW(m); - // First step - individual can't reach final cell so still dispersing + // First step - still in unsuitable cell so still dispersing isDispersing = ind.moveStep(&ls, &sp, hab_index, false); assert(ind.getCurrCell() == init_cell); assert(ind.getStatus() == 1); @@ -2236,7 +2243,7 @@ void testIndividual() { assert(ind.getCurrCell() == init_cell); assert(ind.getStatus() == 3); ind.setStatus(1); // dispersing again - // Third step - reaching max steps, dies + // Third step - reaching max steps, dies in unsuitable cell isDispersing = ind.moveStep(&ls, &sp, hab_index, false); assert(ind.getCurrCell() == init_cell); assert(ind.getStatus() == 6); @@ -2244,7 +2251,7 @@ void testIndividual() { // Step length too long m.stepLength = ls_params.dimX * SQRT2 * 1.5; // overshoots sp.setMovtTraits(m); - ind = Individual(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); + ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); ind.setStatus(1); // dispersing ind.forceInitPath(); ind.forceInitCRW(m); @@ -2263,12 +2270,12 @@ void testIndividual() { ind.setStatus(1); // dispersing ind.forceInitPath(); ind.forceInitCRW(m); - // Initial angle still random but should eventually reach the right cell + // Initial angle still random but should eventually reach the suitable cell isDispersing = ind.moveStep(&ls, &sp, hab_index, false); assert(ind.getStatus() == 2); assert(ind.getCurrCell() == final_cell); - // If boundaries are absorbing however, very likely to die + // If boundaries are absorbing however, most likely to die ind = Individual(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); ind.setStatus(1); // dispersing ind.forceInitPath(); @@ -2279,15 +2286,27 @@ void testIndividual() { assert(ind.getCurrCell() == 0); // deref apparently // Correlation parameter - // If rho = 1, should move in a straight line (after moving out of initial patch) - + // If rho = 1 move in a straight line + + // All cells are suitable + /* + vector cell_vec; + for (int x = ls_params.minX; x < ls_params.dimX; ++x) { + for (int y = ls_params.minY; y < ls_params.dimY; ++y) { + cell_vec.push_back(new Cell(x, y, 0, hab_suitable)); + } + } + Cell* init_cell = cell_vec[12]; // central + ls.setCellArray(); + for (auto c : cell_vec) ls.addCellToLand(c); + */ // Add a central cell to get a diagonal of suitable cells - Cell* pMiddleCell = new Cell(2, 2, 0, hab_index); + Cell* pMiddleCell = new Cell(2, 2, 0, hab_suitable); ls.addCellToLand(pMiddleCell); ls.allocatePatches(&sp); ls.updateCarryingCapacity(&sp, 0, 0); - m.stepLength = 2 * SQRT2; // move by 1 cell diagonally - m.rho = 1; + m.stepLength = 2 * SQRT2; // long enough to move by 1 cell diagonally + m.rho = 1; // init angle must be 0.7854 sp.setMovtTraits(m); steps.maxStepsYr = steps.maxSteps = 2; sp.setSteps(0, 0, steps); @@ -2295,6 +2314,8 @@ void testIndividual() { ind.setStatus(1); // dispersing ind.forceInitPath(); ind.forceInitCRW(m); + const float diag_angle = 0.7854; // about 45 degrees + ind.setInitAngle(diag_angle); isDispersing = ind.moveStep(&ls, &sp, hab_index, false); assert(ind.getStatus() == 2); assert(ind.getCurrCell() == pMiddleCell); @@ -2302,10 +2323,10 @@ void testIndividual() { isDispersing = ind.moveStep(&ls, &sp, hab_index, false); assert(ind.getStatus() == 2); assert(ind.getCurrCell() == final_cell); - // not a good test yet, must add other suitable cells - // and start outside of natal patch - + // can set angle change through movt? + // can it go back to first cell? + // not a good test yet, must add other suitable cells } } #endif // RSDEBUG diff --git a/Individual.h b/Individual.h index 0a676c3..f8cc7a4 100644 --- a/Individual.h +++ b/Individual.h @@ -258,6 +258,7 @@ class Individual { void setCRW(crwParams* pCRW); void forceInitPath(); void forceInitCRW(const trfrMovtTraits&); + void setInitAngle(const float angle); #endif private: From 8436606da0e830efb844357fcc35b781ba75c1db Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 6 Feb 2024 16:31:54 +0100 Subject: [PATCH 028/332] complete rho=1 test --- Individual.cpp | 49 ++++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 8c282dd..f11b523 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -2286,47 +2286,42 @@ void testIndividual() { assert(ind.getCurrCell() == 0); // deref apparently // Correlation parameter - // If rho = 1 move in a straight line - - // All cells are suitable - /* - vector cell_vec; + // If rho = 1 should move in a straight line + // Many cells, all suitable + ls_params.dimX = ls_params.dimY = 10; + ls_params.minX = ls_params.minY = 0; + ls_params.maxX = ls_params.maxY = ls_params.dimX - 1; + ls_params.resol = 1; + ls = Landscape(); + ls.setLandParams(ls_params, true); + cell_vec.clear(); for (int x = ls_params.minX; x < ls_params.dimX; ++x) { for (int y = ls_params.minY; y < ls_params.dimY; ++y) { cell_vec.push_back(new Cell(x, y, 0, hab_suitable)); } } - Cell* init_cell = cell_vec[12]; // central ls.setCellArray(); for (auto c : cell_vec) ls.addCellToLand(c); - */ - // Add a central cell to get a diagonal of suitable cells - Cell* pMiddleCell = new Cell(2, 2, 0, hab_suitable); - ls.addCellToLand(pMiddleCell); ls.allocatePatches(&sp); ls.updateCarryingCapacity(&sp, 0, 0); - m.stepLength = 2 * SQRT2; // long enough to move by 1 cell diagonally - m.rho = 1; // init angle must be 0.7854 + // Individual moves by 1 along the diagonal + m.stepLength = ls_params.resol * SQRT2; // 1 diagonal cell + m.rho = 1; // angle = previous angle sp.setMovtTraits(m); - steps.maxStepsYr = steps.maxSteps = 2; + steps.maxStepsYr = steps.maxSteps = ls_params.dimX; sp.setSteps(0, 0, steps); - ind = Individual(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); - ind.setStatus(1); // dispersing + ind = Individual(cell_vec[0], natalPatch, 0, 0, 0, 0.0, true, 2); ind.forceInitPath(); ind.forceInitCRW(m); - const float diag_angle = 0.7854; // about 45 degrees + const float diag_angle = PI / 4.0; // 45 degrees ind.setInitAngle(diag_angle); - isDispersing = ind.moveStep(&ls, &sp, hab_index, false); - assert(ind.getStatus() == 2); - assert(ind.getCurrCell() == pMiddleCell); - ind.setStatus(1); // emigrate again - isDispersing = ind.moveStep(&ls, &sp, hab_index, false); - assert(ind.getStatus() == 2); - assert(ind.getCurrCell() == final_cell); - // can set angle change through movt? - // can it go back to first cell? - - // not a good test yet, must add other suitable cells + // Individual moves only along diagonal cells + for (int i = 1; i < ls_params.dimX; ++i) { + ind.setStatus(1); // dispersing + isDispersing = ind.moveStep(&ls, &sp, hab_index, false); + assert(ind.getStatus() == 2); + assert(ind.getCurrCell() == cell_vec[i * (ls_params.dimX + 1)]); + } } } #endif // RSDEBUG From 239a795b91b34c6002a3af60e49b3eab212dfa6e Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 9 Feb 2024 12:33:09 +0100 Subject: [PATCH 029/332] update CMake --- CMakeLists.txt | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a100830..d8fe69f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,30 @@ # Config file for compilation with CMake -# Only relevant for Batch mode, but this file needs to live in the RScore folder -add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticLoad.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SubCommunity.cpp) +if (NOT batchmode) # that is, RScore as a standalone + cmake_minimum_required(VERSION 3.10) + # set the project name and version + project(RScore VERSION 2.1.0) + # specify the C++ standard + set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD_REQUIRED True) + add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticLoad.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) +else() # that is, RScore compiled as library within RangeShifter_batch + add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticLoad.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) +endif() # pass config definitions to compiler +target_compile_definitions(RScore PRIVATE RSWIN64) + +# enable LINUX_CLUSTER macro on Linux + macOS if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") - target_compile_definitions(RScore PRIVATE "RSDEBUG" "RSWIN64" "LINUX_CLUSTER") -else() # Windows - target_compile_definitions(RScore PRIVATE "RSDEBUG" "RSWIN64") + add_compile_definitions("LINUX_CLUSTER") endif() + +# Debug Mode by default, unless "release" is passed +if(NOT DEFINED release) + add_compile_definitions(RSDEBUG) +endif() + +if(NOT batchmode) + target_include_directories(RScore PUBLIC "${PROJECT_BINARY_DIR}") +endif() \ No newline at end of file From 3a02aab50c6dd2e9df4475de228e4e87d5667183 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 9 Feb 2024 12:33:30 +0100 Subject: [PATCH 030/332] rm DEBUGLOG blobs --- Cell.cpp | 12 - Community.cpp | 87 -------- FractalGenerator.cpp | 10 - Individual.cpp | 516 ++----------------------------------------- Landscape.cpp | 364 +----------------------------- 5 files changed, 16 insertions(+), 973 deletions(-) diff --git a/Cell.cpp b/Cell.cpp index 2f8c1b3..fac40c8 100644 --- a/Cell.cpp +++ b/Cell.cpp @@ -59,18 +59,12 @@ Cell::Cell(int xx, int yy, intptr patch, float hab) } Cell::~Cell() { -#if RSDEBUG - //DEBUGLOG << "Cell::~Cell(): this = " << this << " smsData = " << smsData << endl; -#endif habIxx.clear(); habitats.clear(); if (smsData != 0) { if (smsData->effcosts != 0) delete smsData->effcosts; delete smsData; } -#if RSDEBUG - //DEBUGLOG << "Cell::~Cell(): deleted" << endl; -#endif } void Cell::setHabIndex(short hx) { @@ -118,12 +112,6 @@ void Cell::setPatch(intptr p) { } intptr Cell::getPatch(void) { -#if RSDEBUG - //DebugGUI(("Cell::getPatch(): this=" + Int2Str((int)this) - // + " x=" + Int2Str(x) + " y=" + Int2Str(y) - // + " habIxx[0]=" + Int2Str(habIxx[0]) + " pPatch=" + Int2Str(pPatch) - //).c_str()); -#endif return pPatch; } diff --git a/Community.cpp b/Community.cpp index c05e023..7ffc8ed 100644 --- a/Community.cpp +++ b/Community.cpp @@ -262,13 +262,6 @@ void Community::initialise(Species* pSpecies, int year) while (indIx < ninds && iind.year <= year) { iind = paramsInit->getInitInd(indIx); while (iind.year == year) { -#if RSDEBUG - //DEBUGLOG << "Community::initialise(): year=" << year - // << " indIx=" << indIx << " iind.year=" << iind.year - // << " iind.patchID=" << iind.patchID << " iind.x=" << iind.x << " iind.y=" << iind.y - // << " iind.sex=" << iind.sex << " iind.age=" << iind.age << " iind.stage=" << iind.stage - // << endl; -#endif if (ppLand.patchModel) { if (pLandscape->existsPatch(iind.patchID)) { pPatch = pLandscape->findPatch(iind.patchID); @@ -537,21 +530,12 @@ void Community::dispersal(short landIx) for (int i = 0; i < nsubcomms; i++) { // all populations subComms[i]->resetPossSettlers(); } -#if RSDEBUG - //DEBUGLOG << "Community::dispersal() 1111: ndispersers=" << ndispersers << endl; -#endif #if RS_RCPP // included also SEASONAL ndispersers = matrix->transfer(pLandscape, landIx, nextseason); #else ndispersers = matrix->transfer(pLandscape, landIx); #endif // SEASONAL || RS_RCPP -#if RSDEBUG - //DEBUGLOG << "Community::dispersal() 2222: ndispersers=" << ndispersers << endl; -#endif matrix->completeDispersal(pLandscape, sim.outConnect); -#if RSDEBUG - //DEBUGLOG << "Community::dispersal() 3333: ndispersers=" << ndispersers << endl; -#endif } while (ndispersers > 0); #if RSDEBUG @@ -560,11 +544,6 @@ void Community::dispersal(short landIx) DEBUGLOG << "Community::dispersal(): transfer time=" << t2 - t1 << endl; #endif -#if RSDEBUG - //int t3 = time(0); - //DEBUGLOG << "Community::dispersal(): completion time = " << t3-t2 << endl; -#endif - } void Community::survival(short part, short option0, short option1) @@ -663,25 +642,9 @@ commStats Community::getStats(void) patchPop = subComms[i]->getPopStats(); s.ninds += patchPop.nInds; s.nnonjuvs += patchPop.nNonJuvs; -#if RSDEBUG - //DEBUGLOG << "Community::getStats(): i = " << i - // << " pSpecies = " << patchPop.pSpecies << " pPatch = " << patchPop.pPatch - // << " nInds = " << patchPop.nInds << endl; -#endif if (patchPop.pPatch != 0) { // not the matrix patch -#if RSDEBUG - //DEBUGLOG << "Community::getStats(): i = " << i - // << " patchNum = " << patchPop.pPatch->getPatchNum() << endl; -#endif if (patchPop.pPatch->getPatchNum() != 0) { // not matrix patch localK = patchPop.pPatch->getK(); -#if RSDEBUG - //DEBUGLOG << "Community::getStats(): i= " << i - // << " pSpecies= " << patchPop.pSpecies << " pPatch= " << patchPop.pPatch - // << " patchNum= " << patchPop.pPatch->getPatchNum() << " localK= " << localK - // << " nInds= " << patchPop.nInds << " breeding= " << (int)patchPop.breeding - // << endl; -#endif if (localK > 0.0) s.suitable++; if (patchPop.nInds > 0 && patchPop.breeding) { s.occupied++; @@ -962,17 +925,6 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) ts.sumS0[j] += scts.sumS0[j]; ts.ssqS0[j] += scts.ssqS0[j]; ts.sumAlphaS[j] += scts.sumAlphaS[j]; ts.ssqAlphaS[j] += scts.ssqAlphaS[j]; ts.sumBetaS[j] += scts.sumBetaS[j]; ts.ssqBetaS[j] += scts.ssqBetaS[j]; -#if RSDEBUG - //DEBUGLOG << "Community::outRange(): i=" << i << " j=" << j - // << " scts.ninds[j]=" << scts.ninds[j] - // << " scts.sumD0[j]=" << scts.sumD0[j] - // << " scts.ssqD0[j]=" << scts.ssqD0[j] - // << endl; - //DEBUGLOG << "Community::outRange(): i=" << i << " j=" << j - // << " ts.ninds[j]=" << ts.ninds[j] - // << " ts.sumD0[j]=" << ts.sumD0[j] << " ts.ssqD0[j]=" << ts.ssqD0[j] - // << endl; -#endif } } @@ -1011,16 +963,6 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; } } -#if RSDEBUG - //DEBUGLOG << "Community::outRange(): ngenes=" << ngenes << " g=" << g - // << " ts.ninds[g]=" << ts.ninds[g] - // << " ts.sumD0[g]=" << ts.sumD0[g] - // << " ts.ssqD0[g]=" << ts.ssqD0[g] - // << endl; - //DEBUGLOG << "Community::outRange(): popsize=" << popsize - // << " mnD0[g]" << mnD0[g] << " sdD0[g]" << sdD0[g] - // << endl; -#endif } if (emig.sexDep) { outrange << "\t" << mnD0[0] << "\t" << sdD0[0]; @@ -1098,17 +1040,6 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) if (sdBetaDB[g] > 0.0) sdBetaDB[g] = sqrt(sdBetaDB[g]); else sdBetaDB[g] = 0.0; } } -#if RSDEBUG - //DEBUGLOG << "Community::outRange(): ngenes=" << ngenes << " g=" << g - // << " ts.ninds[g]=" << ts.ninds[g] - // << " ts.sumDP[g]=" << ts.sumDP[g] << " ts.ssqDP[g]=" << ts.ssqDP[g] - // << " ts.sumGB[g]=" << ts.sumGB[g] << " ts.ssqGB[g]=" << ts.ssqGB[g] - // << endl; - //DEBUGLOG << "Community::outRange(): popsize=" << popsize - // << " mnDP[g]" << mnDP[g] << " sdDP[g]" << sdDP[g] - // << " mnGB[g]" << mnGB[g] << " sdGB[g]" << sdGB[g] - // << endl; -#endif } if (trfr.moveModel) { if (trfr.moveType == 1) { @@ -1282,35 +1213,17 @@ void Community::outOccSuit(bool view) { simParams sim = paramsSim->getSim(); //streamsize prec = outsuit.precision(); -#if RSDEBUG -//DEBUGLOG << "Community::outOccSuit(): sim.reps=" << sim.reps -// << " sim.years=" << sim.years << " sim.outInt=" << sim.outInt << endl; -#endif for (int i = 0; i < (sim.years / sim.outIntOcc) + 1; i++) { sum = ss = 0.0; for (int rep = 0; rep < sim.reps; rep++) { sum += occSuit[i][rep]; ss += occSuit[i][rep] * occSuit[i][rep]; -#if RSDEBUG - //DEBUGLOG << "Community::outOccSuit(): i=" << i << " rep=" << rep - // << " occSuit[i][rep]=" << occSuit[i][rep] - // << " sum=" << sum << " ss=" << ss - // << endl; -#endif } mean = sum / (double)sim.reps; sd = (ss - (sum * sum / (double)sim.reps)) / (double)(sim.reps - 1); -#if RSDEBUG - //DEBUGLOG << "Community::outOccSuit(): i=" << i - // << " mean=" << mean << " sd=" << sd << endl; -#endif if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; se = sd / sqrt((double)(sim.reps)); -#if RSDEBUG - //DEBUGLOG << "Community::outOccSuit(): i=" << i - // << " sd=" << sd << " se=" << se << endl; -#endif // outsuit << i*sim.outInt << "\t" << mean << "\t" << se << endl; // if (view) viewOccSuit(i*sim.outInt,mean,se); diff --git a/FractalGenerator.cpp b/FractalGenerator.cpp index 9dda608..c0a0392 100644 --- a/FractalGenerator.cpp +++ b/FractalGenerator.cpp @@ -211,17 +211,7 @@ vector& fractal_landscape(int X, int Y, double Hurst, double prop, } if (arena != NULL) { -#if RSDEBUG - //DebugGUI(("fractal_landscape(): arena=" + Int2Str((int)arena) - // + " X=" + Int2Str(X) + " Y=" + Int2Str(Y) - // ).c_str()); -#endif for (ii = 0; ii < X; ii++) { -#if RSDEBUG - //DebugGUI(("fractal_landscape(): ii=" + Int2Str(ii) - // + " arena[ii]=" + Int2Str((int)arena[ii]) - // ).c_str()); -#endif delete[] arena[ii]; } delete[] arena; diff --git a/Individual.cpp b/Individual.cpp index 25dc99f..d4d6d53 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -35,11 +35,6 @@ Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short rep float probmale, bool movt, short moveType) { indId = indCounter; indCounter++; // unique identifier for each individual -#if RSDEBUG - //DEBUGLOG << "Individual::Individual(): indId=" << indId - // << " stg=" << stg << " a=" << a << " probmale=" << probmale - // << endl; -#endif fitness = 1.0; stage = stg; if (probmale <= 0.0) sex = FEM; @@ -80,13 +75,6 @@ Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short rep } //pEmigTraits = make_unique(nullptr); //pSettleTraits = make_unique(nullptr); -#if RSDEBUG -//locn currloc = pCurrCell->getLocn(); -//DEBUGLOG << "Individual::Individual(): indId=" << indId -// << " x=" << currloc.x << " y=" << currloc.y -//// << " smsData=" << smsData << " dp=" << smsData->dp -// << endl; -#endif } Individual::~Individual(void) { @@ -281,35 +269,12 @@ void Individual::setSettlementTraits(Species* pSpecies, bool sexDep) { s.beta = getTrait(S_BETA_F)->express(); } -#if RSDEBUG - //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId - // << " s.s0=" << s.s0 << " s.alpha=" << s.alpha << " s.beta=" << s.beta - // << endl; -#endif -#if RSDEBUG - //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId - // << " sparams.s0Mean=" << sparams.s0Mean << " sparams.s0SD=" << sparams.s0SD - // << " sparams.s0Scale=" << sparams.s0Scale - // << endl; -#endif pSettleTraits = make_unique(); pSettleTraits->s0 = (float)(s.s0); pSettleTraits->alpha = (float)(s.alpha); pSettleTraits->beta = (float)(s.beta); -#if RSDEBUG - //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId - // << " setttraits->s0=" << setttraits->s0 - // << " setttraits->alpha=" << setttraits->alpha << " setttraits->beta=" << setttraits->beta - // << endl; -#endif if (pSettleTraits->s0 < 0.0) pSettleTraits->s0 = 0.0; if (pSettleTraits->s0 > 1.0) pSettleTraits->s0 = 1.0; -#if RSDEBUG - //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId - // << " setttraits->s0=" << setttraits->s0 - // << " setttraits->alpha=" << setttraits->alpha << " setttraits->beta=" << setttraits->beta - // << endl; -#endif return; } @@ -371,11 +336,6 @@ void Individual::setYearSteps(int t) { if (t >= 0) path->year = t; else path->year = 666; } -#if RSDEBUG - //DEBUGLOG << "Individual::setYearSteps(): indId=" << indId - // << " t=" << t << " path->year=" << path->year - // << endl; -#endif } pathSteps Individual::getSteps(void) { @@ -429,51 +389,23 @@ void Individual::setEmigTraits(Species* pSpecies, bool sexDep, bool densityDep) } } -#if RSDEBUG - //DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId - // << " eparams.betaMean=" << eparams.betaMean << " eparams.betaSD=" << eparams.betaSD - // << " eparams.betaScale=" << eparams.betaScale - // << endl; -#endif pEmigTraits = make_unique(); pEmigTraits->d0 = (float)(e.d0); pEmigTraits->alpha = (float)(e.alpha); pEmigTraits->beta = (float)(e.beta); -#if RSDEBUG - //DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId - // << " emigtraits->d0=" << emigtraits->d0 - // << " emigtraits->alpha=" << emigtraits->alpha << " emigtraits->beta=" << emigtraits->beta - // << endl; -#endif if (pEmigTraits->d0 < 0.0) pEmigTraits->d0 = 0.0; if (pEmigTraits->d0 > 1.0) pEmigTraits->d0 = 1.0; -#if RSDEBUG - //DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId - // << " emigtraits->d0=" << emigtraits->d0 - // << " emigtraits->alpha=" << emigtraits->alpha << " emigtraits->beta=" << emigtraits->beta - // << endl; -#endif return; } // Get phenotypic emigration traits emigTraits Individual::getEmigTraits(void) { -#if RSDEBUG - //DEBUGLOG << "Individual::getEmigTraits(): indId=" << indId - // << endl; -#endif emigTraits e; e.d0 = e.alpha = e.beta = 0.0; if (pEmigTraits != 0) { e.d0 = pEmigTraits->d0; e.alpha = pEmigTraits->alpha; e.beta = pEmigTraits->beta; } -#if RSDEBUG - //DEBUGLOG << "Individual::getEmigTraits(): indId=" << indId - // << " e.d0=" << e.d0 << " e.alpha=" << e.alpha << " e.beta=" << e.beta - // << endl; -#endif - return e; } // Set phenotypic transfer by kernel traits @@ -502,13 +434,6 @@ void Individual::setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel float meanDist2 = (float)(k.meanDist2); float probKern1 = (float)(k.probKern1); -#if RSDEBUG - //DEBUGLOG << "Individual::setKernTraits(): indId=" << indId - // << " kerntraits->meanDist1=" << kerntraits->meanDist1 - // << " kerntraits->meanDist2=" << kerntraits->meanDist2 - // << " kerntraits->probKern1=" << kerntraits->probKern1 - // << endl; -#endif if (!pSpecies->useFullKernel()) { // kernel mean(s) may not be less than landscape resolution if (meanDist1 < resol) meanDist1 = (float)resol; @@ -516,13 +441,6 @@ void Individual::setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel } if (probKern1 < 0.0) probKern1 = 0.0; if (probKern1 > 1.0) probKern1 = 1.0; -#if RSDEBUG - //DEBUGLOG << "Individual::setKernTraits(): indId=" << indId - // << " kerntraits->meanDist1=" << kerntraits->meanDist1 - // << " kerntraits->meanDist2=" << kerntraits->meanDist2 - // << " kerntraits->probKern1=" << kerntraits->probKern1 - // << endl; -#endif auto& pKernel = dynamic_cast(*pTrfrData); pKernel.meanDist1 = meanDist1; pKernel.meanDist2 = meanDist2; @@ -535,10 +453,6 @@ void Individual::setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel // Get phenotypic emigration traits trfrKernTraits Individual::getKernTraits(void) { -#if RSDEBUG - //DEBUGLOG << "Individual::getKernTraits(): indId=" << indId - // << endl; -#endif trfrKernTraits k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; if (pTrfrData != 0) { @@ -548,12 +462,6 @@ trfrKernTraits Individual::getKernTraits(void) { k.meanDist2 = pKernel.meanDist2; k.probKern1 = pKernel.probKern1; } -#if RSDEBUG - //DEBUGLOG << "Individual::getKernTraits(): indId=" << indId - // << " k.meanDist1=" << k.meanDist1 << " k.meanDist2=" << k.meanDist1 - // << " k.probKern1=" << k.probKern1 - // << endl; -#endif return k; } @@ -571,12 +479,6 @@ void Individual::setSMSTraits(Species* pSpecies) { betaDB = getTrait(SMS_BETADB)->express(); } -#if RSDEBUG - //DEBUGLOG << "Individual::setSMSTraits(): indId=" << indId - // << " dp=" << dp << " gb=" << gb - // << " alphaDB=" << alphaDB << " betaDB=" << betaDB - // << endl; -#endif auto& pSMS = dynamic_cast(*pTrfrData); pSMS.dp = (float)(dp); pSMS.gb = (float)(gb); @@ -588,22 +490,10 @@ void Individual::setSMSTraits(Species* pSpecies) { pSMS.alphaDB = s.alphaDB; pSMS.betaDB = s.betaDB; } -#if RSDEBUG - //DEBUGLOG << "Individual::setSMSTraits() 1111: indId=" << indId - // << " smsData->dp=" << smsData->dp << " smsData->gb=" << smsData->gb - // << " smsData->alphaDB=" << smsData->alphaDB << " smsData->betaDB=" << smsData->betaDB - // << endl; -#endif if (pSMS.dp < 1.0) pSMS.dp = 1.0; if (pSMS.gb < 1.0) pSMS.gb = 1.0; if (pSMS.alphaDB <= 0.0) pSMS.alphaDB = 0.000001f; if (pSMS.betaDB < 1) pSMS.betaDB = 1; -#if RSDEBUG - //DEBUGLOG << "Individual::setSMSTraits() 2222: indId=" << indId - // << " smsData->dp=" << smsData->dp << " smsData->gb=" << smsData->gb - // << " smsData->alphaDB=" << smsData->alphaDB << " smsData->betaDB=" << smsData->betaDB - // << endl; -#endif return; } @@ -613,10 +503,7 @@ trfrData* Individual::getTrfrData(void) { // Get phenotypic transfer by SMS traits trfrSMSTraits Individual::getSMSTraits(void) { -#if RSDEBUG - //DEBUGLOG << "Individual::getSMSTraits(): indId=" << indId << " smsData=" << smsData - // << endl; -#endif + trfrSMSTraits s; s.dp = s.gb = s.alphaDB = 1.0; s.betaDB = 1; if (pTrfrData != 0) { @@ -625,12 +512,7 @@ trfrSMSTraits Individual::getSMSTraits(void) { s.dp = pSMS.dp; s.gb = pSMS.gb; s.alphaDB = pSMS.alphaDB; s.betaDB = pSMS.betaDB; } -#if RSDEBUG - //DEBUGLOG << "Individual::getSMSTraits(): indId=" << indId - // << " s.dp=" << s.dp << " s.gb=" << s.gb - // << " s.alphaDB=" << s.alphaDB << " s.betaDB=" << s.betaDB - // << endl; -#endif + return s; } @@ -647,37 +529,17 @@ void Individual::setCRWTraits(Species* pSpecies, bool sexDep) { c.rho = getTrait(CRW_STEPCORRELATION_F)->express(); } -#if RSDEBUG - //DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId - // << " c.stepLength=" << c.stepLength << " c.rho=" << c.rho - // << endl; -#endif - auto& pCRW = dynamic_cast(*pTrfrData); pCRW.stepLength = (float)(c.stepLength); pCRW.rho = (float)(c.rho); -#if RSDEBUG - //DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId - // << " crw->stepL=" << crw->stepL << " crw->rho=" << crw->rho - // << endl; -#endif if (pCRW.stepLength < 1.0) pCRW.stepLength = 1.0; if (pCRW.rho < 0.0) pCRW.rho = 0.0; if (pCRW.rho > 0.999) pCRW.rho = 0.999f; -#if RSDEBUG - //DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId - // << " crw->stepL=" << crw->stepL << " crw->rho=" << crw->rho - // << endl; -#endif return; } // Get phenotypic transfer by CRW traits trfrCRWTraits Individual::getCRWTraits(void) { -#if RSDEBUG - //DEBUGLOG << "Individual::getCRWTraits(): indId=" << indId - // << endl; -#endif trfrCRWTraits c; c.stepLength = c.rho = 0.0; @@ -688,11 +550,6 @@ trfrCRWTraits Individual::getCRWTraits(void) { c.stepLength = pCRW.stepLength; c.rho = pCRW.rho; } -#if RSDEBUG - //DEBUGLOG << "Individual::getCRWTraits(): indId=" << indId - // << " c.stepLength=" << c.stepLength << " c.rho=" << c.rho - // << endl; -#endif return c; @@ -700,21 +557,12 @@ trfrCRWTraits Individual::getCRWTraits(void) { // Get phenotypic settlement traits settleTraits Individual::getSettTraits(void) { -#if RSDEBUG - //DEBUGLOG << "Individual::getSettTraits(): indId=" << indId - // << endl; -#endif settleTraits s; s.s0 = s.alpha = s.beta = 0.0; if (pSettleTraits != 0) { s.s0 = pSettleTraits->s0; s.alpha = pSettleTraits->alpha; s.beta = pSettleTraits->beta; } -#if RSDEBUG - //DEBUGLOG << "Individual::getSettTraits(): indId=" << indId - // << " s.s0=" << s.s0 << " s.alpha=" << s.alpha << " s.beta=" << s.beta - // << endl; -#endif return s; } @@ -827,19 +675,8 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, } } } -#if RSDEBUG - //Patch *startPatch = (Patch*)startpatch; - //DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " x=" << loc.x << " y=" << loc.y - //// << " natalPatch = " << natalPatch - //// << " startpatch = " << startpatch << " patchNum = " << startPatch->getPatchNum() - // << " kern.meanDist1=" << kern.meanDist1; - //if (trfr.twinKern) { - // DEBUGLOG << " meanDist2=" << kern.meanDist2 << " probKern1=" << kern.probKern1; - //} - //DEBUGLOG << endl; -#endif -// scale the appropriate kernel mean to the cell size + // scale the appropriate kernel mean to the cell size if (trfr.twinKern) { if (pRandom->Bernoulli(kern.probKern1)) @@ -849,27 +686,9 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, } else meandist = kern.meanDist1 / (float)land.resol; -#if RSDEBUG - //DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " meandist=" << meandist << endl; -#endif -// scaled mean may not be less than 1 unless emigration derives from the kernel -// (i.e. the 'use full kernel' option is applied) + // scaled mean may not be less than 1 unless emigration derives from the kernel + // (i.e. the 'use full kernel' option is applied) if (!usefullkernel && meandist < 1.0) meandist = 1.0; -#if RSDEBUG - //DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " meandist=" << meandist << endl; -#endif - -#if RSDEBUG -//Patch *startPatch = (Patch*)startpatch; -//DEBUGLOG << "Individual::moveKernel(): indId = " << indId << " x = " << x << " y = " << y -// << " natalPatch = " << natalPatch -//// << " startpatch = " << startpatch << " patchNum = " << startPatch->getPatchNum() -// << " meanDist1 = " << kern.meanDist1; -//if (trfr.twinKern) { -// DEBUGLOG << " probKern1 = " << kern.probKern1 << " meanDist2 = " << kern.meanDist2; -//} -//DEBUGLOG << " meandist = " << meandist << endl; -#endif int loopsteps = 0; // new counter to prevent infinite loop added 14/8/15 do { @@ -904,12 +723,6 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, if (path != 0) (path->year)++; #endif loopsteps++; -#if RSDEBUG - //DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " status=" << status - // << " loopsteps=" << loopsteps << " newX=" << newX << " newY=" << newY - // << " loc.x=" << loc.x << " loc.y=" << loc.y - // << endl; -#endif } while (loopsteps < 1000 && ((!absorbing && (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY)) @@ -945,12 +758,6 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, patch = 0; patchNum = -1; } -#if RSDEBUG - //DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " status=" << status - // << " loopsteps=" << loopsteps << " newX=" << newX << " newY=" << newY - // << " pCell=" << pCell << " patch=" << patch << " patchNum=" << patchNum - // << endl; -#endif } while (!absorbing && patchNum < 0 && loopsteps < 1000); // in a no-data region } while (!usefullkernel && pPatch == pNatalPatch && loopsteps < 1000); // still in the original (natal) patch @@ -987,15 +794,8 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, status = 6; dispersing = 0; } -#if RSDEBUG - //DEBUGLOG << "Individual::moveKernel(): indId=" << indId - // << " newX=" << newX << " newY=" << newY - // << " patch=" << patch - // << " patchNum=" << patchNum << " status=" << status; - //DEBUGLOG << endl; -#endif -// apply dispersal-related mortality, which may be distance-dependent + // apply dispersal-related mortality, which may be distance-dependent dist *= (float)land.resol; // re-scale distance moved to landscape scale if (status < 7) { double dispmort; @@ -1044,11 +844,6 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, settleSteps settsteps = pSpecies->getSteps(stage, sex); patch = pCurrCell->getPatch(); -#if RSDEBUG - //DEBUGLOG << "Individual::moveStep() AAAA: indId=" << indId - // << " pCurrCell=" << pCurrCell << " patch=" << patch - // << endl; -#endif if (patch == 0) { // matrix pPatch = 0; @@ -1066,35 +861,12 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, mortprob = 1.0; } else mortprob = pSpecies->getHabMort(h); -#if RSDEBUG - //locn temploc = pCurrCell->getLocn(); - //DEBUGLOG << "Individual::moveStep(): x=" << temploc.x << " y=" << temploc.x - // << " landIx=" << landIx << " h=" << h << " mortprob=" << mortprob - // << endl; -#endif } else mortprob = movt.stepMort; // ... unless individual has not yet left natal patch in emigration year if (pPatch == pNatalPatch && path->out == 0 && path->year == path->total) { mortprob = 0.0; } -#if RSDEBUG - locn loc0, loc1, loc2; - //loc0 = pCurrCell->getLocn(); - //DEBUGLOG << "Individual::moveStep() BBBB: indId=" << indId << " status=" << status - // << " path->year=" << path->year << " path->out=" << path->out - // << " settleStatus=" << path->settleStatus - // << " x=" << loc0.x << " y=" << loc0.y - //// << " patch=" << patch - // << " pPatch=" << pPatch - // << " patchNum=" << patchNum; - //// << " natalPatch=" << natalPatch; - ////if (crw != 0) { - //// DEBUGLOG << " xc=" << crw->xc << " yc=" << crw->yc; - //// DEBUGLOG << " rho=" << movt.rho << " stepLength=" << movt.stepLength; - ////} - //DEBUGLOG << endl; -#endif if (pRandom->Bernoulli(mortprob)) { // individual dies status = 7; dispersing = 0; @@ -1113,23 +885,7 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, switch (trfr.moveType) { case 1: // SMS -#if RSDEBUG - //loc1 = pCurrCell->getLocn(); - //DEBUGLOG << "Individual::moveStep() FFFF: indId=" << indId << " status=" << status - //// << " path->year=" << path->year - // << " path->season=" << path->season - // << " x=" << loc1.x << " y=" << loc1.y - // << " smsData->goalType=" << smsData->goalType - // << " goal.x=" << smsData->goal.x - // << " goal.y=" << smsData->goal.y - // << endl; -#endif move = smsMove(pLandscape, pSpecies, landIx, pPatch == pNatalPatch, trfr.indVar, absorbing); -#if RSDEBUG - //DEBUGLOG << "Individual::moveStep() GGGG: indId=" << indId << " status=" << status - // << " move.dist=" << move.dist - // << endl; -#endif if (move.dist < 0.0) { // either INTERNAL ERROR CONDITION - INDIVIDUAL IS IN NO-DATA SQUARE // or individual has crossed absorbing boundary ... @@ -1138,16 +894,8 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, dispersing = 0; } else { -#if RSDEBUG - //loc1 = pCurrCell->getLocn(); - //DEBUGLOG << "Individual::moveStep() HHHH: indId=" << indId << " status=" << status - // << " path->year=" << path->year - // << " x=" << loc1.x << " y=" << loc1.y - //// << " smsData = " << smsData - // << endl; -#endif - // WOULD IT BE MORE EFFICIENT FOR smsMove TO RETURN A POINTER TO THE NEW CELL? ... + // WOULD IT BE MORE EFFICIENT FOR smsMove TO RETURN A POINTER TO THE NEW CELL? ... patch = pCurrCell->getPatch(); //int patchnum; @@ -1169,7 +917,7 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, auto & pCRW = dynamic_cast(*pTrfrData); - if (trfr.indVar) { + if (trfr.indVar) { movt.stepLength = pCRW.stepLength; movt.rho = pCRW.rho; } @@ -1203,13 +951,6 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, if (xcnew < 0.0) newX = -1; else newX = (int)xcnew; if (ycnew < 0.0) newY = -1; else newY = (int)ycnew; loopsteps++; -#if RSDEBUG - //DEBUGLOG << "Individual::moveStep(): indId=" << indId - // << " xc=" << crw->xc << " yc=" << crw->yc << " pCurrCell=" << pCurrCell - // << " steps=" << path->year << " loopsteps=" << loopsteps - // << " steplen=" << steplen << " rho=" << rho << " angle=" << angle - // << " xcnew=" << xcnew << " ycnew=" << ycnew << " newX=" << newX << " newY=" << newY << endl; -#endif } while (!absorbing && loopsteps < 1000 && (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY)); if (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY) @@ -1222,11 +963,6 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, } else patch = pCurrCell->getPatch(); -#if RSDEBUG - //DEBUGLOG << "Individual::moveStep(): indId=" << indId - // << " loopsteps=" << loopsteps << " absorbed=" << absorbed - // << " pCurrCell=" << pCurrCell << " patch=" << patch << endl; -#endif } while (!absorbing && pCurrCell == 0 && loopsteps < 1000); pCRW.prevdrn = (float)angle; pCRW.xc = (float)xcnew; pCRW.yc = (float)ycnew; @@ -1246,36 +982,10 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, pCurrCell = pPrevCell; } } -#if RSDEBUG - //DEBUGLOG << "Individual::moveStep(): indId=" << indId - // << " status=" << status - // << " pCurrCell=" << pCurrCell << " patch=" << patch << endl; -#endif break; } // end of switch (trfr.moveType) -#if RSDEBUG -//locn loc2; -//if (pCurrCell > 0) { -// loc2 = pCurrCell->getLocn(); -//} -//else { -// loc2.x = -9999; loc2.y = -9999; -//} -//DEBUGLOG << "Individual::moveStep() ZZZZ: indId=" << indId -// << " status=" << status -// << " path->total=" << path->total -// << " x=" << loc2.x << " y=" << loc2.y -// << " patch=" << patch; -//if (patch > 0) { -// pPatch = (Patch*)patch; -// DEBUGLOG << " patchNum=" << pPatch->getPatchNum() -// << " getK()=" << pPatch->getK() -// << " popn=" << pPatch->getPopn((int)pSpecies); -//} -// DEBUGLOG << endl; -#endif if (patch > 0 // not no-data area or matrix && path->total >= settsteps.minSteps) { pPatch = (Patch*)patch; @@ -1324,12 +1034,6 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, locn current; auto& pSMS = dynamic_cast(*pTrfrData); - //if (write_out) { - // out<findCell(x,y); if (pCurrCell == 0) { // x,y is a NODATA square - this should not occur here @@ -1338,16 +1042,11 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, return move; } -#if RSDEBUG - //DEBUGLOG << "Individual::smsMove(): this=" << this << endl; -#endif - landData land = pLand->getLandData(); trfrSMSTraits movt = pSpecies->getSMSTraits(); current = pCurrCell->getLocn(); //get weights for directional persistence.... - //if ((path->out > 0 && path->out < 10 && path->out < 2*movt.pr) if ((path->out > 0 && path->out <= (movt.pr + 1)) || natalPatch || (movt.straigtenPath && path->settleStatus > 0)) { @@ -1360,25 +1059,8 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, else nbr = getSimDir(current.x, current.y, movt.dp); } if (natalPatch || path->settleStatus > 0) path->out = 0; - //if (natalPatch) path->out = 0; -#if RSDEBUG -//DEBUGLOG << "Individual::smsMove() 0000: nbr matrix" << endl; -//for (y2 = 2; y2 > -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) DEBUGLOG << nbr.cell[x2][y2] << " "; -// DEBUGLOG << endl; -//} -#endif -//if (write_out) { -// out< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) out< -1; y2--) { - // for (x2 = 0; x2 < 3; x2++) out< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) out< -1; y2--) { - // for (x2 = 0; x2 < 3; x2++) DEBUGLOG << hab.cell[x2][y2] << " "; - // DEBUGLOG << endl; - //} -#endif pCurrCell->setEffCosts(hab); } else { // they have already been calculated - no action required - // if (write_out) { - // out<<"*** using previous effective costs ***"< -1; y2--) { - // for (x2 = 0; x2 < 3; x2++) { - // out< -1; y2--) { - // for (x2 = 0; x2 < 3; x2++) DEBUGLOG << nbr.cell[x2][y2] << " "; - // DEBUGLOG << endl; - //} -#endif -// determine reciprocal of effective cost for the 8 neighbours -//if (write_out) out<<"reciprocal weighted effective costs:"< -1; y2--) { for (x2 = 0; x2 < 3; x2++) { if (nbr.cell[x2][y2] > 0.0) nbr.cell[x2][y2] = 1.0f / nbr.cell[x2][y2]; - // if (write_out) { - // out< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) { -// temp.cell[x2][y2] = nbr.cell[x2][y2]; -// if (current.x == 488 && current.y == 422) { -// pCell = pLand->findCell((current.x+x2-1),(current.y+y2-1)); -// DEBUGLOG << "Individual::smsMove(): this=" << this -// << " IN THE PROBLEM CELL" -// << " y=" << current.y << " x=" << current.x -// << " y2=" << y2 << " x2=" << x2 -// << " pCell=" << pCell; -// if (pCell != 0) DEBUGLOG << " pCell->getCost=" << pCell->getCost(); -// DEBUGLOG << endl; -// } -// } -//} -#endif - for (y2 = 2; y2 > -1; y2--) { for (x2 = 0; x2 < 3; x2++) { if (!absorbing) { @@ -1537,44 +1135,20 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, if (pCell == 0) nbr.cell[x2][y2] = 0.0; // no-data cell } } -#if RSDEBUG - //DEBUGLOG << "Individual::smsMove(): this=" << this - // << " y=" << current.y << " x=" << current.x - // << " y2=" << y2 << " x2=" << x2 - // << " pCell=" << pCell - // << endl; -#endif -// if (write_out) { -// out< 0.0) { // should always be the case, but safest to check... for (y2 = 2; y2 > -1; y2--) { for (x2 = 0; x2 < 3; x2++) { nbr.cell[x2][y2] = nbr.cell[x2][y2] / (float)sum_nbrs; - // if (write_out) { - // out< -1; y2--) { - // for (x2 = 0; x2 < 3; x2++) DEBUGLOG << nbr.cell[x2][y2] << " "; - // DEBUGLOG << endl; - //} -#endif -// set up cell selection probabilities -//if (write_out) out<<"rnd = "<findCell(newX, newY); } } while (!absorbing && pNewCell == 0 && loopsteps < 1000); // no-data cell -#if RSDEBUG - //DEBUGLOG << "Individual::smsMove() 8888: pNewCell=" << pNewCell - // << " loopsteps=" << loopsteps - // << " current.x=" << current.x << " current.y=" << current.y - // << " newX=" << newX << " newY=" << newY - // << " land.minX=" << land.minX << " land.minY=" << land.minY - // << " land.maxX=" << land.maxX << " land.maxY=" << land.maxY - // << endl; -#endif if (loopsteps >= 1000 || pNewCell == 0) { // unable to make a move or crossed absorbing boundary // flag individual to die @@ -1688,15 +1240,12 @@ array3x3d Individual::getSimDir(const int x, const int y, const float dp) if ((x - prev.x) == 0 && (y - prev.y) == 0) { // back to 'square 1' (first memory location) - use previous step drn only prev = memory.back(); - // if (write_out) out<<"step 3"<getHabIndex(landIx); cost = pSpecies->getHabCost(h); -#if RSDEBUG - //DEBUGLOG << "Individual::getHabMatrix(): x4=" << x4 << " y4=" << y4 - // << " landIx=" << landIx << " h=" << h << " cost=" << cost - // << endl; -#endif pCell->setCost(cost); } else { -#if RSDEBUG - //DEBUGLOG << "Individual::getHabMatrix(): x4=" << x4 << " y4=" << y4 - // << " cost=" << cost - // << endl; -#endif - + // nothing? } } } @@ -1938,26 +1464,14 @@ array3x3f Individual::getHabMatrix(Landscape* pLand, Species* pSpecies, ncells++; sumweights += weight; } } - // if (write_out2) out2<get_target() > 50) targetseen++; - // } - //#endif } //end of y3 loop } //end of x3 loop - // if (write_out) out<<"ncells in PR = "<avail=" << iter->avail - // << " iter->value=" << iter->value << endl; -#endif pCell = findCell(x, y); if (continuous) { if (iter->value > 0.0) { // habitat @@ -722,12 +615,6 @@ void Landscape::generatePatches(void) else { // random landscape int hab = 0; ncells = (int)((float)(dimX) * (float)(dimY)*propSuit + 0.00001); // no. of cells to initialise -#if RSDEBUG - //DEBUGLOG << "Landscape::generatePatches(): dimX=" << dimX << " dimY=" << dimY - // << " propSuit=" << propSuit - // << " PRODUCT=" << ((float)(dimX) * (float)(dimY) * propSuit + 0.00001) - // << " ncells=" << ncells << endl; -#endif int i = 0; do { do { @@ -735,11 +622,6 @@ void Landscape::generatePatches(void) pCell = findCell(x, y); hab = pCell->getHabIndex(0); } while (hab > 0); -#if RSDEBUG - //DEBUGLOG << "Landscape::generatePatches() 00000: y=" << y << " x=" << x - // << " i=" << i << " hab=" << hab << " patchnum=" << patchnum - // << endl; -#endif patchnums.push_back(patchnum); pPatch = newPatch(patchnum++); pCell = findCell(x, y); @@ -764,10 +646,6 @@ void Landscape::generatePatches(void) } else { // discrete if (pCell->getHabIndex(0) == 0) { -#if RSDEBUG - //DEBUGLOG << "Landscape::generatePatches() 11111: yy=" << yy << " xx=" << xx - // << endl; -#endif addCellToPatch(pCell, patches[0], x); } } @@ -775,11 +653,6 @@ void Landscape::generatePatches(void) } } -#if RSDEBUG - //DEBUGLOG << "Landscape::generatePatches(): finished, no. of patches = " - // << patchCount() << endl; -#endif - simParams sim = paramsSim->getSim(); if (pSpecies->getNumberOfNeutralLoci() > 0 && (sim.outputWCFstat || sim.outputPairwiseFst)) { @@ -802,10 +675,6 @@ void Landscape::generatePatches(void) habitat cells are added to the matrix patch) */ void Landscape::allocatePatches(Species* pSpecies) { -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): pSpecies=" << pSpecies - // << " N patches=" << (int)patches.size() << endl; -#endif //int hx; float habK; Patch* pPatch; @@ -814,10 +683,6 @@ void Landscape::allocatePatches(Species* pSpecies) // delete all existing patches int npatches = (int)patches.size(); for (int i = 0; i < npatches; i++) { -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): i=" << i - // << " patches[i]=" << patches[i] << endl; -#endif if (patches[i] != NULL) delete patches[i]; } patches.clear(); @@ -825,10 +690,6 @@ void Landscape::allocatePatches(Species* pSpecies) patches.push_back(new Patch(0, 0)); Patch* matrixPatch = patches[0]; patchnums.push_back(0); -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): npatches=" << npatches - // << " N patches=" << (int)patches.size() << endl; -#endif int patchnum = 1; switch (rasterType) { @@ -836,10 +697,6 @@ void Landscape::allocatePatches(Species* pSpecies) case 0: // habitat codes for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y - // << " cells=" << cells[y][x] << endl; -#endif if (cells[y][x] != 0) { // not no-data cell pCell = cells[y][x]; // hx = pCell->getHabIndex(); @@ -848,13 +705,6 @@ void Landscape::allocatePatches(Species* pSpecies) int nhab = pCell->nHabitats(); for (int i = 0; i < nhab; i++) { habK += pSpecies->getHabK(pCell->getHabIndex(i)); -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y - // << " i=" << i - // << " cells[y][x]=" << cells[y][x] - // << " pCell=" << pCell - // << " habK=" << habK << endl; -#endif } if (habK > 0.0) { // cell is suitable - create a patch for it patchnums.push_back(patchnum); @@ -872,10 +722,6 @@ void Landscape::allocatePatches(Species* pSpecies) case 1: // habitat cover for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y - // << " cells=" << cells[y][x] << endl; -#endif if (cells[y][x] != 0) { // not no-data cell pCell = cells[y][x]; habK = 0.0; @@ -884,13 +730,6 @@ void Landscape::allocatePatches(Species* pSpecies) for (int i = 0; i < nhab; i++) { habK += pSpecies->getHabK(i) * pCell->getHabitat(i) / 100.0f; -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y - // << " i=" << i - // << " cells[y][x]=" << cells[y][x] - // << " pCell=" << pCell - // << " habK=" << habK << endl; -#endif } if (habK > 0.0) { // cell is suitable - create a patch for it patchnums.push_back(patchnum); @@ -908,25 +747,13 @@ void Landscape::allocatePatches(Species* pSpecies) case 2: // habitat quality for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y - // << " cells=" << cells[y][x] << endl; -#endif if (cells[y][x] != 0) { // not no-data cell pCell = cells[y][x]; habK = 0.0; int nhab = pCell->nHabitats(); - // for (int i = 0; i < nHab; i++) for (int i = 0; i < nhab; i++) { habK += pSpecies->getHabK(0) * pCell->getHabitat(i) / 100.0f; -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y - // << " i=" << i - // << " cells[y][x]=" << cells[y][x] - // << " pCell=" << pCell - // << " habK=" << habK << endl; -#endif } if (habK > 0.0) { // cell is suitable (at some time) - create a patch for it patchnums.push_back(patchnum); @@ -955,12 +782,6 @@ void Landscape::allocatePatches(Species* pSpecies) pSpecies->setSamplePatchList(patchesToSample); } - - -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): finished, N patches = " << (int)patches.size() << endl; -#endif - } Patch* Landscape::newPatch(int num) @@ -1118,12 +939,6 @@ void Landscape::updateCarryingCapacity(Species* pSpecies, int yr, short landIx) patchLimits landlimits; landlimits.xMin = minX; landlimits.xMax = maxX; landlimits.yMin = minY; landlimits.yMax = maxY; -#if RSDEBUG - //DEBUGLOG << "Landscape::updateCarryingCapacity(): yr=" << yr - // << " xMin=" << landlimits.xMin << " yMin=" << landlimits.yMin - // << " xMax=" << landlimits.xMax << " yMax=" << landlimits.yMax - // << endl; -#endif int npatches = (int)patches.size(); for (int i = 0; i < npatches; i++) { if (patches[i]->getPatchNum() != 0) { // not matrix patch @@ -1181,13 +996,6 @@ int Landscape::checkTotalCover(void) { float sumCover = 0.0; for (int i = 0; i < nHab; i++) { sumCover += cells[y][x]->getHabitat(i); -#if RSDEBUG - //DebugGUI(("Landscape::checkTotalCover(): y=" + Int2Str(y) - // + " x=" + Int2Str(x) - // + " i=" + Int2Str(i) - // + " sumCover=" + Float2Str(sumCover) - // ).c_str()); -#endif } if (sumCover > 100.00001) nCells++; // decimal part to allow for floating point error if (sumCover <= 0.0) // cell is a matrix cell @@ -1209,28 +1017,13 @@ void Landscape::updateHabitatIndices(void) { // convert codes in landscape int h; int changes = (int)landchanges.size(); -#if RSDEBUG - //DebugGUI(("Landscape::updateHabitatIndices(): nHab=" + Int2Str(nHab) - // + " changes=" + Int2Str(changes) - // ).c_str()); -#endif for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { if (cells[y][x] != 0) { // not a no-data cell for (int c = 0; c <= changes; c++) { h = cells[y][x]->getHabIndex(c); -#if RSDEBUG - //DebugGUI(("Landscape::updateHabitatIndices() 00000: y=" + Int2Str(y) - // + " x=" + Int2Str(x) + " c=" + Int2Str(c) + " h=" + Int2Str(h) - // ).c_str()); -#endif if (h >= 0) { h = findHabCode(h); -#if RSDEBUG - //DebugGUI(("Landscape::updateHabitatIndices() 11111: y=" + Int2Str(y) - // + " x=" + Int2Str(x) + " c=" + Int2Str(c) + " h=" + Int2Str(h) - // ).c_str()); -#endif cells[y][x]->changeHabIndex(c, h); } } @@ -1248,11 +1041,6 @@ void Landscape::setEnvGradient(Species* pSpecies, bool initial) double envval; // gradient parameters envGradParams grad = paramsGrad->getGradient(); -#if RSDEBUG - //DEBUGLOG << "Landscape::setEnvGradient(): grad.opt_y = " << grad.opt_y - // << " grad.grad_inc = " << grad.grad_inc << " grad.factor " << grad.factor - // << endl; -#endif for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { // NB: gradient lies in range 0-1 for all types, and is applied when necessary... @@ -1273,11 +1061,6 @@ void Landscape::setEnvGradient(Species* pSpecies, bool initial) break; } } -#if RSDEBUG - //DEBUGLOG << "Landscape::setEnvGradient(): y=" << y << " x=" << x - // << " dist_from_opt=" << dist_from_opt << " rasterType=" << rasterType << " hab=" << hab - // << endl; -#endif if (habK > 0.0) { // suitable cell if (initial) { // set local environmental deviation cells[y][x]->setEnvDev((float)pRandom->Random() * (2.0f) - 1.0f); @@ -1285,11 +1068,6 @@ void Landscape::setEnvGradient(Species* pSpecies, bool initial) dist_from_opt = (float)(fabs((double)grad.opt_y - (double)y)); dev = cells[y][x]->getEnvDev(); envval = 1.0 - dist_from_opt * grad.grad_inc + dev * grad.factor; -#if RSDEBUG - //DEBUGLOG << "Landscape::setEnvGradient(): y=" << y << " x=" << x - // << " dist_from_opt=" << dist_from_opt << " dev=" << dev << " p=" << p - // << endl; -#endif if (envval < 0.000001) envval = 0.0; if (envval > 1.0) envval = 1.0; } @@ -1325,11 +1103,6 @@ void Landscape::updateLocalStoch(void) { for (int x = 0; x < dimX; x++) { if (cells[y][x] != 0) { // not a no-data cell randpart = (float)(pRandom->Normal(0.0, env.std) * sqrt(1.0 - (env.ac * env.ac))); -#if RSDEBUG - //DEBUGLOG << "Landscape::updateLocalStoch(): y=" << y << " x=" << x - // << " env.std= " << env.std << " env.ac= " << env.ac << " randpart= " << randpart - // << endl; -#endif cells[y][x]->updateEps((float)env.ac, randpart); } } @@ -1364,11 +1137,6 @@ void Landscape::resetEffCosts(void) { void Landscape::setDynamicLand(bool dyn) { dynamic = dyn; } void Landscape::addLandChange(landChange c) { -#if RSDEBUG - //DebugGUI(("Landscape::addLandChange(): chgnum=" + Int2Str(c.chgnum) - // + " chgyear=" + Int2Str(c.chgyear) - // ).c_str()); -#endif landchanges.push_back(c); } @@ -1413,12 +1181,6 @@ int Landscape::readLandChange(int filenum, bool costs) if (filenum < 0) return 19; - //if (patchModel && (rasterType == 0 || rasterType == 2)) { - // if (filenum == 0) { // first change - // createPatchChgMatrix(); - // } - // pchseq = patchCount(); - //} if (patchModel) pchseq = patchCount(); #if !RS_RCPP @@ -1543,11 +1305,6 @@ int Landscape::readLandChange(int filenum, bool costs) } #endif } -#if RSDEBUG - //DebugGUI(("Landscape::readLandscape(): x=" + Int2Str(x) + " y=" + Int2Str(y) - // + " h=" + Int2Str(h) + " p=" + Int2Str(p) - //).c_str()); -#endif if (cells[y][x] != 0) { // not a no data cell (in initial landscape) if (h == habnodata) { // invalid no data cell in change map hfile.close(); hfile.clear(); @@ -1687,10 +1444,6 @@ int Landscape::readLandChange(int filenum, bool costs) } #endif } -#if RSDEBUG - //MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) - // + " p=" + Int2Str(p)).c_str()); -#endif if (cells[y][x] != 0) { // not a no data cell (in initial landscape) if (h == habnodata) { // invalid no data cell in change map hfile.close(); hfile.clear(); @@ -1795,14 +1548,6 @@ void Landscape::createPatchChgMatrix(void) } } patchChgMatrix[y][x][2] = 0; -#if RSDEBUG - //DebugGUI(("Landscape::createPatchChgMatrix(): y=" + Int2Str(y) - // + " x=" + Int2Str(x) - // + " patchChgMatrix[y][x][0]=" + Int2Str(patchChgMatrix[y][x][0]) - // + " [1]=" + Int2Str(patchChgMatrix[y][x][1]) - // + " [2]=" + Int2Str(patchChgMatrix[y][x][2]) - // ).c_str()); -#endif } } } @@ -1820,15 +1565,6 @@ void Landscape::recordPatchChanges(int landIx) { chg.oldpatch = patchChgMatrix[y][x][2]; chg.newpatch = patchChgMatrix[y][x][0]; patchchanges.push_back(chg); -#if RSDEBUG - //DebugGUI(("Landscape::recordPatchChanges(): landIx=" + Int2Str(landIx) - // + " chg.chgnum=" + Int2Str(chg.chgnum) - // + " chg.x=" + Int2Str(chg.x) - // + " chg.y=" + Int2Str(chg.y) - // + " chg.oldpatch=" + Int2Str(chg.oldpatch) - // + " chg.newpatch=" + Int2Str(chg.newpatch) - // ).c_str()); -#endif } } else { // any other change @@ -1838,15 +1574,6 @@ void Landscape::recordPatchChanges(int landIx) { chg.oldpatch = patchChgMatrix[y][x][1]; chg.newpatch = patchChgMatrix[y][x][2]; patchchanges.push_back(chg); -#if RSDEBUG - //DebugGUI(("Landscape::recordPatchChanges(): landIx=" + Int2Str(landIx) - // + " chg.chgnum=" + Int2Str(chg.chgnum) - // + " chg.x=" + Int2Str(chg.x) - // + " chg.y=" + Int2Str(chg.y) - // + " chg.oldpatch=" + Int2Str(chg.oldpatch) - // + " chg.newpatch=" + Int2Str(chg.newpatch) - // ).c_str()); -#endif } } // reset cell for next landscape change @@ -1897,14 +1624,6 @@ void Landscape::createCostsChgMatrix(void) costsChgMatrix[y][x][0] = costsChgMatrix[y][x][1] = pCell->getCost(); } costsChgMatrix[y][x][2] = 0; -#if RSDEBUG - //DebugGUI(("Landscape::createCostsChgMatrix(): y=" + Int2Str(y) - // + " x=" + Int2Str(x) - // + " costsChgMatrix[y][x][0]=" + Int2Str(costsChgMatrix[y][x][0]) - // + " [1]=" + Int2Str(costsChgMatrix[y][x][1]) - // + " [2]=" + Int2Str(costsChgMatrix[y][x][2]) - // ).c_str()); -#endif } } } @@ -1925,42 +1644,15 @@ void Landscape::recordCostChanges(int landIx) { chg.oldcost = costsChgMatrix[y][x][2]; chg.newcost = costsChgMatrix[y][x][0]; costschanges.push_back(chg); -#if RSDEBUG - //DebugGUI(("Landscape::recordCostsChanges(): landIx=" + Int2Str(landIx) - // + " chg.chgnum=" + Int2Str(chg.chgnum) - // + " chg.x=" + Int2Str(chg.x) - // + " chg.y=" + Int2Str(chg.y) - // + " chg.oldcost=" + Int2Str(chg.oldcost) - // + " chg.newcost=" + Int2Str(chg.newcost) - // ).c_str()); -#endif } } else { // any other change -#if RSDEBUG - //if (x < 20 && y == 0) { - // DEBUGLOG << "Landscape::recordCostChanges(): x=" << x << " y=" << y - // << " costsChgMatrix[y][x][0]=" << costsChgMatrix[y][x][0] - // << " costsChgMatrix[y][x][1]=" << costsChgMatrix[y][x][1] - // << " costsChgMatrix[y][x][2]=" << costsChgMatrix[y][x][2] - // << endl; - //} -#endif if (costsChgMatrix[y][x][2] != costsChgMatrix[y][x][1]) { // record change of cost for current cell chg.chgnum = landIx; chg.x = x; chg.y = y; chg.oldcost = costsChgMatrix[y][x][1]; chg.newcost = costsChgMatrix[y][x][2]; costschanges.push_back(chg); -#if RSDEBUG - //DebugGUI(("Landscape::recordCostsChanges(): landIx=" + Int2Str(landIx) - // + " chg.chgnum=" + Int2Str(chg.chgnum) - // + " chg.x=" + Int2Str(chg.x) - // + " chg.y=" + Int2Str(chg.y) - // + " chg.oldcost=" + Int2Str(chg.oldcost) - // + " chg.newcost=" + Int2Str(chg.newcost) - // ).c_str()); -#endif } } // reset cell for next landscape change @@ -2267,12 +1959,6 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string return 135; } #endif - -#if RSDEBUG - //DebugGUI(("Landscape::readLandscape(): x=" + Int2Str(x) + " y=" + Int2Str(y) - // + " h=" + Int2Str(h) + " p=" + Int2Str(p) - //).c_str()); -#endif if (h == habnodata) addNewCellToLand(x, y, -1); // add cell only to landscape else { @@ -2374,10 +2060,6 @@ if (patchModel) #endif } //end if patchmodel -#if RSDEBUG -//MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) -// + " p=" + Int2Str(p)).c_str()); -#endif if (h == habnodata) { addNewCellToLand(x, y, -1); // add cell only to landscape } @@ -2526,10 +2208,6 @@ else { // couldn't read from hfile } #endif } -#if RSDEBUG - //MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) - // + " p=" + Int2Str(p)).c_str()); -#endif if (h == habnodata) { addNewCellToLand(x, y, -1); // add cell only to landscape } @@ -2635,7 +2313,7 @@ int Landscape::readCosts(string fname) #if !RS_RCPP simView v = paramsSim->getViews(); #endif - +#endif int maxcost = 0; #if RSDEBUG @@ -2710,19 +2388,10 @@ int Landscape::readCosts(string fname) } #endif if (hc < 1 && hc != NODATACost) { -#if RSDEBUG -#if BATCH - // DEBUGLOG << "Landscape::readCosts(): x=" << x << " y=" << y - // << " fcost=" << fcost << " hc=" << hc - // << endl; -#endif -#endif #if RS_RCPP && !R_CMD Rcpp::Rcout << "Cost map my only contain values of 1 or higher, but found " << fcost << "." << endl; #endif // error - zero / negative cost not allowed -// MessageDlg("Error in the costs map file : zero or negative cost detected." -// , mtError, TMsgDlgButtons() << mbOK,0); costs.close(); costs.clear(); return -999; } @@ -2767,40 +2436,16 @@ rasterdata CheckRasterFile(string fname) infile.open(fname.c_str()); if (infile.is_open()) { infile >> header >> r.ncols; -#if RSDEBUG - DebugGUI(("CheckRasterFile(): header=" + header + " r.ncols=" + Int2Str(r.ncols) - ).c_str()); -#endif if (header != "ncols" && header != "NCOLS") r.errors++; infile >> header >> r.nrows; -#if RSDEBUG - DebugGUI(("CheckRasterFile(): header=" + header + " r.nrows=" + Int2Str(r.nrows) - ).c_str()); -#endif if (header != "nrows" && header != "NROWS") r.errors++; infile >> header >> r.xllcorner; -#if RSDEBUG - DebugGUI(("CheckRasterFile(): header=" + header + " r.xllcorner=" + Float2Str(r.xllcorner) - ).c_str()); -#endif if (header != "xllcorner" && header != "XLLCORNER") r.errors++; infile >> header >> r.yllcorner; -#if RSDEBUG - DebugGUI(("CheckRasterFile(): header=" + header + " r.yllcorner=" + Float2Str(r.yllcorner) - ).c_str()); -#endif if (header != "yllcorner" && header != "YLLCORNER") r.errors++; infile >> header >> r.cellsize; -#if RSDEBUG - DebugGUI(("CheckRasterFile(): header=" + header + " r.cellsize=" + Int2Str(r.cellsize) - ).c_str()); -#endif if (header != "cellsize" && header != "CELLSIZE") r.errors++; infile >> header >> inint; -#if RSDEBUG - DebugGUI(("CheckRasterFile(): header=" + header + " inint=" + Int2Str(inint) - ).c_str()); -#endif if (header != "NODATA_value" && header != "NODATA_VALUE") r.errors++; infile.close(); infile.clear(); @@ -2823,9 +2468,6 @@ void Landscape::createConnectMatrix(void) { if (connectMatrix != 0) deleteConnectMatrix(); int npatches = (int)patches.size(); -#if RSDEBUG - //DEBUGLOG << "Landscape::createConnectMatrix(): npatches=" << npatches << endl; -#endif connectMatrix = new int* [npatches]; for (int i = 0; i < npatches; i++) { connectMatrix[i] = new int[npatches]; @@ -3025,10 +2667,6 @@ void Landscape::outVisits(int rep, int landNr) { outvisits << "NODATA_value -9" << endl; for (int y = dimY - 1; y >= 0; y--) { -#if RSDEBUG - //DebugGUI(("Landscape::drawLandscape(): y=" + Int2Str(y) - // + " cells[y]=" + Int2Str((int)cells[y])).c_str()); -#endif for (int x = 0; x < dimX; x++) { if (cells[y][x] == 0) { // no-data cell outvisits << "-9 "; From 10ecad7e4466dd7f6cded335b23398b691c5d7f7 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 9 Feb 2024 12:34:09 +0100 Subject: [PATCH 031/332] fix missing argument --- Landscape.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Landscape.cpp b/Landscape.cpp index b1e3663..bee1045 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -547,7 +547,7 @@ void Landscape::addPatchNum(int p) { /* Create an artificial landscape (random or fractal), which can be either binary (habitat index 0 is the matrix, 1 is suitable habitat) or continuous (0 is the matrix, >0 is suitable habitat) */ -void Landscape::generatePatches(void) +void Landscape::generatePatches(Species* pSpecies) { int x, y, ncells; double p; From f1a63780bb2bcbc3893638a9beef593c0878873a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 12 Feb 2024 11:07:58 +0100 Subject: [PATCH 032/332] fix default constructor --- NeutralStatsManager.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index 23ce1bb..4b269e0 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -15,9 +15,7 @@ struct PatchMatrix public: - PatchMatrix() {}; - - PatchMatrix(unsigned int rows, unsigned int cols) : _rows(0), _cols(0), _length(0), _val(0) { + PatchMatrix(int rows = 0, int cols = 0) : _rows(0), _cols(0), _length(0), _val(0) { _length = rows * cols; _val.resize(_length); _rows = rows; _cols = cols; From 3fedb66680b5e766bb6054d969d16bc6d7151080 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 12 Feb 2024 14:23:46 +0000 Subject: [PATCH 033/332] fix a few warnings --- Species.cpp | 4 ++-- Species.h | 28 +++++++++++++--------------- SpeciesTrait.cpp | 5 ++++- SpeciesTrait.h | 2 ++ 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/Species.cpp b/Species.cpp index 03d0da7..a32c814 100644 --- a/Species.cpp +++ b/Species.cpp @@ -756,8 +756,8 @@ void Species::setSettTraits(const short stg, const short sex, const settleTraits } } -void Species::setGeneticParameters(const set& chromosomeEnds, const int genomeSize, const float recombinationRate, - const set& samplePatchList, const string nIndsToSample, const set& stagesToSampleFrom, string nSampleCellsFst) +void Species::setGeneticParameters(const std::set& chromosomeEnds, const int genomeSize, const float recombinationRate, + const std::set& samplePatchList, const string nIndsToSample, const std::set& stagesToSampleFrom, string nSampleCellsFst) { this->genomeSize = genomeSize; for (auto position : chromosomeEnds) { diff --git a/Species.h b/Species.h index 9cd6377..fc4a79c 100644 --- a/Species.h +++ b/Species.h @@ -49,6 +49,8 @@ #include "SpeciesTrait.h" #include "TTrait.h" #include +#include +#include // structures for demographic parameters @@ -280,7 +282,7 @@ class Species { short // option: 0 = return minimum, otherwise = return maximum ); - set& getSamplePatches() { + std::set& getSamplePatches() { return samplePatchList; }; @@ -288,7 +290,7 @@ class Species { return nIndsToSample; }; - set& getStagesToSample() { + std::set& getStagesToSample() { return stagesToSampleFrom; } @@ -419,19 +421,16 @@ class Species { //map>& getTraitTable(void); //return by reference so ensure variable recieving is const - set getTraitTypes(); + std::set getTraitTypes(); int getNTraits() const; int getNPositionsForTrait(const TraitType trait) const; int getGenomeSize() const; - void setGenomeSize(int); float getRecombinationRate() const; - void setRecombinationRate(float); - set getChromosomeEnds() const; - void setChromosomeEnds(const set& ends); - void setGeneticParameters(const set& chromosomeEnds, const int genomeSize, const float recombinationRate, - const set& samplePatchList, const string nIndsToSample, const set& stagesToSampleFrom, string nSampleCellsFst); - void setSamplePatchList(const set& samplePatchList); + std::set getChromosomeEnds() const; + void setGeneticParameters(const std::set& chromosomeEnds, const int genomeSize, const float recombinationRate, + const std::set& samplePatchList, const string nIndsToSample, const std::set& stagesToSampleFrom, string nSampleCellsFst); + void setSamplePatchList(const std::set& samplePatchList); private: @@ -484,17 +483,17 @@ class Species { // genome parameters /**The traits table.*/ - map> spTraitTable; - set chromosomeEnds; + std::map> spTraitTable; + std::set chromosomeEnds; int genomeSize; bool diploid; bool mutationsOn; int numberOfNeutralLoci; int numberOfAdaptiveTraits; float recombinationRate; - set samplePatchList; + std::set samplePatchList; string nSampleCellsFst; //for cell based landscape - set stagesToSampleFrom; + std::set stagesToSampleFrom; string nIndsToSample; //could be integer or 'all', all means in in selected patches not necessarily all in population // emigration parameters @@ -569,7 +568,6 @@ class Species { float betaS[NSTAGES][NSEXES]; // inflection point of the settlement reaction norm to density // other attributes - int spNum; }; diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 7d5264a..6ce6354 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -1,6 +1,5 @@ #include "SpeciesTrait.h" -#include "Species.h" //could be handled in header file but here for now for flexibility SpeciesTrait::SpeciesTrait(vector parameters, Species* pSpecies) { @@ -53,6 +52,7 @@ TraitType SpeciesTrait::stringToTraitType(const std::string& str, sex_t sex) con else if (str == "kernel_probability") return KERNEL_PROBABILITY_M; else if (str == "crw_stepLength") return CRW_STEPLENGTH_M; else if (str == "crw_stepCorrelation") return CRW_STEPCORRELATION_M; + else throw logic_error(str + " is not a valid trait type."); } else { if (str == "emigration_d0") return E_D0_F; else if (str == "emigration_alpha") return E_ALPHA_F; @@ -71,6 +71,7 @@ TraitType SpeciesTrait::stringToTraitType(const std::string& str, sex_t sex) con else if (str == "sms_betaDB") return SMS_BETADB; else if (str == "neutral") return SNP; else if (str == "adaptive") return ADAPTIVE; + else throw logic_error(str + " is not a valid trait type."); } } @@ -79,6 +80,7 @@ ExpressionType SpeciesTrait::stringToExpressionType(const std::string& str) cons else if (str == "additive") return ADDITIVE; else if (str == "multiplicative") return MULTIPLICATIVE; else if (str == "#") return NEUTRAL; + else throw logic_error(str + " is not a valid gene expression type."); } DistributionType SpeciesTrait::stringToDistributionType(const std::string& str) const @@ -91,6 +93,7 @@ DistributionType SpeciesTrait::stringToDistributionType(const std::string& str) else if (str == "negExp") return NEGEXP; else if (str == "KAM") return KAM; else if (str == "SSM") return SSM; + else throw logic_error(str + " is not a valid distribution type."); } map SpeciesTrait::stringToParameterMap(string parameters) const { diff --git a/SpeciesTrait.h b/SpeciesTrait.h index 3894207..c31b21e 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -2,6 +2,8 @@ #define SPECIESTRAITH #include "Parameters.h" +#include "Species.h" + #include #include #include From 6ec8a760dd3c45126f4cb114e4cdddf02cfae8a1 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 12 Feb 2024 16:30:49 +0000 Subject: [PATCH 034/332] fix undefined function call --- Parameters.h | 2 -- SpeciesTrait.cpp | 55 ++++++++++++++++++++++++++++-------------------- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/Parameters.h b/Parameters.h index 23d8bda..dab5a56 100644 --- a/Parameters.h +++ b/Parameters.h @@ -159,9 +159,7 @@ typedef enum { KERNEL, SMS, CRW} movement_t; //GeneType convertToGeneType(const string& ); -float convertParameters(string, string); bool iequals(std::string_view lhs, std::string_view rhs); -set convertStringToSet(string); set convertStringToPatches(string, int, Landscape*); set convertStringToStages(string); set convertStringToChromosomeEnds(string, int); diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 6ce6354..9f02d2c 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -138,29 +138,38 @@ set SpeciesTrait::stringToLoci(string pos, string nLoci, Species* pSpecies) set positions; if (pos != "random") { - //stringstream ss(pos); - - //string value, valueWithin; - //while (std::getline(ss, value, ',')) { - // stringstream sss(value); - // vector minMax; - // while (std::getline(sss, valueWithin, '-')) { - // minMax.push_back(stoi(valueWithin)); - // } - // if (minMax[0] > pSpecies->getGenomeSize() || minMax[1] > pSpecies->getGenomeSize()) { - // cout << endl << "Traits file: ERROR - trait positions must not exceed genome size" << endl; - // } - // else { - // if (minMax.size() > 1) { - // for (int i = minMax[0]; i < minMax[1] + 1; ++i) { - // positions.insert(i); - // } - // } - // else - // positions.insert(minMax[0]); - // } - //} - positions = convertStringToSet(pos); + + // Parse comma-separated list from input string + stringstream ss(pos); + string value, valueWithin; + // Read comma-separated positions + while (std::getline(ss, value, ',')) { + stringstream sss(value); + vector positionRange; + // Read single positions and dash-separated ranges + while (std::getline(sss, valueWithin, '-')) { + positionRange.push_back(stoi(valueWithin)); + } + switch (positionRange.size()) + { + case 1: // single position + if (positionRange[0] > pSpecies->getGenomeSize()) + throw logic_error("Traits file: ERROR - trait positions must not exceed genome size"); + positions.insert(positionRange[0]); + break; + case 2: // dash-separated range + if (positionRange[0] > pSpecies->getGenomeSize() || positionRange[1] > pSpecies->getGenomeSize()) { + throw logic_error("Traits file: ERROR - trait positions must not exceed genome size"); + } + for (int i = positionRange[0]; i < positionRange[1] + 1; ++i) { + positions.insert(i); + } + break; + default: // zero or more than 2 values between commas: error + throw logic_error("Traits file: ERROR - incorrectly formatted position range."); + break; + } + } for (auto position : positions) { if (position > pSpecies->getGenomeSize()) From 3c7f1536262aee7939b866dbd3dfde60e266184a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 12 Feb 2024 16:37:37 +0000 Subject: [PATCH 035/332] define undefined stringToSex functiono --- Parameters.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Parameters.cpp b/Parameters.cpp index 9275e29..1f27f13 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -395,6 +395,12 @@ string paramSim::getDir(int option) { return s; } +const sex_t stringToSex(const std::string& str) { + if (str == "female") return FEM; + else if (str == "male") return MAL; + else throw logic_error("Traits file: ERROR - sex can either be 'female' or 'male'."); +} + #if RS_RCPP bool paramSim::getReturnPopRaster(void) { return ReturnPopRaster; } bool paramSim::getCreatePopFile(void) { return CreatePopFile; } From d8c910fa4914bbf3cf7f1b940cb9260984fcc97c Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 12 Feb 2024 17:54:11 +0000 Subject: [PATCH 036/332] add definition for undefined function convertStringToChromosomeEnds --- Parameters.cpp | 27 +++++++++++++++++++++++++++ Species.cpp | 4 ---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/Parameters.cpp b/Parameters.cpp index 1f27f13..2a0b114 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -401,6 +401,33 @@ const sex_t stringToSex(const std::string& str) { else throw logic_error("Traits file: ERROR - sex can either be 'female' or 'male'."); } +set convertStringToPatches(string str, int nb_patches, Landscape* pLandscape) { + +} + +set convertStringToChromosomeEnds(string str, int genomeSize) { + set chromosomeEnds; + if (str == "#") + chromosomeEnds.insert(genomeSize - 1); // last position in genome + else { + // Parse comma-separated list from input string + stringstream ss(str); + string strPos; + int pos; + // Read comma-separated positions + while (std::getline(ss, strPos, ',')) { + pos = std::stoi(strPos); + if (pos > genomeSize) + throw logic_error("Genetics file: ERROR - chromosome ends must not exceed genome size."); + else { + chromosomeEnds.insert(pos); + } + } + } + return chromosomeEnds; +} + + #if RS_RCPP bool paramSim::getReturnPopRaster(void) { return ReturnPopRaster; } bool paramSim::getCreatePopFile(void) { return CreatePopFile; } diff --git a/Species.cpp b/Species.cpp index a32c814..ca68b90 100644 --- a/Species.cpp +++ b/Species.cpp @@ -760,10 +760,6 @@ void Species::setGeneticParameters(const std::set& chromosomeEnds, const in const std::set& samplePatchList, const string nIndsToSample, const std::set& stagesToSampleFrom, string nSampleCellsFst) { this->genomeSize = genomeSize; - for (auto position : chromosomeEnds) { - if (position > this->getGenomeSize() - 1) - cout << endl << "Genetics file: ERROR - chromosome ends " << position << " must not exceed genome size" << endl; - } this->chromosomeEnds = chromosomeEnds; this->recombinationRate = recombinationRate; this->samplePatchList = samplePatchList; From 1641aff7eb853fcabbc54814c19de333adcbba7f Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 13 Feb 2024 11:42:39 +0000 Subject: [PATCH 037/332] defined missing functions convertStringToStages and convertStringToPatches --- Landscape.h | 1 + Parameters.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++++++-- Parameters.h | 8 +++--- 3 files changed, 69 insertions(+), 6 deletions(-) diff --git a/Landscape.h b/Landscape.h index cda6cee..4ef9231 100644 --- a/Landscape.h +++ b/Landscape.h @@ -234,6 +234,7 @@ class Landscape { void setCellArray(void); void addPatchNum(int); + std::vector getPatchNums() const { return patchnums; } void generatePatches(Species*); // create an artificial landscape void allocatePatches(Species*); // create patches for a cell-based landscape Patch* newPatch( diff --git a/Parameters.cpp b/Parameters.cpp index 2a0b114..4138822 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -401,8 +401,44 @@ const sex_t stringToSex(const std::string& str) { else throw logic_error("Traits file: ERROR - sex can either be 'female' or 'male'."); } -set convertStringToPatches(string str, int nb_patches, Landscape* pLandscape) { - +set convertStringToPatches(const string& str, const int& nb_rnd_patches, const vector& existingPatches) { + + set patches; + + if (str == "random") { + if (nb_rnd_patches > existingPatches.size()) { + throw logic_error("Genetics file: ERROR - Nb of patches to randomly sample exceeds nb of existing patches."); + } else { + // Sample without replacement + std::sample( + existingPatches.begin(), + existingPatches.end(), + patches.begin(), + nb_rnd_patches, + pRandom->getRNG() + ); + } + } else if (str == "all") { + // Copy all patches into sampled patches + for (int pch : existingPatches) patches.insert(pch); + } else { + // comma-separated list of patches + stringstream ss(str); + string strPch; + int pch; + bool patchExists; + // Read comma-separated values + while (std::getline(ss, strPch, ',')) { + pch = std::stoi(strPch); + patchExists = std::find(existingPatches.begin(), existingPatches.end(), pch) != existingPatches.end(); + if (!patchExists) + throw logic_error("Genetics file: ERROR - sampled patch does not exist."); + else { + patches.insert(pch); + } + } + } + return patches; } set convertStringToChromosomeEnds(string str, int genomeSize) { @@ -427,6 +463,32 @@ set convertStringToChromosomeEnds(string str, int genomeSize) { return chromosomeEnds; } +set convertStringToStages(const string& str, const int& nbStages) { + set stages; + if (str == "all") { + for (int stg = 0; stg < nbStages; ++stg) { + stages.insert(stg); + } + } + else { + // Parse comma-separated list from input string + stringstream ss(str); + string strStg; + int stg; + // Read comma-separated values + while (std::getline(ss, strStg, ',')) { + stg = std::stoi(strStg); + if (stg > nbStages - 1) + throw logic_error("Genetics file: ERROR - sampled stage exceeds number of stages."); + else { + stages.insert(stg); + } + } + } + return stages; +} + + #if RS_RCPP bool paramSim::getReturnPopRaster(void) { return ReturnPopRaster; } diff --git a/Parameters.h b/Parameters.h index dab5a56..01009a3 100644 --- a/Parameters.h +++ b/Parameters.h @@ -64,8 +64,6 @@ using namespace std; #include "RSrandom.h" -class Landscape; - #define NODATACOST 100000 // cost to use in place of nodata value for SMS; #define ABSNODATACOST 100 // cost to use in place of nodata value for SMS; // when boundaries are absorbing @@ -160,8 +158,8 @@ typedef enum { KERNEL, SMS, CRW} movement_t; //GeneType convertToGeneType(const string& ); bool iequals(std::string_view lhs, std::string_view rhs); -set convertStringToPatches(string, int, Landscape*); -set convertStringToStages(string); +set convertStringToPatches(const string&, const int&, const vector&); +set convertStringToStages(const string&, const int&); set convertStringToChromosomeEnds(string, int); //sex types @@ -449,5 +447,7 @@ extern ofstream DEBUGLOG; void DebugGUI(string); #endif +extern RSrandom* pRandom; + //--------------------------------------------------------------------------- #endif From fc7c3f4db4216c18c4c7c7650ad44f69d41ce106 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 13 Feb 2024 12:47:41 +0000 Subject: [PATCH 038/332] rm iequals() --- Parameters.h | 1 - SpeciesTrait.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Parameters.h b/Parameters.h index 01009a3..344f8ac 100644 --- a/Parameters.h +++ b/Parameters.h @@ -157,7 +157,6 @@ typedef enum { KERNEL, SMS, CRW} movement_t; //GeneType convertToGeneType(const string& ); -bool iequals(std::string_view lhs, std::string_view rhs); set convertStringToPatches(const string&, const int&, const vector&); set convertStringToStages(const string&, const int&); set convertStringToChromosomeEnds(string, int); diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 9f02d2c..aa56340 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -19,7 +19,7 @@ SpeciesTrait::SpeciesTrait(vector parameters, Species* pSpecies) { if (traitType == SNP || traitType == ADAPTIVE) this->inherited = true; else - this->inherited = iequals(parameters[10], "true") ? true : false; + this->inherited = (parameters[10] == "true") ? true : false; if (this->isInherited()) { this->mutationDistribution = stringToDistributionType(parameters[11]); From c7c95da1b421b838ffad54ab820d4bad73ad4e93 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 13 Feb 2024 13:38:32 +0000 Subject: [PATCH 039/332] fwd declaration to fix circular dependency issue --- Species.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Species.h b/Species.h index fc4a79c..bedfcb7 100644 --- a/Species.h +++ b/Species.h @@ -52,6 +52,8 @@ #include #include +class SpeciesTrait; + // structures for demographic parameters struct demogrParams { From ce60603783568ad0f2e3a625bc8bf61e9d416d25 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 13 Feb 2024 13:43:50 +0000 Subject: [PATCH 040/332] clarify chromosome switch; compiler mistakes it for bitwise operation --- GeneticLoad.cpp | 4 ++-- SNPTrait.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index 7e45c19..4fd5588 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -319,7 +319,7 @@ void GeneticLoad::inheritDiploid(sex_t whichChromosome, map nextBreakpoint) { std::advance(it, 1); nextBreakpoint = *it; - parentChromosome = !parentChromosome; // switch to the other one + parentChromosome = 1 - parentChromosome; // switch to the other one } if (locus <= nextBreakpoint) { diff --git a/SNPTrait.cpp b/SNPTrait.cpp index c144715..167cb84 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -199,7 +199,7 @@ void SNPTrait::inheritDiploid(sex_t whichChromosome, map nextBreakpoint) { std::advance(it, 1); nextBreakpoint = *it; - parentChromosome = !parentChromosome; //switch chromosome + parentChromosome = 1 - parentChromosome; //switch chromosome } if (locus <= nextBreakpoint) { From d6aba0df44dc6ba1bb30586a98fbaa362fad5fbb Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 13 Feb 2024 14:06:41 +0000 Subject: [PATCH 041/332] fix set iterators --- Parameters.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Parameters.cpp b/Parameters.cpp index 4138822..6e25de6 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -413,14 +413,17 @@ set convertStringToPatches(const string& str, const int& nb_rnd_patches, co std::sample( existingPatches.begin(), existingPatches.end(), - patches.begin(), - nb_rnd_patches, + std::inserter(patches, patches.end()), + nb_rnd_patches, pRandom->getRNG() ); } } else if (str == "all") { // Copy all patches into sampled patches - for (int pch : existingPatches) patches.insert(pch); + std::copy(existingPatches.begin(), + existingPatches.end(), + std::inserter(patches, patches.end()) + ); } else { // comma-separated list of patches stringstream ss(str); From bf735ccb3a59cd02601c1131769edb45334d9c6f Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 13 Feb 2024 15:26:55 +0000 Subject: [PATCH 042/332] fix a bunch of warnings and messages --- Allele.h | 2 +- GeneticLoad.cpp | 68 ++++++++++++++++++++--------------------- Individual.h | 6 ++-- NeutralStatsManager.cpp | 14 ++++----- Population.cpp | 6 ++-- QTLTrait.cpp | 36 +++++++++++----------- SNPTrait.cpp | 7 ++--- Species.cpp | 2 +- SpeciesTrait.cpp | 2 +- SpeciesTrait.h | 2 +- SubCommunity.cpp | 3 -- 11 files changed, 72 insertions(+), 76 deletions(-) diff --git a/Allele.h b/Allele.h index 7f8a0a8..1b00706 100644 --- a/Allele.h +++ b/Allele.h @@ -11,6 +11,6 @@ class Allele { ~Allele() {} float getAlleleValue() const { return value; }; float getDominanceCoef() const { return dominance; }; - float getId() const { return id; } + int getId() const { return id; } }; #endif \ No newline at end of file diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index 4fd5588..b467c9a 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -21,39 +21,39 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) switch (mutationDistribution) { case UNIFORM: { - if (!mutationParameters.count(MAX)) - cout << endl << ("Error:: adaptive mutation uniform distribution parameter must contain max value (e.g. max= ) \n"); + if (mutationParameters.count(MAX) != 1) + cout << endl << ("Error:: adaptive mutation uniform distribution parameter must contain one max value (e.g. max= ) \n"); - if (!mutationParameters.count(MIN)) - cout << endl << ("Error:: adaptive mutation uniform distribution parameter must contain min value (e.g. min= ) \n"); + if (mutationParameters.count(MIN) != 1) + cout << endl << ("Error:: adaptive mutation uniform distribution parameter must contain one min value (e.g. min= ) \n"); break; } case NORMAL: { - if (!mutationParameters.count(MEAN)) - cout << endl << ("Error:: adaptive mutation distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); + if (mutationParameters.count(MEAN) != 1) + cout << endl << ("Error:: adaptive mutation distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); - if (!mutationParameters.count(SDEV)) - cout << endl << ("Error:: adaptive mutation distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); + if (mutationParameters.count(SDEV) != 1) + cout << endl << ("Error:: adaptive mutation distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); break; } case GAMMA: { - if (!mutationParameters.count(SHAPE)) - cout << endl << ("Error:: adaptive mutation distribution set to gamma so parameters must contain shape value (e.g. shape= ) \n"); + if (mutationParameters.count(SHAPE) != 1) + cout << endl << ("Error:: adaptive mutation distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); - if (!mutationParameters.count(SCALE)) - cout << endl << ("Error:: adaptive mutation distribution set to gamma so parameters must contain scale value (e.g. scale= ) \n"); + if (mutationParameters.count(SCALE) != 1) + cout << endl << ("Error:: adaptive mutation distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); break; } case NEGEXP: { - if (!mutationParameters.count(MEAN)) - cout << endl << ("Error:: adaptive mutation distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); + if (mutationParameters.count(MEAN) != 1) + cout << endl << ("Error:: adaptive mutation distribution set to negative exponential (negative decay) so parameters must contain one mean value (e.g. mean= ) \n"); break; } @@ -70,38 +70,38 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) switch (dominanceDistribution) { case UNIFORM: { - if (!dominanceParameters.count(MAX)) - cout << endl << ("Error:: adaptive dominance uniform distribution parameter must contain max value (e.g. max= ) \n"); + if (dominanceParameters.count(MAX) != 1) + cout << endl << ("Error:: adaptive dominance uniform distribution parameter must contain one max value (e.g. max= ) \n"); - if (!dominanceParameters.count(MIN)) - cout << endl << ("Error:: adaptive dominance uniform distribution parameter must contain min value (e.g. min= ) \n"); + if (dominanceParameters.count(MIN) != 1) + cout << endl << ("Error:: adaptive dominance uniform distribution parameter must contain one min value (e.g. min= ) \n"); break; } case NORMAL: { - if (!dominanceParameters.count(MEAN)) - cout << endl << ("Error:: adaptive dominance distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); + if (dominanceParameters.count(MEAN) != 1) + cout << endl << ("Error:: adaptive dominance distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); - if (!dominanceParameters.count(SDEV)) - cout << endl << ("Error:: adaptive dominance distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); + if (dominanceParameters.count(SDEV) != 1) + cout << endl << ("Error:: adaptive dominance distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); break; } case GAMMA: { - if (!dominanceParameters.count(SHAPE)) - cout << endl << ("Error:: adaptive dominance distribution set to gamma so parameters must contain shape value (e.g. shape= ) \n"); + if (dominanceParameters.count(SHAPE) != 1) + cout << endl << ("Error:: adaptive dominance distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); - if (!dominanceParameters.count(SCALE)) - cout << endl << ("Error:: adaptive dominance distribution set to gamma so parameters must contain scale value (e.g. scale= ) \n"); + if (dominanceParameters.count(SCALE) != 1) + cout << endl << ("Error:: adaptive dominance distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); break; } case NEGEXP: { - if (!dominanceParameters.count(MEAN)) + if (dominanceParameters.count(MEAN) != 1) cout << endl << ("Error:: adaptive dominance distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); break; @@ -363,8 +363,8 @@ float GeneticLoad::express() { for (auto const& [locus, pAllelePair] : genes) { - auto pAlleleLeft = (!pAllelePair[0]) ? wildType : pAllelePair[0]; - auto pAlleleRight = (!pAllelePair[1]) ? wildType : pAllelePair[1]; + shared_ptr pAlleleLeft = (!pAllelePair[0]) ? wildType : pAllelePair[0]; + shared_ptr pAlleleRight = (!pAllelePair[1]) ? wildType : pAllelePair[1]; if (pAlleleLeft.get()->getId() != pAlleleRight.get()->getId()) // heterozygote { @@ -391,9 +391,9 @@ bool GeneticLoad::isHeterozygoteAtLocus(int locus) const { if (it == genes.end()) //not found so must be wildtype homozygous return false; else { - auto a = (!it->second[0]) ? wildType : it->second[0]; - auto b = (!it->second[1]) ? wildType : it->second[1]; - return a != b; + shared_ptr alleleRight = (!it->second[0]) ? wildType : it->second[0]; + shared_ptr alleleLeft = (!it->second[1]) ? wildType : it->second[1]; + return alleleRight != alleleLeft; } } @@ -407,8 +407,8 @@ int GeneticLoad::countHeterozygoteLoci() const { int count = 0; for (auto const& [locus, allelePair] : genes) { - auto alleleLeft = (!allelePair[0]) ? wildType : allelePair[0]; - auto alleleRight = (!allelePair[1]) ? wildType : allelePair[1]; + shared_ptr alleleLeft = (!allelePair[0]) ? wildType : allelePair[0]; + shared_ptr alleleRight = (!allelePair[1]) ? wildType : allelePair[1]; count += alleleLeft != alleleRight; } return count; diff --git a/Individual.h b/Individual.h index 2245c1a..71d986a 100644 --- a/Individual.h +++ b/Individual.h @@ -123,7 +123,7 @@ struct crwData : trfrData { // to hold data for CRW movement model void clone(const trfrData& copyFrom) { - auto pCopy = dynamic_cast(copyFrom); + const crwData& pCopy = dynamic_cast(copyFrom); stepLength = pCopy.stepLength; rho = pCopy.rho; @@ -154,7 +154,7 @@ struct smsData : trfrData { //static float stepMort; //static bool straigtenPath; - smsData(locn prevA, locn goalA) : prev(prevA), goal(goalA), dp(0.0), gb(0.0), alphaDB(0.0), betaDB(0.0) {} + smsData(locn prevA, locn goalA) : prev(prevA), goal(goalA), dp(0.0), gb(0.0), alphaDB(0.0), betaDB(0) {} ~smsData() {} @@ -206,7 +206,7 @@ struct kernelData : trfrData { movement_t getType() { return KERNEL; } void clone(const trfrData& copyFrom) { - auto pCopy = dynamic_cast(copyFrom); + const kernelData& pCopy = dynamic_cast(copyFrom); meanDist1 = pCopy.meanDist1; meanDist2 = pCopy.meanDist2; probKern1 = pCopy.probKern1; diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index de578c5..3c0b15a 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -29,7 +29,7 @@ // ---------------------------------------------------------------------------------------- NeutralStatsManager::NeutralStatsManager(set const& patchList, const int nLoci) { - this->_fst_matrix = PatchMatrix(patchList.size(), patchList.size()); + this->_fst_matrix = PatchMatrix(static_cast(patchList.size()), static_cast(patchList.size())); globalAlleleTable.reserve(nLoci); //don't have to be pointers, not shared or moved } @@ -282,17 +282,17 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int int patchSize = pPop->sampleSize(); if (patchSize) { extantPs++; - sum_weights += (patchSize * patchSize / nInds); + sum_weights += (patchSize * patchSize / static_cast(nInds)); } } _n_extantPopulations = extantPs; _n_individuals = nInds; - n_bar = nInds / extantPs; + n_bar = nInds / static_cast(extantPs); n_c = (nInds - sum_weights) / (extantPs - 1); - inverse_n_bar = 1 / (n_bar - 1); - inverse_n_total = 1 / nInds; + inverse_n_bar = 1.0 / (n_bar - 1); + inverse_n_total = 1.0 / nInds; double var; double s2, p_bar, h_bar; @@ -359,7 +359,7 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i int patchSize = pPop->sampleSize(); if (patchSize) { extantPs++; - sum_weights += (patchSize * patchSize / nInds); + sum_weights += (patchSize * patchSize / static_cast(nInds)); } } @@ -550,7 +550,7 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd copy(patchList.begin(), patchList.end(), std::back_inserter(patchVect)); //needs to be in vector to iterate over, copy preserves order - int nPatches = patchList.size(); + int nPatches = static_cast(patchList.size()); //initialise diff --git a/Population.cpp b/Population.cpp index 199e3c6..4615951 100644 --- a/Population.cpp +++ b/Population.cpp @@ -378,7 +378,7 @@ void Population::updateAlleleTable() { std::for_each(alleleTable.begin(), alleleTable.end(), [&](NeutralData& v) -> void { - v.setFrequencies(sampledInds.size() * 2); + v.setFrequencies(static_cast(sampledInds.size()) * 2); //v->divideHeteros(sampledInds.size()); //weir and cockerham doesn't need this division?? }); } @@ -926,7 +926,7 @@ void Population::fledge(void) } Individual* Population::sampleInd() const { - int index = pRandom->IRandom(0, inds.size() - 1); + int index = pRandom->IRandom(0, static_cast(inds.size() - 1)); return inds[index]; } @@ -953,7 +953,7 @@ void Population::sampleIndsWithoutReplacement(string n, const set& sampleSt } int Population::sampleSize() const { - return sampledInds.size(); + return static_cast(sampledInds.size()); } set Population::getIndividualsInStage(int stage) { diff --git a/QTLTrait.cpp b/QTLTrait.cpp index 6c9d451..1b38fee 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -20,10 +20,10 @@ QTLTrait::QTLTrait(SpeciesTrait* P) switch (mutationDistribution) { case UNIFORM: { - if (!mutationParameters.count(MAX)) + if (mutationParameters.count(MAX) != 1) cout << endl << ("Error:: mutation uniform qtl distribution parameter must contain max value (e.g. max= ) \n"); - if (!mutationParameters.count(MIN)) + if (mutationParameters.count(MIN) != 1) cout << endl << ("Error:: mutation uniform qtl distribution parameter must contain min value (e.g. min= ) \n"); _mutate_func_ptr = &QTLTrait::mutateUniform; @@ -31,10 +31,10 @@ QTLTrait::QTLTrait(SpeciesTrait* P) } case NORMAL: { - if (!mutationParameters.count(MEAN)) + if (mutationParameters.count(MEAN) != 1) cout << endl << ("Error:: qtl mutation distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); - if (!mutationParameters.count(SDEV)) + if (mutationParameters.count(SDEV) != 1) cout << endl << ("Error::qtl mutation distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); _mutate_func_ptr = &QTLTrait::mutateNormal; @@ -55,10 +55,10 @@ QTLTrait::QTLTrait(SpeciesTrait* P) switch (initialDistribution) { case UNIFORM: { - if (!initialParameters.count(MAX)) + if (initialParameters.count(MAX) != 1) cout << endl << ("Error:: initial uniform qtl distribution parameter must contain max value (e.g. max= ) \n"); - if (!initialParameters.count(MIN)) + if (initialParameters.count(MIN) != 1) cout << endl << ("Error:: initial uniform qtl distribution parameter must contain min value (e.g. min= ) \n"); float maxD = initialParameters.find(MAX)->second; @@ -69,10 +69,10 @@ QTLTrait::QTLTrait(SpeciesTrait* P) } case NORMAL: { - if (!initialParameters.count(MEAN)) + if (initialParameters.count(MEAN) != 1) cout << endl << ("Error:: initial normal qtl distribution parameter must contain mean value (e.g. mean= ) \n"); - if (!initialParameters.count(SDEV)) + if (initialParameters.count(SDEV) != 1) cout << endl << ("Error:: initial normal qtl distribution parameter must contain sdev value (e.g. sdev= ) \n"); float mean = initialParameters.find(MEAN)->second; @@ -209,18 +209,18 @@ void QTLTrait::inheritDiploid(sex_t whichChromosome, mapfirst); - unsigned int nextBreakpoint = *it; + int nextBreakpoint = *it; auto distance = std::distance(recomPositions.begin(), it); if (distance % 2 != 0) - parentChromosome = !parentChromosome; //switch chromosome + parentChromosome = 1 - parentChromosome; //switch chromosome for (auto const& [locus, allelePair] : parentGenes) { while (locus > nextBreakpoint) { std::advance(it, 1); nextBreakpoint = *it; - parentChromosome = !parentChromosome; //switch chromosome + parentChromosome = 1 - parentChromosome; //switch chromosome } if (locus <= nextBreakpoint) { @@ -258,10 +258,10 @@ void QTLTrait::inheritInitialParameters(sex_t whichChromosome, mapsecond; @@ -273,10 +273,10 @@ void QTLTrait::inheritInitialParameters(sex_t whichChromosome, mapsecond; @@ -303,7 +303,7 @@ void QTLTrait::inheritInitialParameters(sex_t whichChromosome, mapgetPositions(); + const set positions = pSpeciesTrait->getPositions(); short ploidy = pSpeciesTrait->getPloidy(); for (auto position : positions) { @@ -318,7 +318,7 @@ void QTLTrait::initialiseNormal(float mean, float sd) { void QTLTrait::initialiseUniform(float min, float max) { - const auto positions = pSpeciesTrait->getPositions(); + const set positions = pSpeciesTrait->getPositions(); short ploidy = pSpeciesTrait->getPloidy(); for (auto position : positions) { @@ -341,7 +341,7 @@ float QTLTrait::expressAdditive() { for (auto const& [locus, allelePair] : genes) { - for (auto m : allelePair) + for (const std::shared_ptr m : allelePair) phenotype += m->getAlleleValue(); } return phenotype; diff --git a/SNPTrait.cpp b/SNPTrait.cpp index 167cb84..102d9cf 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -21,7 +21,7 @@ SNPTrait::SNPTrait(SpeciesTrait* P) if (mutationDistribution != SSM && mutationDistribution != KAM) cout << endl << ("Error:: wrong mutation distribution for neutral markers, must be KAM or SSM \n"); - if (!mutationParameters.count(MAX)) + if (mutationParameters.count(MAX) != 1) cout << endl << ("Error:: KAM or SSM mutation distribution parameter must contain max value (e.g. max= ), max cannot exceed 256 \n"); if (wildType == -999) @@ -39,8 +39,8 @@ SNPTrait::SNPTrait(SpeciesTrait* P) switch (initialDistribution) { case UNIFORM: { - if (!initialParameters.count(MAX)) - cout << endl << "Error:: initial SNP/Microsat distribution parameter must contain max value if set to UNIFORM (e.g. max= ), max cannot exceed " << maxSNPAlleles << "\n"; + if (initialParameters.count(MAX) != 1) + cout << endl << "Error:: initial SNP/Microsat distribution parameter must contain one max value if set to UNIFORM (e.g. max= ), max cannot exceed " << maxSNPAlleles << "\n"; float maxD = initialParameters.find(MAX)->second; if (maxD > maxSNPAlleles) { @@ -83,7 +83,6 @@ SNPTrait::SNPTrait(const SNPTrait& T) : // ---------------------------------------------------------------------------------------- void SNPTrait::mutate_KAM() { - const int positionsSize = pProtoTrait->getPositionsSize(); const auto& positions = pProtoTrait->getPositions(); const short ploidy = pProtoTrait->getPloidy(); diff --git a/Species.cpp b/Species.cpp index ca68b90..459c3d3 100644 --- a/Species.cpp +++ b/Species.cpp @@ -478,7 +478,7 @@ set Species::getTraitTypes() { } int Species::getNTraits() const { - return spTraitTable.size(); + return static_cast(spTraitTable.size()); } int Species::getNPositionsForTrait(const TraitType trait) const { diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index aa56340..f8c5d8a 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -34,7 +34,7 @@ SpeciesTrait::SpeciesTrait(vector parameters, Species* pSpecies) { if (pSpecies->getNumberOfNeutralLoci() > 0) cout << endl << "Traits file: WARNING - can only have one set of neutral markers, overwriting previous" << endl; - else pSpecies->setNumberOfNeutralLoci(positions.size()); + else pSpecies->setNumberOfNeutralLoci(static_cast(positions.size())); } } diff --git a/SpeciesTrait.h b/SpeciesTrait.h index c31b21e..9a634cb 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -36,7 +36,7 @@ class SpeciesTrait { float getMutationRate() const { return mutationRate; } short getPloidy() const { return ploidy; } set& getPositions() { return positions; } // returning by reference, make sure receiver is const - int getPositionsSize() const { return positions.size(); } + int getPositionsSize() const { return static_cast(positions.size()); } bool isInherited() const { return inherited; } DistributionType getMutationDistribution() const { return mutationDistribution; }; map getMutationParameters() const { return mutationParameters; }; diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 67dbebf..5164444 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -1111,9 +1111,6 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, } // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT -// ngenes = 1; - double mnS0[2], mnAlpha[2], mnBeta[2], sdS0[2], sdAlpha[2], sdBeta[2]; - if (writefile) outtraits << endl; for (int s = 0; s < NSEXES; s++) { From ab4dc2cb0b2d165d439415271d01d798ae72afea Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 13 Feb 2024 16:14:41 +0000 Subject: [PATCH 043/332] more warnings and messages fixes --- Community.cpp | 17 +++++++++-------- GeneticLoad.cpp | 18 +++++++++--------- Population.cpp | 20 ++++++++++++-------- Population.h | 1 - 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/Community.cpp b/Community.cpp index 38d991b..a8f7673 100644 --- a/Community.cpp +++ b/Community.cpp @@ -64,7 +64,7 @@ void Community::initialise(Species* pSpecies, int year) int nsubcomms, npatches, ndistcells, spratio, patchnum, rr = 0; locn distloc; patchData pch; - patchLimits limits; + patchLimits limits = patchLimits(); intptr ppatch, subcomm; std::vector subcomms; std::vector selected; @@ -257,7 +257,8 @@ void Community::initialise(Species* pSpecies, int year) indIx = 0; // reset index for initial individuals } else { // add any initial individuals for the current year - initInd iind; iind.year = 0; + initInd iind = initInd(); + iind.year = 0; int ninds = paramsInit->numInitInds(); while (indIx < ninds && iind.year <= year) { iind = paramsInit->getInitInd(indIx); @@ -505,7 +506,7 @@ void Community::dispersal(short landIx) #endif // SEASONAL || RS_RCPP { #if RSDEBUG - int t0, t1, t2; + time_t t0, t1, t2; t0 = time(0); #endif @@ -631,7 +632,7 @@ void Community::deleteOccupancy(int nrows) { // Determine range margins commStats Community::getStats(void) { - commStats s; + commStats s = commStats(); landParams ppLand = pLandscape->getLandParams(); s.ninds = s.nnonjuvs = s.suitable = s.occupied = 0; s.minX = ppLand.maxX; s.minY = ppLand.maxY; s.maxX = s.maxY = 0; @@ -883,9 +884,9 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) outrange << "\t0\t0\t0\t0"; if (emig.indVar || trfr.indVar || sett.indVar) { // output trait means - traitsums ts; + traitsums ts = traitsums(); traitsums scts; // sub-community traits - traitCanvas tcanv; + traitCanvas tcanv = traitCanvas(); int ngenes, popsize; tcanv.pcanvas[0] = NULL; @@ -1889,8 +1890,8 @@ void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); int popSize = pPop->sampleSize(); int het = 0; - for (unsigned int a = 0; a < nAlleles; ++a) { - het += pPop->getHetero(thisLocus, a); + for (int a = 0; a < nAlleles; ++a) { + het += static_cast(pPop->getHetero(thisLocus, a)); // not sure why this returns a double } outperlocusfstat << "\t" << het / (2.0 * popSize); } diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index b467c9a..aa93e8d 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -211,27 +211,27 @@ float GeneticLoad::drawDominance(float selCoef) { { const float mean = dominanceParameters.find(MEAN)->second; const float sd = dominanceParameters.find(SDEV)->second; - h = pRandom->Normal(mean, sd); + h = static_cast(pRandom->Normal(mean, sd)); break; } case GAMMA: { const float shape = dominanceParameters.find(SHAPE)->second; const float scale = dominanceParameters.find(SCALE)->second; - h = pRandom->Gamma(shape, scale); + h = static_cast(pRandom->Gamma(shape, scale)); break; } case NEGEXP: { const float mean = dominanceParameters.find(MEAN)->second; - h = pRandom->NegExp(mean); + h = static_cast(pRandom->NegExp(mean)); break; } case SCALED: { const float min = 0; - const float max = exp((-log(2 * 0.36) / 0.05) * selCoef); - h = pRandom->FRandom(min, max); + const float max = static_cast(exp((-log(2 * 0.36) / 0.05) * selCoef)); + h = static_cast(pRandom->FRandom(min, max)); break; } @@ -270,7 +270,7 @@ float GeneticLoad::drawSelectionCoef() { { const float mean = mutationParameters.find(MEAN)->second; const float sd = mutationParameters.find(SDEV)->second; - s = pRandom->Normal(mean, sd); + s = static_cast(pRandom->Normal(mean, sd)); break; } @@ -278,13 +278,13 @@ float GeneticLoad::drawSelectionCoef() { { const float shape = mutationParameters.find(SHAPE)->second; const float scale = mutationParameters.find(SCALE)->second; - s = pRandom->Gamma(shape, scale); + s = static_cast(pRandom->Gamma(shape, scale)); break; } case NEGEXP: { const float mean = mutationParameters.find(MEAN)->second; - s = pRandom->NegExp(mean); + s = static_cast(pRandom->NegExp(mean)); break; } default: @@ -315,7 +315,7 @@ void GeneticLoad::inheritDiploid(sex_t whichChromosome, mapfirst); - unsigned int nextBreakpoint = *it; + int nextBreakpoint = *it; auto distance = std::distance(recomPositions.begin(), it); if (distance % 2 != 0) diff --git a/Population.cpp b/Population.cpp index 4615951..aec1141 100644 --- a/Population.cpp +++ b/Population.cpp @@ -56,7 +56,7 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) pSpecies = pSp; pPatch = pPch; // record the new population in the patch - patchPopn pp; + patchPopn pp = patchPopn(); pp.pSp = (intptr)pSpecies; pp.pPop = (intptr)this; pPatch->addPopn(pp); #if RSDEBUG @@ -229,7 +229,7 @@ Population::~Population(void) { traitsums Population::getTraits(Species* pSpecies) { int g; - traitsums ts; + traitsums ts = traitsums(); for (int i = 0; i < NSEXES; i++) { ts.ninds[i] = 0; ts.sumD0[i] = ts.ssqD0[i] = 0.0; @@ -456,10 +456,10 @@ double Population::computeHs() { popStats Population::getStats(void) { - popStats p; + popStats p = popStats(); int ninds; float fec; - bool breeders[2]; breeders[0] = breeders[1] = false; + bool breeders[2] = { false, false }; demogrParams dem = pSpecies->getDemogr(); p.pSpecies = pSpecies; p.pPatch = pPatch; @@ -1147,7 +1147,7 @@ void Population::allEmigrate(void) { // If an Individual has been identified as an emigrant, remove it from the Population disperser Population::extractDisperser(int ix) { - disperser d; + disperser d = disperser(); indStats ind = inds[ix]->getStats(); if (ind.status == 1) { // emigrant d.pInd = inds[ix]; d.yes = true; @@ -1190,7 +1190,7 @@ void Population::addSettleTraitsForInd(int ix, settleTraits& avgSettleTraits) { // if it is a settler, return its new location and remove it from the current population // otherwise, leave it in the matrix population for possible reporting before deletion disperser Population::extractSettler(int ix) { - disperser d; + disperser d = disperser(); Cell* pCell; //Patch* pPatch; @@ -1232,7 +1232,8 @@ int Population::transfer(Landscape* pLandscape, short landIx) Cell* pCell = 0; indStats ind; Population* pNewPopn = 0; - locn newloc, nbrloc; + locn newloc = locn(); + locn nbrloc = locn(); landData ppLand = pLandscape->getLandData(); short reptype = pSpecies->getRepType(); @@ -1716,6 +1717,9 @@ void Population::survival0(float localK, short option0, short option1) if ((ind.stage == 0 && option0 < 2) || (ind.stage > 0 && option0 > 0)) { // condition for processing the stage is met... if (ind.status < 6) { // not already doomed + if (ind.sex < sex_t::FEM || ind.sex > sex_t::MAL) + // ?? MSVC believes it's important to bound check ind.sex + throw runtime_error("Individual sex is out of bounds"); double probsurv = surv[ind.stage][ind.sex]; // does the individual survive? if (pRandom->Bernoulli(probsurv)) { // survives @@ -2129,7 +2133,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, outInds << "\t" << ind.status; } pCell = inds[i]->getLocn(1); - locn loc; + locn loc = locn(); if (pCell == 0) loc.x = loc.y = -1; // beyond boundary or in no-data cell else loc = pCell->getLocn(); pCell = inds[i]->getLocn(0); diff --git a/Population.h b/Population.h index 3c7d438..dae449a 100644 --- a/Population.h +++ b/Population.h @@ -235,7 +235,6 @@ class Population { int countHeterozygoteLoci(); vector countLociHeterozyotes(); double computeHs(); - void updateHeteroTable(); private: short nStages; From df3563b2254756b7329dfc8c2db10c7cbb1291ab Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 13 Feb 2024 16:31:40 +0000 Subject: [PATCH 044/332] trigger cmakelist change --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d8fe69f..c0bfd0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,4 +27,4 @@ endif() if(NOT batchmode) target_include_directories(RScore PUBLIC "${PROJECT_BINARY_DIR}") -endif() \ No newline at end of file +endif() From f52000a72fbe727e303700c825c6b368f729d830 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 14 Feb 2024 13:30:09 +0000 Subject: [PATCH 045/332] rm fionaOptions --- Community.cpp | 49 ++---------------------------------------- Community.h | 7 +----- Model.cpp | 19 +---------------- Parameters.cpp | 6 ------ Parameters.h | 4 ---- Population.cpp | 50 ++++++------------------------------------- Population.h | 6 +----- Species.cpp | 4 ---- Species.h | 1 - SubCommunity.cpp | 55 ++---------------------------------------------- SubCommunity.h | 6 +----- 11 files changed, 15 insertions(+), 192 deletions(-) diff --git a/Community.cpp b/Community.cpp index a8f7673..7abb597 100644 --- a/Community.cpp +++ b/Community.cpp @@ -39,7 +39,6 @@ ofstream outpairwisefst; Community::Community(Landscape* pLand) { pLandscape = pLand; indIx = 0; - pColdStorage = 0; pNeutralStatistics = 0; } @@ -49,7 +48,6 @@ Community::~Community(void) { delete subComms[i]; } subComms.clear(); - delete pColdStorage; } SubCommunity* Community::addSubComm(Patch* pPch, int num) { @@ -60,7 +58,6 @@ SubCommunity* Community::addSubComm(Patch* pPch, int num) { void Community::initialise(Species* pSpecies, int year) { - int nsubcomms, npatches, ndistcells, spratio, patchnum, rr = 0; locn distloc; patchData pch; @@ -74,11 +71,6 @@ void Community::initialise(Species* pSpecies, int year) landParams ppLand = pLandscape->getLandParams(); initParams init = paramsInit->getInit(); - if (pColdStorage != 0) - delete pColdStorage; - - pColdStorage = new Population(); - nsubcomms = (int)subComms.size(); spratio = ppLand.spResol / ppLand.resol; @@ -423,44 +415,7 @@ void Community::patchChanges(void) { } } -void Community::addIndividualsToColdStorage() { - int nsubcomms = (int)subComms.size(); - for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->copyIndividualsForColdStorage(pColdStorage); - } -} - -void Community::createAverageTraitIndividualAndStore(Species* pSpecies, Landscape* pLandscape) { - int nsubcomms = (int)subComms.size(); - int totalInds = 0; - Patch* pPatch = pLandscape->getPatchData(0).pPatch; - Cell* pCell = pPatch->getRandomCell(); - Individual* avgInd = new Individual(pCell, pPatch, 0, 0, 0, pSpecies->getDemogr().propMales, true, pSpecies->getTrfr().moveType); - - emigTraits avgEmigTraits = emigTraits(); - settleTraits avgSettleTraits = settleTraits(); - - - for (int i = 0; i < nsubcomms; i++) { // all sub-communities - - totalInds += subComms[i]->addEmigrationAndSettlementTraitValues(avgEmigTraits, avgSettleTraits); - subComms[i]->addTransferDataForInd(avgInd->getTrfrData()); - - - } - //divide to get the mean - avgInd->getTrfrData()->divideTraitsBy(totalInds); - avgEmigTraits.divideTraitsBy(totalInds); - avgSettleTraits.divideTraitsBy(totalInds); - - avgInd->setEmigTraits(avgEmigTraits); - avgInd->setSettleTraits(avgSettleTraits); - - pColdStorage->recruit(avgInd); - -} - -void Community::reproduction(int yr, bool cloneFromColdStorage) +void Community::reproduction(int yr) { float eps = 0.0; // epsilon for environmental stochasticity landParams land = pLandscape->getLandParams(); @@ -477,7 +432,7 @@ void Community::reproduction(int yr, bool cloneFromColdStorage) eps = pLandscape->getGlobalStoch(yr); } } - subComms[i]->reproduction(land.resol, eps, land.rasterType, land.patchModel, cloneFromColdStorage, pColdStorage); + subComms[i]->reproduction(land.resol, eps, land.rasterType, land.patchModel); } #if RSDEBUG DEBUGLOG << "Community::reproduction(): finished" << endl; diff --git a/Community.h b/Community.h index 0c5d3e4..2d1b695 100644 --- a/Community.h +++ b/Community.h @@ -79,14 +79,11 @@ class Community { int // year (relevent only for seedType == 2) ); void addManuallySelected(void); - void addIndividualsToColdStorage(void); - void createAverageTraitIndividualAndStore(Species* pSpecies, Landscape* pLandscape); void resetPopns(void); void localExtinction(int); void patchChanges(void); void reproduction( - int, // year - bool + int // year ); void emigration(void); #if RS_RCPP // included also SEASONAL @@ -223,7 +220,6 @@ class Community { void writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList); void writePairwiseFSTFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList); - private: Landscape* pLandscape; int indIx; // index used to apply initial individuals @@ -231,7 +227,6 @@ class Community { std::vector subComms; //below won't work for multispecies - Population* pColdStorage; unique_ptr pNeutralStatistics; }; diff --git a/Model.cpp b/Model.cpp index 2d68cd5..690aeea 100644 --- a/Model.cpp +++ b/Model.cpp @@ -295,7 +295,6 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->initialise(pSpecies, -1); // } bool updateland = false; - bool cloneFromColdStorage = false; int landIx = 0; // landscape change index #if RSDEBUG @@ -402,22 +401,6 @@ int RunModel(Landscape* pLandscape, int seqsim) } } } - - if (yr == sim.storeIndsYr) { //implement after first change only - - if (sim.fionaOptions == 1) - pSpecies->turnOffMutations(); - - if (sim.fionaOptions == 2) { - pComm->addIndividualsToColdStorage(); - cloneFromColdStorage = true; - } - - if (sim.fionaOptions == 3) { - pComm->createAverageTraitIndividualAndStore(pSpecies, pLandscape); - cloneFromColdStorage = true; - } - } // environmental gradient, stochasticity & local extinction // or dynamic landscape updateland = false; @@ -592,7 +575,7 @@ int RunModel(Landscape* pLandscape, int seqsim) } // reproduction - pComm->reproduction(yr, cloneFromColdStorage); + pComm->reproduction(yr); if (dem.stageStruct) { if (sstruct.survival == 0) { // at reproduction diff --git a/Parameters.cpp b/Parameters.cpp index 6e25de6..7dad8f9 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -239,8 +239,6 @@ paramSim::paramSim(void) { outPaths = false; ReturnPopRaster = false; CreatePopFile = true; #endif drawLoaded = false; - fionaOptions = 0.0; - storeIndsYr = -9999; fixReplicateSeed = false; viewLand = false; viewPatch = false; viewGrad = false; viewCosts = false; viewPop = false; viewTraits = false; viewPaths = false; viewGraph = false; @@ -285,8 +283,6 @@ void paramSim::setSim(simParams s) { CreatePopFile = s.CreatePopFile; #endif drawLoaded = s.drawLoaded; - fionaOptions = s.fionaOptions; - storeIndsYr = s.storeIndsYr; fixReplicateSeed = s.fixReplicateSeed; } @@ -327,8 +323,6 @@ simParams paramSim::getSim(void) { s.CreatePopFile = CreatePopFile; #endif s.drawLoaded = drawLoaded; - s.fionaOptions = fionaOptions; - s.storeIndsYr = storeIndsYr; s.outputWCFstat = outputWCFstat; s.outputPerLocusWCFstat = outputPerLocusWCFstat; s.outputPairwiseFst = outputPairwiseFst; diff --git a/Parameters.h b/Parameters.h index 344f8ac..ab03949 100644 --- a/Parameters.h +++ b/Parameters.h @@ -348,8 +348,6 @@ struct simParams { int outStartPaths; int outIntPaths; bool outPaths; bool ReturnPopRaster; bool CreatePopFile; #endif - int fionaOptions; - int storeIndsYr; bool fixReplicateSeed; bool outputWCFstat, outputPerLocusWCFstat, outputPairwiseFst; int outputGeneticInterval; @@ -432,8 +430,6 @@ class paramSim { bool viewGraph; // view population/occupancy graph on screen? string dir; // full name of working directory - int fionaOptions; - int storeIndsYr; bool fixReplicateSeed; bool outputWCFstat; bool outputPerLocusWCFstat; diff --git a/Population.cpp b/Population.cpp index aec1141..7d227f8 100644 --- a/Population.cpp +++ b/Population.cpp @@ -554,8 +554,7 @@ void Population::extirpate(void) { //--------------------------------------------------------------------------- // Produce juveniles and hold them in the juvs vector -void Population::reproduction(const float localK, const float envval, const int resol, bool cloneFromColdStorage, - Population* pColdStorage) +void Population::reproduction(const float localK, const float envval, const int resol) { // get population size at start of reproduction @@ -743,17 +742,12 @@ void Population::reproduction(const float localK, const float envval, const int for (int j = 0; j < njuvs; j++) { Individual* newJuv; - if (cloneFromColdStorage) { - newJuv = pColdStorage->sampleInd()->traitClone(pCell, pPatch, dem.propMales, trfr.moveModel, trfr.moveType); - } - else { #if RSDEBUG - // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... - newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, true, trfr.moveType); + // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... + newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, true, trfr.moveType); #else - newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.moveModel, trfr.moveType); + newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.moveModel, trfr.moveType); #endif - } if (pSpecies->getNTraits() > 0) { newJuv->inheritTraits(pSpecies, inds[i], father, resol); @@ -858,17 +852,12 @@ void Population::reproduction(const float localK, const float envval, const int for (int j = 0; j < njuvs; j++) { Individual* newJuv; - if (cloneFromColdStorage) { - newJuv = pColdStorage->sampleInd()->traitClone(pCell, pPatch, dem.propMales, trfr.moveModel, trfr.moveType); - } - else { #if RSDEBUG - // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... - newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, true, trfr.moveType); + // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... + newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, true, trfr.moveType); #else - newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.moveModel, trfr.moveType); + newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.moveModel, trfr.moveType); #endif - } if (pSpecies->getNTraits() > 0) { newJuv->inheritTraits(pSpecies, inds[i], father, resol); } @@ -1160,31 +1149,6 @@ disperser Population::extractDisperser(int ix) { return d; } -Individual* Population::copyForColdStorage(int ix) { - demogrParams dem = pSpecies->getDemogr(); - trfrRules trfr = pSpecies->getTrfr(); - Individual* ind = inds[ix]; - Individual* clone = ind->traitClone(pPatch->getRandomCell(), pPatch, dem.propMales, trfr.moveModel, trfr.moveType); - return clone; -} - -void Population::addEmigTraitsForInd(int ix, emigTraits& avgEmTraits) { - const emigTraits indEmigTraits = inds[ix]->getEmigTraits(); - avgEmTraits.d0 += indEmigTraits.d0; - avgEmTraits.alpha += indEmigTraits.alpha; - avgEmTraits.beta += indEmigTraits.beta; -} - -void Population::addTransferDataForInd(int ix, trfrData* avgTrfrData) { - inds[ix]->getTrfrData()->addMyself(*avgTrfrData); -} - -void Population::addSettleTraitsForInd(int ix, settleTraits& avgSettleTraits) { - const settleTraits settleTraits = inds[ix]->getSettTraits(); - avgSettleTraits.alpha += settleTraits.alpha; - avgSettleTraits.beta += settleTraits.beta; - avgSettleTraits.s0 += settleTraits.s0; -} // For an individual identified as being in the matrix population: // if it is a settler, return its new location and remove it from the current population diff --git a/Population.h b/Population.h index dae449a..63ffd55 100644 --- a/Population.h +++ b/Population.h @@ -130,10 +130,7 @@ class Population { void reproduction( const float, // local carrying capacity const float, // effect of environmental gradient and/or stochasticty - const int, // Landscape resolution - bool, - Population* - + const int // Landscape resolution ); // Following reproduction of ALL species, add juveniles to the population void fledge(void); @@ -151,7 +148,6 @@ class Population { disperser extractSettler( int // index no. to the Individual in the inds vector ); - Individual* copyForColdStorage(int ix); void addEmigTraitsForInd(int ix, emigTraits&); void addSettleTraitsForInd(int, settleTraits&); void addTransferDataForInd(int ix, trfrData* avgTrfrData); diff --git a/Species.cpp b/Species.cpp index 459c3d3..3473c82 100644 --- a/Species.cpp +++ b/Species.cpp @@ -370,10 +370,6 @@ float Species::getMinMax(short opt) { //--------------------------------------------------------------------------- -void Species::turnOffMutations(void) { - mutationsOn = false; -} - bool Species::areMutationsOn(void) { return mutationsOn; } diff --git a/Species.h b/Species.h index bedfcb7..8e59d2b 100644 --- a/Species.h +++ b/Species.h @@ -301,7 +301,6 @@ class Species { } // Genetic functions - void turnOffMutations(void); void resetGeneticParameters(); bool areMutationsOn(void); bool isDiploid() const; diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 5164444..33d8659 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -280,7 +280,7 @@ void SubCommunity::patchChange(void) { } } -void SubCommunity::reproduction(int resol, float epsGlobal, short rasterType, bool patchModel, bool cloneFromColdStorage, Population* pColdStorage) +void SubCommunity::reproduction(int resol, float epsGlobal, short rasterType, bool patchModel) { if (subCommNum == 0) return; // no reproduction in the matrix float localK, envval; @@ -317,7 +317,7 @@ void SubCommunity::reproduction(int resol, float epsGlobal, short rasterType, bo } } for (int i = 0; i < npops; i++) { // all populations - popns[i]->reproduction(localK, envval, resol, cloneFromColdStorage, pColdStorage); + popns[i]->reproduction(localK, envval, resol); popns[i]->fledge(); } } @@ -375,59 +375,8 @@ void SubCommunity::initiateDispersal(SubCommunity* matrix) { // remove pointers to emigrants popns[i]->clean(); } - -} - -void SubCommunity::copyIndividualsForColdStorage(Population* pColdStorage) { - int npops = (int)popns.size(); - popStats pop; - Individual* clone; - for (int i = 0; i < npops; i++) { // all populations - pop = popns[i]->getStats(); - for (int j = 0; j < pop.nInds; j++) { -#if RSDEBUG - //DEBUGLOG << "SubCommunity::initiateDispersal(): i = " << i - // << " j " << j - // << endl; -#endif - - clone = popns[i]->copyForColdStorage(j); - pColdStorage->recruit(clone); - } - } - -} - - -int SubCommunity::addEmigrationAndSettlementTraitValues(emigTraits& avgEmTraits, settleTraits& avgSettleTraits) { - int npops = (int)popns.size(); - int totalInds = 0; - popStats pop; - for (int i = 0; i < npops; i++) { // all populations - pop = popns[i]->getStats(); - for (int j = 0; j < pop.nInds; j++) { - popns[i]->addEmigTraitsForInd(j, avgEmTraits); - popns[i]->addSettleTraitsForInd(j, avgSettleTraits); - totalInds++; - } - } - return totalInds; -} - -void SubCommunity::addTransferDataForInd(trfrData* avgTrfrData) { - int npops = (int)popns.size(); - popStats pop; - for (int i = 0; i < npops; i++) { // all populations - pop = popns[i]->getStats(); - for (int j = 0; j < pop.nInds; j++) { - popns[i]->addTransferDataForInd(j, avgTrfrData); - } - } } - - - // Add an individual into the local population of its species in the patch void SubCommunity::recruit(Individual* pInd, Species* pSpecies) { int npops = (int)popns.size(); diff --git a/SubCommunity.h b/SubCommunity.h index 19017b0..f24830d 100644 --- a/SubCommunity.h +++ b/SubCommunity.h @@ -91,9 +91,7 @@ class SubCommunity { int, // Landscape resolution float, // epsilon - global stochasticity value short, // raster type (see Landscape) - bool, // TRUE for a patch-based model, FALSE for a cell-based model - bool, // TRUE if cloning from cold storage - Population* //cold storage + bool // TRUE for a patch-based model, FALSE for a cell-based model ); void emigration(void); // Remove emigrants from their natal patch and add to patch 0 (matrix) @@ -133,7 +131,6 @@ class SubCommunity { // 1 - development and survival ); void ageIncrement(void); - void copyIndividualsForColdStorage(Population*); int addEmigrationAndSettlementTraitValues(emigTraits& avgEmTraits, settleTraits& avgSettleTraits); @@ -142,7 +139,6 @@ class SubCommunity { // Find the population of a given species in a given patch Population* findPop(Species*, Patch*); - int getPopulationCountForStage(int stage); void createOccupancy( int // no. of rows = (no. of years / interval) + 1 ); From a04fa8c4343e1a716e1497c617fe537be09dd20e Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 14 Feb 2024 13:55:27 +0000 Subject: [PATCH 046/332] rm unused function declarations --- Community.cpp | 2 -- Model.h | 17 ----------------- Patch.h | 2 -- 3 files changed, 21 deletions(-) diff --git a/Community.cpp b/Community.cpp index 7abb597..82b4cef 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1487,8 +1487,6 @@ void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int outtraitsrows << "\t" << mn << "\t" << sd; } } - - outtraitsrows << endl; } diff --git a/Model.h b/Model.h index 0461b05..630e3a9 100644 --- a/Model.h +++ b/Model.h @@ -89,20 +89,7 @@ void RangePopOutput( int, // year int // generation ); -void Outputs_Visuals_B( - int, // replicate - int, // year - int, // generation - int // Landscape number -); -void RefreshVisualCost(void); traitCanvas SetupTraitCanvas(void); -void SetupVisualOutput(void); -void ResetVisualOutput(void); -void DrawPopnGraph( - Community*, // pointer to Community - int // year -); void OutParameters( Landscape* // pointer to Landscape ); @@ -128,10 +115,6 @@ extern RSrandom *pRandom; #if BATCH extern void MemoLine(string); #endif -void GUIsetLandScale( - int, // landscape image height (pixels) - int // landscape image width (pixels) -); #if RS_RCPP extern std::uint32_t RS_random_seed; diff --git a/Patch.h b/Patch.h index adb390f..7da3247 100644 --- a/Patch.h +++ b/Patch.h @@ -141,8 +141,6 @@ class Patch { bool // TRUE if there is a gradient in carrying capacity across the Landscape ); float getK(void); - // dummy function for batch version - void drawCells(float, int, rgb); private: int patchSeqNum;// sequential patch number - patch 0 is reserved for the inter-patch matrix From 9e6fa3c4ab416a70c4d2e362c73564318e243aab Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 15 Feb 2024 11:38:43 +0000 Subject: [PATCH 047/332] errors in unix build --- Model.h | 1 + Species.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Model.h b/Model.h index 0461b05..92507dd 100644 --- a/Model.h +++ b/Model.h @@ -48,6 +48,7 @@ #include #include +#include #include "Parameters.h" #include "Landscape.h" diff --git a/Species.cpp b/Species.cpp index 459c3d3..79ec734 100644 --- a/Species.cpp +++ b/Species.cpp @@ -384,8 +384,8 @@ void Species::resetGeneticParameters() { numberOfAdaptiveTraits = 0; genomeSize = -9999; recombinationRate = -9999; - nSampleCellsFst = -9999; - nIndsToSample = -9999; + nSampleCellsFst = ""; + nIndsToSample = ""; chromosomeEnds.clear(); samplePatchList.clear(); } From 9af75819de943d95ed58230211d3e0d90f332d47 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 15 Feb 2024 11:47:38 +0000 Subject: [PATCH 048/332] gcc dislikes switch missing a default --- Population.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Population.cpp b/Population.cpp index aec1141..1a188de 100644 --- a/Population.cpp +++ b/Population.cpp @@ -289,6 +289,9 @@ traitsums Population::getTraits(Species* pSpecies) { ts.sumRho[g] += c.rho; ts.ssqRho[g] += c.rho * c.rho; break; } + default: + throw runtime_error("moveModel enabled but moveType is neither 1 (SMS) or 2 (CRW)."); + break; } else { trfrKernTraits k = inds[i]->getKernTraits(); From 564518dd09658f4320e1bb9e1fc674af80cf2862 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 15 Feb 2024 11:50:00 +0000 Subject: [PATCH 049/332] oops misplaced default --- Population.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Population.cpp b/Population.cpp index 1a188de..52b6a87 100644 --- a/Population.cpp +++ b/Population.cpp @@ -288,10 +288,10 @@ traitsums Population::getTraits(Species* pSpecies) { ts.sumStepL[g] += c.stepLength; ts.ssqStepL[g] += c.stepLength * c.stepLength; ts.sumRho[g] += c.rho; ts.ssqRho[g] += c.rho * c.rho; break; - } default: throw runtime_error("moveModel enabled but moveType is neither 1 (SMS) or 2 (CRW)."); break; + } } else { trfrKernTraits k = inds[i]->getKernTraits(); From 92a1adbafadff81038467a80a5c930af38025134 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 15 Feb 2024 11:55:20 +0000 Subject: [PATCH 050/332] break was not the issue, switch cases must be fenced --- Population.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Population.cpp b/Population.cpp index 52b6a87..6e39fe4 100644 --- a/Population.cpp +++ b/Population.cpp @@ -275,6 +275,7 @@ traitsums Population::getTraits(Species* pSpecies) { switch (trfr.moveType) { case 1: // SMS + { trfrSMSTraits sms = inds[i]->getSMSTraits(); g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT ts.sumDP[g] += sms.dp; ts.ssqDP[g] += sms.dp * sms.dp; @@ -282,12 +283,15 @@ traitsums Population::getTraits(Species* pSpecies) { ts.sumAlphaDB[g] += sms.alphaDB; ts.ssqAlphaDB[g] += sms.alphaDB * sms.alphaDB; ts.sumBetaDB[g] += sms.betaDB; ts.ssqBetaDB[g] += sms.betaDB * sms.betaDB; break; + } case 2: + { trfrCRWTraits c = inds[i]->getCRWTraits(); g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT ts.sumStepL[g] += c.stepLength; ts.ssqStepL[g] += c.stepLength * c.stepLength; ts.sumRho[g] += c.rho; ts.ssqRho[g] += c.rho * c.rho; break; + } default: throw runtime_error("moveModel enabled but moveType is neither 1 (SMS) or 2 (CRW)."); break; From 5e2e1e5e4b38b9a49ea32763a122eb0addc3d57c Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 15 Feb 2024 12:03:40 +0000 Subject: [PATCH 051/332] missing include for ranges --- Species.cpp | 2 +- Species.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Species.cpp b/Species.cpp index 79ec734..3d3c474 100644 --- a/Species.cpp +++ b/Species.cpp @@ -472,7 +472,7 @@ void Species::clearTraitTable() { //} set Species::getTraitTypes() { - auto kv = views::keys(spTraitTable); + auto kv = std::views::keys(spTraitTable); set keys{ kv.begin(), kv.end() }; return keys; } diff --git a/Species.h b/Species.h index bedfcb7..00f8ec6 100644 --- a/Species.h +++ b/Species.h @@ -51,6 +51,7 @@ #include #include #include +#include class SpeciesTrait; From 395daebcb64c0d650cb037f269611b597252affd Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 15 Feb 2024 15:31:49 +0000 Subject: [PATCH 052/332] would this be better, xcode? --- Species.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Species.cpp b/Species.cpp index 3d3c474..79ec734 100644 --- a/Species.cpp +++ b/Species.cpp @@ -472,7 +472,7 @@ void Species::clearTraitTable() { //} set Species::getTraitTypes() { - auto kv = std::views::keys(spTraitTable); + auto kv = views::keys(spTraitTable); set keys{ kv.begin(), kv.end() }; return keys; } From 7fdbe44b7ee5c93cadb7acd2909e32af25cd9702 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 15 Feb 2024 15:33:38 +0000 Subject: [PATCH 053/332] like this? --- Species.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Species.cpp b/Species.cpp index 79ec734..340b919 100644 --- a/Species.cpp +++ b/Species.cpp @@ -472,7 +472,7 @@ void Species::clearTraitTable() { //} set Species::getTraitTypes() { - auto kv = views::keys(spTraitTable); + auto kv = std::ranges::views::keys(spTraitTable); set keys{ kv.begin(), kv.end() }; return keys; } From b15556499a9ac24917c7d6ce326001d4dfe44e41 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 15 Feb 2024 16:54:04 +0000 Subject: [PATCH 054/332] update expected output files for test scenario --- Species.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Species.h b/Species.h index 00f8ec6..bedfcb7 100644 --- a/Species.h +++ b/Species.h @@ -51,7 +51,6 @@ #include #include #include -#include class SpeciesTrait; From 178db29d94334d45422a7cc73e578070b1b3418a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 16 Feb 2024 13:43:04 +0000 Subject: [PATCH 055/332] fix compilation via gnu compiler --- Cell.cpp | 12 ------------ Cell.h | 4 ---- Community.h | 1 + FractalGenerator.h | 3 --- GeneticLoad.h | 3 +++ Individual.h | 1 + Landscape.cpp | 7 ------- Landscape.h | 3 --- Main.cpp | 7 +------ Model.cpp | 16 ---------------- Model.h | 24 +----------------------- Parameters.h | 2 +- QTLTrait.h | 2 ++ SNPTrait.h | 13 ++----------- Species.cpp | 3 --- Species.h | 13 +++++-------- TTrait.h | 3 ++- TraitFactory.h | 2 ++ 18 files changed, 21 insertions(+), 98 deletions(-) diff --git a/Cell.cpp b/Cell.cpp index fac40c8..85fa78c 100644 --- a/Cell.cpp +++ b/Cell.cpp @@ -37,12 +37,6 @@ Cell::Cell(int xx, int yy, intptr patch, int hab) envVal = 1.0; // default - no effect of any gradient envDev = eps = 0.0; habIxx.push_back(hab); -#if RSDEBUG - //DebugGUI(("Cell::Cell(): this=" + Int2Str((int)this) - // + " x=" + Int2Str(x) + " y=" + Int2Str(y) - // + " habIndex=" + Int2Str(habIndex) - //).c_str()); -#endif visits = 0; smsData = 0; } @@ -68,12 +62,6 @@ Cell::~Cell() { } void Cell::setHabIndex(short hx) { -#if RSDEBUG - //DebugGUI(("Cell::setHabIndex(): this=" + Int2Str((int)this) - // + " x=" + Int2Str(x) + " y=" + Int2Str(y) - // + " habIx=" + Int2Str(habIx) - //).c_str()); -#endif if (hx < 0) habIxx.push_back(0); else habIxx.push_back(hx); } diff --git a/Cell.h b/Cell.h index 02d9368..0d9757e 100644 --- a/Cell.h +++ b/Cell.h @@ -165,10 +165,6 @@ class DistCell { }; -#if RSDEBUG -extern void DebugGUI(string); -#endif - //--------------------------------------------------------------------------- #endif diff --git a/Community.h b/Community.h index 0c5d3e4..057190d 100644 --- a/Community.h +++ b/Community.h @@ -51,6 +51,7 @@ #include #include +#include #include using namespace std; diff --git a/FractalGenerator.h b/FractalGenerator.h index 5e7e9f9..c030566 100644 --- a/FractalGenerator.h +++ b/FractalGenerator.h @@ -77,9 +77,6 @@ vector& fractal_landscape( bool compare(const land&, const land&); extern RSrandom* pRandom; -#if RSDEBUG -extern void DebugGUI(string); -#endif //--------------------------------------------------------------------------- #endif diff --git a/GeneticLoad.h b/GeneticLoad.h index ae0a585..95d60ab 100644 --- a/GeneticLoad.h +++ b/GeneticLoad.h @@ -3,6 +3,9 @@ #include #include +#include +#include +#include #include "TTrait.h" diff --git a/Individual.h b/Individual.h index 71d986a..1fa1bf8 100644 --- a/Individual.h +++ b/Individual.h @@ -48,6 +48,7 @@ #include #include #include +#include using namespace std; #include "Parameters.h" diff --git a/Landscape.cpp b/Landscape.cpp index 369c3a3..3f23cfd 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -2354,11 +2354,6 @@ int Landscape::readCosts(string fname) costs >> maxXcost >> header >> maxYcost >> header >> minLongCost; costs >> header >> minLatCost >> header >> resolCost >> header >> NODATACost; - -#if !RS_RCPP - MemoLine("Loading costs map. Please wait..."); -#endif - for (int y = maxYcost - 1; y > -1; y--) { for (int x = 0; x < maxXcost; x++) { #if RS_RCPP @@ -2403,8 +2398,6 @@ if (costs.eof()) { #endif } else EOFerrorR(fname); -#else -MemoLine("Costs map loaded."); #endif costs.close(); costs.clear(); diff --git a/Landscape.h b/Landscape.h index 4ef9231..fbe4799 100644 --- a/Landscape.h +++ b/Landscape.h @@ -549,11 +549,8 @@ extern RSrandom* pRandom; #if RSDEBUG extern ofstream DEBUGLOG; -extern void DebugGUI(string); #endif -extern void MemoLine(string); - #if RS_RCPP extern rasterdata landraster, patchraster, spdistraster, costsraster; extern void EOFerrorR(string); diff --git a/Main.cpp b/Main.cpp index 42f783b..efc996f 100644 --- a/Main.cpp +++ b/Main.cpp @@ -61,12 +61,7 @@ ofstream MUTNLOG; vector hfnames; Species* pSpecies; Community* pComm; -void DebugGUI(string msg) { - // nothing -} -void MemoLine(string msg) { - /// nothing -} + traitCanvas SetupTraitCanvas(void) { traitCanvas tcanv; for (int i = 0; i < NTRAITS; i++) { tcanv.pcanvas[i] = 0; } diff --git a/Model.cpp b/Model.cpp index 2d68cd5..bbde41f 100644 --- a/Model.cpp +++ b/Model.cpp @@ -113,8 +113,6 @@ int RunModel(Landscape* pLandscape, int seqsim) #endif #endif - MemoLine(("Running replicate " + Int2Str(rep) + "...").c_str()); - if (sim.saveVisits && !ppLand.generated) { pLandscape->resetVisits(); } @@ -141,7 +139,6 @@ int RunModel(Landscape* pLandscape, int seqsim) // its corresponding patch upon deletion) if (pComm != 0) delete pComm; // generate new cell-based landscape - MemoLine("...generating new landscape..."); pLandscape->resetLand(); #if RSDEBUG DEBUGLOG << "RunModel(): finished resetting landscape" << endl << endl; @@ -179,7 +176,6 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES #endif } - MemoLine("...completed..."); #if RSDEBUG DEBUGLOG << endl << "RunModel(): finished generating populations" << endl; #endif @@ -198,40 +194,33 @@ int RunModel(Landscape* pLandscape, int seqsim) // open output files if (sim.outRange) { // open Range file if (!pComm->outRangeHeaders(pSpecies, ppLand.landNum)) { - MemoLine("UNABLE TO OPEN RANGE FILE"); filesOK = false; } } if (sim.outOccup && sim.reps > 1) if (!pComm->outOccupancyHeaders(0)) { - MemoLine("UNABLE TO OPEN OCCUPANCY FILE(S)"); filesOK = false; } if (sim.outPop) { // open Population file if (!pComm->outPopHeaders(pSpecies, ppLand.landNum)) { - MemoLine("UNABLE TO OPEN POPULATION FILE"); filesOK = false; } } if (sim.outTraitsCells) if (!pComm->outTraitsHeaders(pSpecies, ppLand.landNum)) { - MemoLine("UNABLE TO OPEN TRAITS FILE"); filesOK = false; } if (sim.outTraitsRows) if (!pComm->outTraitsRowsHeaders(pSpecies, ppLand.landNum)) { - MemoLine("UNABLE TO OPEN TRAITS ROWS FILE"); filesOK = false; } if (sim.outConnect && ppLand.patchModel) // open Connectivity file if (!pLandscape->outConnectHeaders(0)) { - MemoLine("UNABLE TO OPEN CONNECTIVITY FILE"); filesOK = false; } if (sim.outputWCFstat) { // open neutral genetics file if (!pComm->openWCFstatFile(pSpecies, ppLand.landNum)) { - MemoLine("UNABLE TO OPEN NEUTRAL GENETICS FILE"); filesOK = false; } } @@ -328,7 +317,6 @@ int RunModel(Landscape* pLandscape, int seqsim) #endif // years loop - MemoLine("...running..."); for (yr = 0; yr < sim.years; yr++) { #if RSDEBUG DEBUGLOG << endl << "RunModel(): starting simulation=" << sim.simulation @@ -846,12 +834,10 @@ int RunModel(Landscape* pLandscape, int seqsim) // Occupancy outputs if (sim.outOccup && sim.reps > 1) { - MemoLine("Writing final occupancy output..."); pComm->outOccupancy(); pComm->outOccSuit(v.viewGraph); pComm->deleteOccupancy((sim.years / sim.outIntOcc) + 1); pComm->outOccupancyHeaders(-999); - MemoLine("...finished"); } if (sim.outRange) { @@ -871,9 +857,7 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outputPerLocusWCFstat) pComm->openWCPerLocusFstatFile(pSpecies, pLandscape, -999, 0); if (sim.outputPairwiseFst) pComm->openPairwiseFSTFile(pSpecies, pLandscape, -999, 0); - MemoLine("Deleting community..."); delete pComm; pComm = 0; - MemoLine("...finished"); #if RS_RCPP && !R_CMD return list_outPop; diff --git a/Model.h b/Model.h index 92507dd..ff1ae83 100644 --- a/Model.h +++ b/Model.h @@ -90,20 +90,7 @@ void RangePopOutput( int, // year int // generation ); -void Outputs_Visuals_B( - int, // replicate - int, // year - int, // generation - int // Landscape number -); -void RefreshVisualCost(void); traitCanvas SetupTraitCanvas(void); -void SetupVisualOutput(void); -void ResetVisualOutput(void); -void DrawPopnGraph( - Community*, // pointer to Community - int // year -); void OutParameters( Landscape* // pointer to Landscape ); @@ -118,22 +105,13 @@ extern Community* pComm; const bool batchMode = true; extern string landFile; extern vector hfnames; -extern string habmapname; // see Main.cpp (batch) +extern string habmapname; // see Main.cpp (batch) extern string patchmapname; // see Main.cpp (batch) extern string distnmapname; // see Main.cpp (batch) extern string costmapname; // see Main.cpp (batch) extern string genfilename; // see Main.cpp (batch) extern RSrandom *pRandom; -// these functions to have different version for GUI and batch applications ... -#if BATCH -extern void MemoLine(string); -#endif -void GUIsetLandScale( - int, // landscape image height (pixels) - int // landscape image width (pixels) -); - #if RS_RCPP extern std::uint32_t RS_random_seed; extern string name_landscape, name_patch, name_costfile, name_sp_dist; diff --git a/Parameters.h b/Parameters.h index 344f8ac..f7a95f3 100644 --- a/Parameters.h +++ b/Parameters.h @@ -60,6 +60,7 @@ #include #include #include +#include using namespace std; #include "RSrandom.h" @@ -443,7 +444,6 @@ class paramSim { #if RSDEBUG extern ofstream DEBUGLOG; -void DebugGUI(string); #endif extern RSrandom* pRandom; diff --git a/QTLTrait.h b/QTLTrait.h index 2a62de8..f6e7545 100644 --- a/QTLTrait.h +++ b/QTLTrait.h @@ -3,6 +3,8 @@ #include #include +#include +#include #include "TTrait.h" diff --git a/SNPTrait.h b/SNPTrait.h index 2133dbd..5bea21c 100644 --- a/SNPTrait.h +++ b/SNPTrait.h @@ -1,10 +1,10 @@ #ifndef SNPTRAITH #define SNPTRAITH - - #include #include +#include +#include #include "TTrait.h" @@ -35,30 +35,21 @@ class SNPTrait : public TTrait { void mutate_KAM(); void mutate_SSM(); - - - public: - //this one for species held trait table, e.g. prototype table, sets static members - SNPTrait(SpeciesTrait* P); //this one for individuals, static members are not reset SNPTrait(const SNPTrait& T); - virtual unique_ptr clone() const override { return std::make_unique(*this); } - virtual void inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) override; - virtual void mutate() override { (this->*_mutate_func_ptr) (); } virtual int getNLoci() const override { return pProtoTrait->getPositionsSize(); } - float getMutationRate() const override { return pProtoTrait->getMutationRate(); } bool isInherited() const override { return pProtoTrait->isInherited(); } diff --git a/Species.cpp b/Species.cpp index 340b919..8073f4f 100644 --- a/Species.cpp +++ b/Species.cpp @@ -546,9 +546,6 @@ float Species::getEmigD0(short stg, short sex) { // Transfer functions void Species::setTrfr(const trfrRules t) { -#if RSDEBUG - //DebugGUI("Species::setTrfr(): t.indVar=" + Int2Str((int)t.indVar)); -#endif moveModel = t.moveModel; stgDepTrfr = t.stgDep; sexDepTrfr = t.sexDep; distMort = t.distMort; indVarTrfr = t.indVar; twinKern = t.twinKern; diff --git a/Species.h b/Species.h index bedfcb7..1ff8cde 100644 --- a/Species.h +++ b/Species.h @@ -45,12 +45,14 @@ #ifndef SpeciesH #define SpeciesH -#include "Parameters.h" -#include "SpeciesTrait.h" -#include "TTrait.h" #include #include #include +#include + +#include "Parameters.h" +#include "SpeciesTrait.h" +#include "TTrait.h" class SpeciesTrait; @@ -577,10 +579,5 @@ class Species { //--------------------------------------------------------------------------- -#if RSDEBUG -//extern ofstream DEBUGLOG; -extern void DebugGUI(string); -#endif - //--------------------------------------------------------------------------- #endif diff --git a/TTrait.h b/TTrait.h index 9e7228b..733fbbd 100644 --- a/TTrait.h +++ b/TTrait.h @@ -2,7 +2,8 @@ #define TRAITTH #include -#include +#include +#include #include "Parameters.h" #include "Allele.h" diff --git a/TraitFactory.h b/TraitFactory.h index e7420ab..73836e3 100644 --- a/TraitFactory.h +++ b/TraitFactory.h @@ -1,6 +1,8 @@ #ifndef TRAITFACTORYH #define TRAITFACTORYH +#include + #include "SpeciesTrait.h" #include "SNPTrait.h" #include "QTLTrait.h" From 23b906928b79a757d558e344c016858559648db1 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 21 Feb 2024 11:38:51 +0000 Subject: [PATCH 056/332] fixes for batch interface --- Landscape.cpp | 19 ++++++++++++------- Landscape.h | 4 +--- Parameters.h | 6 +++++- SpeciesTrait.cpp | 20 ++++++++++++-------- 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index 369c3a3..9f293f1 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -868,6 +868,18 @@ void Landscape::addCellToPatch(Cell* pCell, Patch* pPatch, int hab) { pPatch->addCell(pCell, loc.x, loc.y); } +std::vector Landscape::getTruePatchNums() const { + // Need access to patchnums in Batch interface to set up random sampled patches + // when patchnums member is not yet initialised. + // Bad solution, would be better to rm patchnums and use this in all instances + // but might break existing assumptions in current code. + vector patchNums; + for (auto p : patches) { + patchNums.push_back(p->getPatchNum()); + } + return patchNums; +} + patchData Landscape::getPatchData(int ix) { patchData ppp; ppp.pPatch = patches[ix]; ppp.patchNum = patches[ix]->getPatchNum(); @@ -2354,11 +2366,6 @@ int Landscape::readCosts(string fname) costs >> maxXcost >> header >> maxYcost >> header >> minLongCost; costs >> header >> minLatCost >> header >> resolCost >> header >> NODATACost; - -#if !RS_RCPP - MemoLine("Loading costs map. Please wait..."); -#endif - for (int y = maxYcost - 1; y > -1; y--) { for (int x = 0; x < maxXcost; x++) { #if RS_RCPP @@ -2403,8 +2410,6 @@ if (costs.eof()) { #endif } else EOFerrorR(fname); -#else -MemoLine("Costs map loaded."); #endif costs.close(); costs.clear(); diff --git a/Landscape.h b/Landscape.h index 4ef9231..10b703b 100644 --- a/Landscape.h +++ b/Landscape.h @@ -235,6 +235,7 @@ class Landscape { void setCellArray(void); void addPatchNum(int); std::vector getPatchNums() const { return patchnums; } + std::vector getTruePatchNums() const; void generatePatches(Species*); // create an artificial landscape void allocatePatches(Species*); // create patches for a cell-based landscape Patch* newPatch( @@ -549,11 +550,8 @@ extern RSrandom* pRandom; #if RSDEBUG extern ofstream DEBUGLOG; -extern void DebugGUI(string); #endif -extern void MemoLine(string); - #if RS_RCPP extern rasterdata landraster, patchraster, spdistraster, costsraster; extern void EOFerrorR(string); diff --git a/Parameters.h b/Parameters.h index ab03949..f7a95f3 100644 --- a/Parameters.h +++ b/Parameters.h @@ -60,6 +60,7 @@ #include #include #include +#include using namespace std; #include "RSrandom.h" @@ -348,6 +349,8 @@ struct simParams { int outStartPaths; int outIntPaths; bool outPaths; bool ReturnPopRaster; bool CreatePopFile; #endif + int fionaOptions; + int storeIndsYr; bool fixReplicateSeed; bool outputWCFstat, outputPerLocusWCFstat, outputPairwiseFst; int outputGeneticInterval; @@ -430,6 +433,8 @@ class paramSim { bool viewGraph; // view population/occupancy graph on screen? string dir; // full name of working directory + int fionaOptions; + int storeIndsYr; bool fixReplicateSeed; bool outputWCFstat; bool outputPerLocusWCFstat; @@ -439,7 +444,6 @@ class paramSim { #if RSDEBUG extern ofstream DEBUGLOG; -void DebugGUI(string); #endif extern RSrandom* pRandom; diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index f8c5d8a..a536b9a 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -40,7 +40,16 @@ SpeciesTrait::SpeciesTrait(vector parameters, Species* pSpecies) { TraitType SpeciesTrait::stringToTraitType(const std::string& str, sex_t sex) const { - if (sex == MAL) { + // Non-dispersal traits + if (str == "neutral") return SNP; + else if (str == "adaptive") return ADAPTIVE; + // Sex-invariant dispersal traits + else if (str == "sms_directionalPersistence") return SMS_DP; + else if (str == "sms_goalBias") return SMS_GB; + else if (str == "sms_alphaDB") return SMS_ALPHADB; + else if (str == "sms_betaDB") return SMS_BETADB; + // Sex-specific dispersal traits + else if (sex == MAL) { if (str == "emigration_d0") return E_D0_M; else if (str == "emigration_alpha") return E_ALPHA_M; else if (str == "emigration_beta") return E_BETA_M; @@ -53,7 +62,8 @@ TraitType SpeciesTrait::stringToTraitType(const std::string& str, sex_t sex) con else if (str == "crw_stepLength") return CRW_STEPLENGTH_M; else if (str == "crw_stepCorrelation") return CRW_STEPCORRELATION_M; else throw logic_error(str + " is not a valid trait type."); - } else { + } + else { if (str == "emigration_d0") return E_D0_F; else if (str == "emigration_alpha") return E_ALPHA_F; else if (str == "emigration_beta") return E_BETA_F; @@ -65,12 +75,6 @@ TraitType SpeciesTrait::stringToTraitType(const std::string& str, sex_t sex) con else if (str == "kernel_probability") return KERNEL_PROBABILITY_F; else if (str == "crw_stepLength") return CRW_STEPLENGTH_F; else if (str == "crw_stepCorrelation") return CRW_STEPCORRELATION_F; - else if (str == "sms_directionalPersistence") return SMS_DP; - else if (str == "sms_goalBias") return SMS_GB; - else if (str == "sms_alphaDB") return SMS_ALPHADB; - else if (str == "sms_betaDB") return SMS_BETADB; - else if (str == "neutral") return SNP; - else if (str == "adaptive") return ADAPTIVE; else throw logic_error(str + " is not a valid trait type."); } } From cb64b4777e8d55653a9e64fe774f27d5b84b20f0 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 22 Feb 2024 10:32:19 +0000 Subject: [PATCH 057/332] run example with evolvable traits --- Individual.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Individual.cpp b/Individual.cpp index 8a9fbb8..ce7227e 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -107,7 +107,10 @@ void Individual::setSettleTraits(const settleTraits& settle) { } TTrait* Individual::getTrait(TraitType trait) const { - return this->spTraitTable.find(trait)->second.get(); + auto p = this->spTraitTable.find(trait); + if (p == spTraitTable.end()) + throw runtime_error("Trait does not exist in trait table."); + else return p->second.get(); } //map> Individual::getTraitTable(void) const From a82b463d2ba469bf400c8287edac44fb65e06b46 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 22 Feb 2024 16:32:15 +0000 Subject: [PATCH 058/332] cleanup --- Community.cpp | 14 +-- Individual.cpp | 6 +- Main.cpp | 2 +- Model.cpp | 56 ++---------- Parameters.cpp | 6 +- Parameters.h | 17 ++-- Patch.cpp | 8 +- Patch.h | 2 +- Population.cpp | 209 ++++++++++++++++++------------------------- Population.h | 70 +++++++-------- Species.cpp | 62 ++++++------- Species.h | 36 ++++---- SubCommunity.cpp | 226 ++++++++++++++++++++++++----------------------- SubCommunity.h | 2 +- 14 files changed, 321 insertions(+), 395 deletions(-) diff --git a/Community.cpp b/Community.cpp index 82b4cef..5df18f6 100644 --- a/Community.cpp +++ b/Community.cpp @@ -441,7 +441,7 @@ void Community::reproduction(int yr) void Community::emigration(void) { - int nsubcomms = (int)subComms.size(); + int nsubcomms = static_cast(subComms.size()); #if RSDEBUG DEBUGLOG << "Community::emigration(): this=" << this << " nsubcomms=" << nsubcomms << endl; @@ -846,7 +846,7 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) tcanv.pcanvas[0] = NULL; - for (int i = 0; i < NSEXES; i++) { + for (int i = 0; i < maxNbSexes; i++) { ts.ninds[i] = 0; ts.sumD0[i] = ts.ssqD0[i] = 0.0; ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; @@ -864,7 +864,7 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) int nsubcomms = (int)subComms.size(); for (int i = 0; i < nsubcomms; i++) { // all sub-communities (incl. matrix) scts = subComms[i]->outTraits(tcanv, pLandscape, rep, yr, gen, true); - for (int j = 0; j < NSEXES; j++) { + for (int j = 0; j < maxNbSexes; j++) { ts.ninds[j] += scts.ninds[j]; ts.sumD0[j] += scts.sumD0[j]; ts.ssqD0[j] += scts.ssqD0[j]; ts.sumAlpha[j] += scts.sumAlpha[j]; ts.ssqAlpha[j] += scts.ssqAlpha[j]; @@ -1218,7 +1218,7 @@ void Community::outTraits(traitCanvas tcanv, Species* pSpecies, // create array of traits means, etc., one for each row ts = new traitsums[land.dimY]; for (int y = 0; y < land.dimY; y++) { - for (int i = 0; i < NSEXES; i++) { + for (int i = 0; i < maxNbSexes; i++) { ts[y].ninds[i] = 0; ts[y].sumD0[i] = ts[y].ssqD0[i] = 0.0; ts[y].sumAlpha[i] = ts[y].ssqAlpha[i] = 0.0; @@ -1249,7 +1249,7 @@ void Community::outTraits(traitCanvas tcanv, Species* pSpecies, int y = loc.y; if (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0) { - for (int s = 0; s < NSEXES; s++) { + for (int s = 0; s < maxNbSexes; s++) { ts[y].ninds[s] += sctraits.ninds[s]; ts[y].sumD0[s] += sctraits.sumD0[s]; ts[y].ssqD0[s] += sctraits.ssqD0[s]; ts[y].sumAlpha[s] += sctraits.sumAlpha[s]; ts[y].ssqAlpha[s] += sctraits.ssqAlpha[s]; @@ -1470,7 +1470,7 @@ void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int } if (pSpecies->getNumberOfAdaptiveTraits() > 0) { - if (NSEXES > 1) { + if (maxNbSexes > 1) { if (ts.ninds[0] > 0) mn = ts.sumFitness[0] / (double)ts.ninds[0]; else mn = 0.0; if (ts.ninds[0] > 1) sd = ts.ssqFitness[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; @@ -1579,7 +1579,7 @@ bool Community::outTraitsRowsHeaders(Species* pSpecies, int landNr) { } if (pSpecies->getNumberOfAdaptiveTraits() > 0) { - if (NSEXES > 1) { + if (maxNbSexes > 1) { outtraitsrows << "\tF_meanFitness\tF_stdFitness\tM_meanFitness\tM_stdFitness"; } else diff --git a/Individual.cpp b/Individual.cpp index ce7227e..f15dff8 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -422,7 +422,6 @@ void Individual::setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel k.meanDist2 = getTrait(KERNEL_MEANDIST_2_M)->express(); k.probKern1 = getTrait(KERNEL_PROBABILITY_M)->express(); } - } else { k.meanDist1 = getTrait(KERNEL_MEANDIST_1_F)->express(); @@ -431,7 +430,6 @@ void Individual::setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel k.meanDist2 = getTrait(KERNEL_MEANDIST_2_F)->express(); k.probKern1 = getTrait(KERNEL_PROBABILITY_F)->express(); } - } float meanDist1 = (float)(k.meanDist1); float meanDist2 = (float)(k.meanDist2); @@ -1370,8 +1368,8 @@ array3x3f Individual::getHabMatrix(Landscape* pLand, Species* pSpecies, Cell* pCell; landData land = pLand->getLandData(); - if (absorbing) nodatacost = ABSNODATACOST; - else nodatacost = NODATACOST; + if (absorbing) nodatacost = absorbingNoDataCost; + else nodatacost = noDataCost; for (int x2 = -1; x2 < 2; x2++) { // index of relative move in x direction for (int y2 = -1; y2 < 2; y2++) { // index of relative move in x direction diff --git a/Main.cpp b/Main.cpp index efc996f..103515e 100644 --- a/Main.cpp +++ b/Main.cpp @@ -64,7 +64,7 @@ Community* pComm; traitCanvas SetupTraitCanvas(void) { traitCanvas tcanv; - for (int i = 0; i < NTRAITS; i++) { tcanv.pcanvas[i] = 0; } + for (int i = 0; i < maxNbTraitsGUI; i++) { tcanv.pcanvas[i] = 0; } return tcanv; } void Landscape::setLandMap(void) { } diff --git a/Model.cpp b/Model.cpp index 30f8b30..cc2ebd6 100644 --- a/Model.cpp +++ b/Model.cpp @@ -161,11 +161,6 @@ int RunModel(Landscape* pLandscape, int seqsim) #endif for (int i = 0; i < npatches; i++) { ppp = pLandscape->getPatchData(i); -#if RSDEBUG - //DEBUGLOG << "RunModel(): i = " << i - // << " ppp.pPatch = " << ppp.pPatch << " ppp.patchNum = " << ppp.patchNum - // << endl; -#endif #if RSWIN64 #if LINUX_CLUSTER pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES @@ -362,12 +357,6 @@ int RunModel(Landscape* pLandscape, int seqsim) #endif pLandscape->setLandLimits(ppLand.minX, minY, ppLand.maxX, ppLand.maxY); updateCC = true; -#if RSDEBUG - //landData d = pLandscape->getLandData(); - //DEBUGLOG << "RunModel(): landscape yr=" << yr - // << " minX=" << d.minX << " minY=" << d.minY << " maxX=" << d.maxX << " maxY=" << d.maxY - // << endl; -#endif } } if (yr == init.finalFrzYr) { @@ -380,12 +369,6 @@ int RunModel(Landscape* pLandscape, int seqsim) #endif pLandscape->setLandLimits(ppLand.minX, s.minY, ppLand.maxX, s.maxY); updateCC = true; -#if RSDEBUG - //landData d = pLandscape->getLandData(); - //DEBUGLOG << "RunModel(): landscape yr=" << yr - // << " minX=" << d.minX << " minY=" << d.minY << " maxX=" << d.maxX << " maxY=" << d.maxY - // << endl; -#endif } } } @@ -398,10 +381,6 @@ int RunModel(Landscape* pLandscape, int seqsim) pLandscape->setEnvGradient(pSpecies, false); updateCC = true; } -#if RSDEBUG - //DEBUGLOG << "RunModel(): yr=" << yr << " shift_begin=" << grad.shift_begin - // << " shift_stop=" << grad.shift_stop << " opt_y=" << grad.opt_y << endl; -#endif if (env.stoch) { if (env.local) pLandscape->updateLocalStoch(); updateCC = true; @@ -422,15 +401,6 @@ int RunModel(Landscape* pLandscape, int seqsim) Cell* pCell; patchchange = pLandscape->getPatchChange(ixpchchg++); while (patchchange.chgnum <= landIx && ixpchchg <= npatchchanges) { -#if RSDEBUG - //DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << landIx - // << " npatchchanges=" << npatchchanges << " ixpchchg=" << ixpchchg - // << " patchchange.chgnum=" << patchchange.chgnum - // << " .oldpatch=" << patchchange.oldpatch - // << " .newpatch=" << patchchange.newpatch - // << " .x=" << patchchange.x << " .y=" << patchchange.y - // << endl; -#endif // move cell from original patch to new patch pCell = pLandscape->findCell(patchchange.x, patchchange.y); if (patchchange.oldpatch != 0) { // not matrix @@ -458,15 +428,6 @@ int RunModel(Landscape* pLandscape, int seqsim) Cell* pCell; costchange = pLandscape->getCostChange(ixcostchg++); while (costchange.chgnum <= landIx && ixcostchg <= ncostchanges) { -#if RSDEBUG - //DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << landIx - // << " ncostchanges=" << ncostchanges << " ixcostchg=" << ixcostchg - // << " costchange.chgnum=" << costchange.chgnum - // << " .x=" << costchange.x << " .y=" << costchange.y - // << " .oldcost=" << costchange.oldcost - // << " .newcost=" << costchange.newcost - // << endl; -#endif pCell = pLandscape->findCell(costchange.x, costchange.y); if (pCell != 0) { pCell->setCost(costchange.newcost); @@ -580,7 +541,6 @@ int RunModel(Landscape* pLandscape, int seqsim) #endif // Dispersal - pComm->emigration(); #if RSDEBUG DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed emigration" << endl; @@ -901,7 +861,7 @@ void PreReproductionOutput(Landscape* pLand, Community* pComm, int rep, int yr, #endif traitCanvas tcanv; - for (int i = 0; i < NTRAITS; i++) { + for (int i = 0; i < maxNbTraitsGUI; i++) { tcanv.pcanvas[i] = 0; } @@ -1303,7 +1263,7 @@ void OutParameters(Landscape* pLandscape) } int mSize; // index for weights matrices - if (dem.repType == 2) mSize = sstruct.nStages * NSEXES; + if (dem.repType == 2) mSize = sstruct.nStages * maxNbSexes; else mSize = sstruct.nStages; outPar << "DENSITY-DEPENDENCE IN FECUNDITY:\t"; @@ -1313,8 +1273,8 @@ void OutParameters(Landscape* pLandscape) outPar << "STAGE'S WEIGHTS:" << endl; for (int i = 0; i < mSize; i++) { if (dem.repType == 2) { - outPar << "stage " << i / NSEXES << " "; - if (i % NSEXES == 0) outPar << "males : \t"; + outPar << "stage " << i / maxNbSexes << " "; + if (i % maxNbSexes == 0) outPar << "males : \t"; else outPar << "females: \t"; } else outPar << "stage " << i << ": \t"; @@ -1335,8 +1295,8 @@ void OutParameters(Landscape* pLandscape) outPar << "STAGE'S WEIGHTS:" << endl; for (int i = 0; i < mSize; i++) { if (dem.repType == 2) { - outPar << "stage " << i / NSEXES << " "; - if (i % NSEXES == 0) outPar << "males : \t"; + outPar << "stage " << i / maxNbSexes << " "; + if (i % maxNbSexes == 0) outPar << "males : \t"; else outPar << "females: \t"; } else outPar << "stage " << i << ": \t"; @@ -1355,8 +1315,8 @@ void OutParameters(Landscape* pLandscape) outPar << "STAGE'S WEIGHTS:" << endl; for (int i = 0; i < mSize; i++) { if (dem.repType == 2) { - outPar << "stage " << i / NSEXES << " "; - if (i % NSEXES == 0) outPar << "males : \t"; + outPar << "stage " << i / maxNbSexes << " "; + if (i % maxNbSexes == 0) outPar << "males : \t"; else outPar << "females: \t"; } else outPar << "stage " << i << ": \t"; diff --git a/Parameters.cpp b/Parameters.cpp index 7dad8f9..0ea711b 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -128,7 +128,7 @@ paramInit::paramInit(void) { minSeedX = 0; maxSeedX = 99999999; minSeedY = 0; maxSeedY = 99999999; nSeedPatches = 1; nSpDistPatches = 1; indsFile = "NULL"; - for (int i = 0; i < NSTAGES; i++) { + for (int i = 0; i < maxNbStages; i++) { initProp[i] = 0.0; } } @@ -176,12 +176,12 @@ initParams paramInit::getInit(void) { } void paramInit::setProp(short stg, float p) { - if (stg >= 0 && stg < NSTAGES && p >= 0.0 && p <= 1.0) initProp[stg] = p; + if (stg >= 0 && stg < maxNbStages && p >= 0.0 && p <= 1.0) initProp[stg] = p; } float paramInit::getProp(short stg) { float p = 0.0; - if (stg >= 0 && stg < NSTAGES) p = initProp[stg]; + if (stg >= 0 && stg < maxNbStages) p = initProp[stg]; return p; } diff --git a/Parameters.h b/Parameters.h index f7a95f3..e1bacee 100644 --- a/Parameters.h +++ b/Parameters.h @@ -65,16 +65,13 @@ using namespace std; #include "RSrandom.h" -#define NODATACOST 100000 // cost to use in place of nodata value for SMS; -#define ABSNODATACOST 100 // cost to use in place of nodata value for SMS; +constexpr int noDataCost = 100000; // cost to use in place of nodata value for SMS; +constexpr int absorbingNoDataCost = 100; // cost to use in place of nodata value for SMS; // when boundaries are absorbing -#define NSTAGES 10 // maximum number of stages permitted -#define NSEXES 2 // maximum number of sexes permitted -#define PARAMDEBUG 0 -#define NTRAITS 18 // maximum number of variable traits which can be displayed - // in GUI (VCL version) -#define NSD 3.0 // no. of s.d. to use to control range for displaying traits - +constexpr int maxNbStages = 10; // maximum number of stages permitted +constexpr int maxNbSexes = 2; // maximum number of sexes permitted +constexpr int maxNbTraitsGUI = 18; // maximum number of variable traits which can be displayed + // in GUI (VCL version) #if RS_RCPP typedef intptr_t intptr; #else @@ -319,7 +316,7 @@ class paramInit { int nSeedPatches; // no. of cells/patches to initialise int nSpDistPatches; // no. of species distribution cells to initialise string indsFile; // no. of species distribution cells to initialise - float initProp[NSTAGES]; // initial stage proportions (structured population only) + float initProp[maxNbStages]; // initial stage proportions (structured population only) vector initinds; // individuals to be initialised diff --git a/Patch.cpp b/Patch.cpp index abfb93a..499dbc5 100644 --- a/Patch.cpp +++ b/Patch.cpp @@ -33,7 +33,7 @@ Patch::Patch(int seqnum, int num) xMin = yMin = 999999999; xMax = yMax = 0; x = y = 0; subCommPtr = 0; localK = 0.0; - for (int sex = 0; sex < NSEXES; sex++) { + for (int sex = 0; sex < maxNbSexes; sex++) { nTemp[sex] = 0; } changed = false; @@ -326,7 +326,7 @@ void Patch::resetPopn(void) { } void Patch::resetPossSettlers(void) { - for (int sex = 0; sex < NSEXES; sex++) { + for (int sex = 0; sex < maxNbSexes; sex++) { nTemp[sex] = 0; } } @@ -338,7 +338,7 @@ void Patch::incrPossSettler(Species* pSpecies, int sex) { // << " sex = " << sex << endl; #endif // NOTE: THE FOLLOWING OPERATION WILL NEED TO BE MADE SPECIES-SPECIFIC... - if (sex >= 0 && sex < NSEXES) { + if (sex >= 0 && sex < maxNbSexes) { nTemp[sex]++; } } @@ -350,7 +350,7 @@ int Patch::getPossSettlers(Species* pSpecies, int sex) { // << " sex = " << sex << endl; #endif // NOTE: THE FOLLOWING OPERATION WILL NEED TO BE MADE SPECIES-SPECIFIC... - if (sex >= 0 && sex < NSEXES) return nTemp[sex]; + if (sex >= 0 && sex < maxNbSexes) return nTemp[sex]; else return 0; } diff --git a/Patch.h b/Patch.h index 7da3247..4b6c871 100644 --- a/Patch.h +++ b/Patch.h @@ -153,7 +153,7 @@ class Patch { float localK; // patch carrying capacity (individuals) bool changed; // NOTE: THE FOLLOWING ARRAY WILL NEED TO BE MADE SPECIES-SPECIFIC... - short nTemp[NSEXES]; // no. of potential settlers in each sex + short nTemp[maxNbSexes]; // no. of potential settlers in each sex std::vector cells; std::vector popns; diff --git a/Population.cpp b/Population.cpp index c3ae58f..e1dbf44 100644 --- a/Population.cpp +++ b/Population.cpp @@ -82,14 +82,14 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) else { nSexes = 2; probmale = dem.propMales; } // set up population sub-totals - for (int stg = 0; stg < NSTAGES; stg++) { - for (int sex = 0; sex < NSEXES; sex++) { + for (int stg = 0; stg < maxNbStages; stg++) { + for (int sex = 0; sex < maxNbSexes; sex++) { nInds[stg][sex] = 0; } } // set up local copy of minimum age table - short minAge[NSTAGES][NSEXES]; + short minAge[maxNbStages][maxNbSexes]; for (int stg = 0; stg < nStages; stg++) { for (int sex = 0; sex < nSexes; sex++) { if (dem.stageStruct) { @@ -104,11 +104,6 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) else { // non-structured population minAge[stg][sex] = 0; } -#if RSDEBUG - //DEBUGLOG << "Population::Population(): 1111 " - // << " minAge[" << stg << "][" << sex << "]=" << minAge[stg][sex] - // << endl; -#endif } } @@ -161,11 +156,6 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) } } } -#if RSDEBUG - //DEBUGLOG << "Population::Population(): this=" << this - // << " n=" << n << " stg=" << stg << " minage=" << minage << " maxage=" << maxage - // << endl; -#endif // create individuals int sex; nindivs = (int)inds.size(); @@ -208,10 +198,6 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) nInds[stg][sex]++; } } -#if RSDEBUG - //DEBUGLOG << "Population::Population(): this=" << this - // << " finished " << endl; -#endif } Population::~Population(void) { @@ -227,69 +213,79 @@ Population::~Population(void) { juvs.clear(); } -traitsums Population::getTraits(Species* pSpecies) { +traitsums Population::getIndTraitsSums(Species* pSpecies) { int g; traitsums ts = traitsums(); - for (int i = 0; i < NSEXES; i++) { - ts.ninds[i] = 0; - ts.sumD0[i] = ts.ssqD0[i] = 0.0; - ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; - ts.sumDist1[i] = ts.ssqDist1[i] = 0.0; ts.sumDist2[i] = ts.ssqDist2[i] = 0.0; - ts.sumProp1[i] = ts.ssqProp1[i] = 0.0; - ts.sumDP[i] = ts.ssqDP[i] = 0.0; - ts.sumGB[i] = ts.ssqGB[i] = 0.0; - ts.sumAlphaDB[i] = ts.ssqAlphaDB[i] = 0.0; - ts.sumBetaDB[i] = ts.ssqBetaDB[i] = 0.0; - ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; - ts.sumS0[i] = ts.ssqS0[i] = 0.0; - ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; - ts.sumFitness[i] = ts.ssqFitness[i] = 0.0; - } - //locus loc; + for (int sex = 0; sex < maxNbSexes; sex++) { + ts.ninds[sex] = 0; + ts.sumD0[sex] = ts.ssqD0[sex] = 0.0; + ts.sumAlpha[sex] = ts.ssqAlpha[sex] = 0.0; + ts.sumBeta[sex] = ts.ssqBeta[sex] = 0.0; + ts.sumDist1[sex] = ts.ssqDist1[sex] = 0.0; + ts.sumDist2[sex] = ts.ssqDist2[sex] = 0.0; + ts.sumProp1[sex] = ts.ssqProp1[sex] = 0.0; + ts.sumDP[sex] = ts.ssqDP[sex] = 0.0; + ts.sumGB[sex] = ts.ssqGB[sex] = 0.0; + ts.sumAlphaDB[sex] = ts.ssqAlphaDB[sex] = 0.0; + ts.sumBetaDB[sex] = ts.ssqBetaDB[sex] = 0.0; + ts.sumStepL[sex] = ts.ssqStepL[sex] = 0.0; + ts.sumRho[sex] = ts.ssqRho[sex] = 0.0; + ts.sumS0[sex] = ts.ssqS0[sex] = 0.0; + ts.sumAlphaS[sex] = ts.ssqAlphaS[sex] = 0.0; + ts.sumBetaS[sex] = ts.ssqBetaS[sex] = 0.0; + ts.sumFitness[sex] = ts.ssqFitness[sex] = 0.0; + } emigRules emig = pSpecies->getEmig(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); int ninds = (int)inds.size(); -#if RSDEBUG - //DEBUGLOG << "Population::getTraits(): ninds = " << ts.ninds[0] - //// << " nalleles = "<< nalleles - //// << " nemiggenes = " << nemiggenes << " ntrfrgenes = " << ntrfrgenes - // << endl; -#endif - for (int i = 0; i < ninds; i++) { - int sex = inds[i]->getSex(); - if (emig.sexDep || trfr.sexDep || sett.sexDep) g = sex; else g = 0; + for (int iInd = 0; iInd < ninds; iInd++) { + int sex = inds[iInd]->getSex(); + if (emig.sexDep || trfr.sexDep || sett.sexDep) + g = sex; + else g = 0; ts.ninds[g] += 1; + // emigration traits - emigTraits e = inds[i]->getEmigTraits(); - if (emig.sexDep) g = sex; else g = 0; - ts.sumD0[g] += e.d0; ts.ssqD0[g] += e.d0 * e.d0; - ts.sumAlpha[g] += e.alpha; ts.ssqAlpha[g] += e.alpha * e.alpha; - ts.sumBeta[g] += e.beta; ts.ssqBeta[g] += e.beta * e.beta; - // transfer traits + emigTraits e = inds[iInd]->getEmigTraits(); + if (emig.sexDep) g = sex; + else g = 0; + ts.sumD0[g] += e.d0; + ts.ssqD0[g] += e.d0 * e.d0; + ts.sumAlpha[g] += e.alpha; + ts.ssqAlpha[g] += e.alpha * e.alpha; + ts.sumBeta[g] += e.beta; + ts.ssqBeta[g] += e.beta * e.beta; + // transfer traits if (trfr.moveModel) { switch (trfr.moveType) { case 1: // SMS { - trfrSMSTraits sms = inds[i]->getSMSTraits(); + trfrSMSTraits sms = inds[iInd]->getSMSTraits(); g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ts.sumDP[g] += sms.dp; ts.ssqDP[g] += sms.dp * sms.dp; - ts.sumGB[g] += sms.gb; ts.ssqGB[g] += sms.gb * sms.gb; - ts.sumAlphaDB[g] += sms.alphaDB; ts.ssqAlphaDB[g] += sms.alphaDB * sms.alphaDB; - ts.sumBetaDB[g] += sms.betaDB; ts.ssqBetaDB[g] += sms.betaDB * sms.betaDB; + ts.sumDP[g] += sms.dp; + ts.ssqDP[g] += sms.dp * sms.dp; + ts.sumGB[g] += sms.gb; + ts.ssqGB[g] += sms.gb * sms.gb; + ts.sumAlphaDB[g] += sms.alphaDB; + ts.ssqAlphaDB[g] += sms.alphaDB * sms.alphaDB; + ts.sumBetaDB[g] += sms.betaDB; + ts.ssqBetaDB[g] += sms.betaDB * sms.betaDB; break; } case 2: { - trfrCRWTraits c = inds[i]->getCRWTraits(); + trfrCRWTraits c = inds[iInd]->getCRWTraits(); g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ts.sumStepL[g] += c.stepLength; ts.ssqStepL[g] += c.stepLength * c.stepLength; - ts.sumRho[g] += c.rho; ts.ssqRho[g] += c.rho * c.rho; + ts.sumStepL[g] += c.stepLength; + ts.ssqStepL[g] += c.stepLength * c.stepLength; + ts.sumRho[g] += c.rho; + ts.ssqRho[g] += c.rho * c.rho; break; } default: @@ -298,33 +294,33 @@ traitsums Population::getTraits(Species* pSpecies) { } } else { - trfrKernTraits k = inds[i]->getKernTraits(); - if (trfr.sexDep) g = sex; else g = 0; - ts.sumDist1[g] += k.meanDist1; ts.ssqDist1[g] += k.meanDist1 * k.meanDist1; - ts.sumDist2[g] += k.meanDist2; ts.ssqDist2[g] += k.meanDist2 * k.meanDist2; - ts.sumProp1[g] += k.probKern1; ts.ssqProp1[g] += k.probKern1 * k.probKern1; + trfrKernTraits k = inds[iInd]->getKernTraits(); + if (trfr.sexDep) g = sex; + else g = 0; + ts.sumDist1[g] += k.meanDist1; + ts.ssqDist1[g] += k.meanDist1 * k.meanDist1; + ts.sumDist2[g] += k.meanDist2; + ts.ssqDist2[g] += k.meanDist2 * k.meanDist2; + ts.sumProp1[g] += k.probKern1; + ts.ssqProp1[g] += k.probKern1 * k.probKern1; } // settlement traits - settleTraits s = inds[i]->getSettTraits(); - if (sett.sexDep) g = sex; else g = 0; + settleTraits s = inds[iInd]->getSettTraits(); + if (sett.sexDep) g = sex; + else g = 0; // g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ts.sumS0[g] += s.s0; ts.ssqS0[g] += s.s0 * s.s0; - ts.sumAlphaS[g] += s.alpha; ts.ssqAlphaS[g] += s.alpha * s.alpha; - ts.sumBetaS[g] += s.beta; ts.ssqBetaS[g] += s.beta * s.beta; - - if (NSEXES > 1) g = sex; else g = 0; - ts.sumFitness[g] += inds[i]->getFitness(); ts.ssqFitness[g] += inds[i]->getFitness() * inds[i]->getFitness(); - -#if RSDEBUG - //DEBUGLOG << "Population::getTraits():" - // << " i=" << i << " g=" << g << " a=" << a - // << " e.d0= " << e.d0 << " e.alpha= " << e.alpha << " e.beta= " << e.beta - // << " mnd0= " << emigTraits[g]->mnD0 << " mnAlpha= " << emigTraits[g]->mnAlpha << " mnBeta= " << emigTraits[g]->mnBeta - // << " sqd0= " << emigTraits[g]->sqD0 << " sqAlpha= " << emigTraits[g]->sqAlpha << " sqBeta= " << emigTraits[g]->sqBeta - // << endl; -#endif + ts.sumS0[g] += s.s0; + ts.ssqS0[g] += s.s0 * s.s0; + ts.sumAlphaS[g] += s.alpha; + ts.ssqAlphaS[g] += s.alpha * s.alpha; + ts.sumBetaS[g] += s.beta; + ts.ssqBetaS[g] += s.beta * s.beta; + + if (maxNbSexes > 1) g = sex; + else g = 0; + ts.sumFitness[g] += inds[iInd]->getFitness(); + ts.ssqFitness[g] += inds[iInd]->getFitness() * inds[iInd]->getFitness(); } - return ts; } @@ -598,7 +594,7 @@ void Population::reproduction(const float localK, const float envval, const int #endif // set up local copy of species fecundity table - float fec[NSTAGES][NSEXES]; + float fec[maxNbStages][maxNbSexes]; for (int stg = 0; stg < sstruct.nStages; stg++) { for (int sex = 0; sex < nsexes; sex++) { if (dem.stageStruct) { @@ -971,26 +967,20 @@ void Population::emigration(float localK) emigRules emig = pSpecies->getEmig(); emigTraits eparams; indStats ind; -#if RSDEBUG - //DEBUGLOG << "Population::emigration(): this=" << this - // << " nStages=" << sstruct.nStages - //// << " emig.emigGenes[0]=" << emig.emigGenes[0] - //// << " emig.emigGenes[1]=" << emig.emigGenes[1] - // << endl; -#endif -// to avoid division by zero, assume carrying capacity is at least one individual -// localK can be zero if there is a moving gradient or stochasticity in K + // to avoid division by zero, assume carrying capacity is at least one individual + // localK can be zero if there is a moving gradient or stochasticity in K if (localK < 1.0) localK = 1.0; - NK = (float)totalPop() / localK; + NK = static_cast(totalPop()) / localK; - int ninds = (int)inds.size(); + int ninds = static_cast(inds.size()); // set up local copy of emigration probability table // used when there is no individual variability // NB - IT IS DOUBTFUL THIS CONTRIBUTES ANY SUBSTANTIAL TIME SAVING - if (dem.repType == 0) nsexes = 1; else nsexes = 2; - double Pemig[NSTAGES][NSEXES]; + if (dem.repType == 0) nsexes = 1; + else nsexes = 2; + double Pemig[maxNbStages][maxNbSexes]; for (int stg = 0; stg < sstruct.nStages; stg++) { for (int sex = 0; sex < nsexes; sex++) { @@ -1014,15 +1004,6 @@ void Population::emigration(float localK) } } Pemig[stg][sex] = eparams.d0 / (1.0 + exp(-(NK - eparams.beta) * eparams.alpha)); -#if RSDEBUG - //if (ppLand.patch_model) { - // DEBUGLOG << "Population::emigration(): stg=" << stg << " sex=" << sex - // << " totalPop=" << totalPop() << " localK=" << localK << " NK=" << NK - // << " d0=" << eparams.d0 << " beta=" << eparams.beta << " alpha=" << eparams.alpha - // << " Pemig[stg][sex]=" << Pemig[stg][sex] - // << endl; - //} -#endif } else { // density-independent if (emig.sexDep) { @@ -1043,18 +1024,12 @@ void Population::emigration(float localK) } } } // end of !emig.indVar -#if RSDEBUG -//DEBUGLOG << "Population::emigration(): this=" << (int)this -// << " totalPop()=" << totalPop() -// << " Pemig[" << stg << "][" << sex << "]="<< Pemig[stg][sex] << endl; -#endif } } for (int i = 0; i < ninds; i++) { ind = inds[i]->getStats(); - if (ind.status < 1) - { + if (ind.status < 1) { if (emig.indVar) { // individual variability in emigration if (dem.stageStruct && ind.stage != emig.emigStage) { // emigration may not occur @@ -1095,14 +1070,6 @@ void Population::emigration(float localK) Pdisp = Pemig[0][0]; } } -#if RSDEBUG - //if (ppLand.patch_model) { - // DEBUGLOG << "Population::emigration(): i=" << i << " sex=" << ind.sex << " stage=" << ind.stage - // << " totalPop=" << totalPop() << " localK=" << localK << " NK=" << NK - // << " Pdisp=" << Pdisp - // << endl; - //} -#endif } else { // density-independent if (emig.sexDep) { @@ -1547,9 +1514,9 @@ void Population::survival0(float localK, short option0, short option1) // set up local copies of species development and survival tables int nsexes; if (dem.repType == 0) nsexes = 1; else nsexes = 2; - float dev[NSTAGES][NSEXES]; - float surv[NSTAGES][NSEXES]; - short minAge[NSTAGES][NSEXES]; + float dev[maxNbStages][maxNbSexes]; + float surv[maxNbStages][maxNbSexes]; + short minAge[maxNbStages][maxNbSexes]; for (int stg = 0; stg < sstruct.nStages; stg++) { for (int sex = 0; sex < nsexes; sex++) { if (dem.stageStruct) { diff --git a/Population.h b/Population.h index 63ffd55..3fe81d4 100644 --- a/Population.h +++ b/Population.h @@ -72,39 +72,39 @@ struct zombie { Individual* pInd; }; struct traitsums { // sums of trait genes for dispersal - int ninds[NSEXES]; // no. of individuals - double sumD0[NSEXES]; // sum of maximum emigration probability - double ssqD0[NSEXES]; // sum of squares of maximum emigration probability - double sumAlpha[NSEXES]; // sum of slope of emigration dens-dep reaction norm - double ssqAlpha[NSEXES]; // sum of squares of slope of emigration den-dep reaction norm - double sumBeta[NSEXES]; // sum of inflection point of emigration reaction norm - double ssqBeta[NSEXES]; // sum of squares of inflection point of emigration reaction norm - double sumDist1[NSEXES]; // sum of kernel I mean - double ssqDist1[NSEXES]; // sum of squares of kernel I mean - double sumDist2[NSEXES]; // sum of kernel II mean - double ssqDist2[NSEXES]; // sum of squares of kernel II mean - double sumProp1[NSEXES]; // sum of propn using kernel I - double ssqProp1[NSEXES]; // sum of squares of propn using kernel I - double sumDP[NSEXES]; // sum of SMS directional persistence - double ssqDP[NSEXES]; // sum of squares of SMS directional persistence - double sumGB[NSEXES]; // sum of SMS goal bias - double ssqGB[NSEXES]; // sum of squares of SMS goal bias - double sumAlphaDB[NSEXES]; // sum of SMS dispersal bias decay rate - double ssqAlphaDB[NSEXES]; // sum of squares of SMS dispersal bias decay rate - double sumBetaDB[NSEXES]; // sum of SMS dispersal bias decay infl. pt. - double ssqBetaDB[NSEXES]; // sum of squares of SMS dispersal bias decay infl. pt. - double sumStepL[NSEXES]; // sum of CRW step length - double ssqStepL[NSEXES]; // sum of squares of CRW step length - double sumRho[NSEXES]; // sum of CRW correlation coefficient - double ssqRho[NSEXES]; // sum of squares of CRW correlation coefficient - double sumS0[NSEXES]; // sum of maximum settlement probability - double ssqS0[NSEXES]; // sum of squares of maximum settlement probability - double sumAlphaS[NSEXES]; // sum of slope of settlement den-dep reaction norm - double ssqAlphaS[NSEXES]; // sum of squares of slope of settlement den-dep reaction norm - double sumBetaS[NSEXES]; // sum of inflection point of settlement reaction norm - double ssqBetaS[NSEXES]; // sum of squares of inflection point of settlement reaction norm - double sumFitness[NSEXES]; - double ssqFitness[NSEXES]; + int ninds[maxNbSexes]; // no. of individuals + double sumD0[maxNbSexes]; // sum of maximum emigration probability + double ssqD0[maxNbSexes]; // sum of squares of maximum emigration probability + double sumAlpha[maxNbSexes]; // sum of slope of emigration dens-dep reaction norm + double ssqAlpha[maxNbSexes]; // sum of squares of slope of emigration den-dep reaction norm + double sumBeta[maxNbSexes]; // sum of inflection point of emigration reaction norm + double ssqBeta[maxNbSexes]; // sum of squares of inflection point of emigration reaction norm + double sumDist1[maxNbSexes]; // sum of kernel I mean + double ssqDist1[maxNbSexes]; // sum of squares of kernel I mean + double sumDist2[maxNbSexes]; // sum of kernel II mean + double ssqDist2[maxNbSexes]; // sum of squares of kernel II mean + double sumProp1[maxNbSexes]; // sum of propn using kernel I + double ssqProp1[maxNbSexes]; // sum of squares of propn using kernel I + double sumDP[maxNbSexes]; // sum of SMS directional persistence + double ssqDP[maxNbSexes]; // sum of squares of SMS directional persistence + double sumGB[maxNbSexes]; // sum of SMS goal bias + double ssqGB[maxNbSexes]; // sum of squares of SMS goal bias + double sumAlphaDB[maxNbSexes]; // sum of SMS dispersal bias decay rate + double ssqAlphaDB[maxNbSexes]; // sum of squares of SMS dispersal bias decay rate + double sumBetaDB[maxNbSexes]; // sum of SMS dispersal bias decay infl. pt. + double ssqBetaDB[maxNbSexes]; // sum of squares of SMS dispersal bias decay infl. pt. + double sumStepL[maxNbSexes]; // sum of CRW step length + double ssqStepL[maxNbSexes]; // sum of squares of CRW step length + double sumRho[maxNbSexes]; // sum of CRW correlation coefficient + double ssqRho[maxNbSexes]; // sum of squares of CRW correlation coefficient + double sumS0[maxNbSexes]; // sum of maximum settlement probability + double ssqS0[maxNbSexes]; // sum of squares of maximum settlement probability + double sumAlphaS[maxNbSexes]; // sum of slope of settlement den-dep reaction norm + double ssqAlphaS[maxNbSexes]; // sum of squares of slope of settlement den-dep reaction norm + double sumBetaS[maxNbSexes]; // sum of inflection point of settlement reaction norm + double ssqBetaS[maxNbSexes]; // sum of squares of inflection point of settlement reaction norm + double sumFitness[maxNbSexes]; + double ssqFitness[maxNbSexes]; }; class Population { @@ -118,7 +118,7 @@ class Population { int // Landscape resolution ); ~Population(void); - traitsums getTraits(Species*); + traitsums getIndTraitsSums(Species*); popStats getStats(void); Species* getSpecies(void); int getNInds(void); @@ -237,7 +237,7 @@ class Population { short nSexes; Species* pSpecies; // pointer to the species Patch* pPatch; // pointer to the patch - int nInds[NSTAGES][NSEXES]; // no. of individuals in each stage/sex + int nInds[maxNbStages][maxNbSexes]; // no. of individuals in each stage/sex std::vector inds; // all individuals in population except ... std::vector juvs; // ... juveniles until reproduction of ALL species diff --git a/Species.cpp b/Species.cpp index 3b60e83..a07dca4 100644 --- a/Species.cpp +++ b/Species.cpp @@ -37,8 +37,8 @@ Species::Species(void) devDens = false; devStageDens = false; survDens = false; survStageDens = false; disperseOnLoss = false; - for (int i = 0; i < NSTAGES; i++) { - for (int j = 0; j < NSEXES; j++) { + for (int i = 0; i < maxNbStages; i++) { + for (int j = 0; j < maxNbSexes; j++) { fec[i][j] = 0.0; dev[i][j] = 0.0; surv[i][j] = 0.0; minAge[i][j] = 0; } @@ -52,8 +52,8 @@ Species::Species(void) // initialise emigration parameters densDepEmig = false; stgDepEmig = false; sexDepEmig = false; indVarEmig = false; emigStage = 0; - for (int i = 0; i < NSTAGES; i++) { - for (int j = 0; j < NSEXES; j++) { + for (int i = 0; i < maxNbStages; i++) { + for (int j = 0; j < maxNbSexes; j++) { d0[i][j] = 0.0; alphaEmig[i][j] = 0.0; betaEmig[i][j] = 1.0; } } @@ -64,8 +64,8 @@ Species::Species(void) habMort = false; costMap = false; moveType = 1; - for (int i = 0; i < NSTAGES; i++) { - for (int j = 0; j < NSEXES; j++) { + for (int i = 0; i < maxNbStages; i++) { + for (int j = 0; j < maxNbSexes; j++) { meanDist1[i][j] = 100.0f; meanDist2[i][j] = 1000.0f; probKern1[i][j] = 0.99f; } } @@ -81,8 +81,8 @@ Species::Species(void) // initialise settlement parameters stgDepSett = false; sexDepSett = false; indVarSett = false; minSteps = 0; maxSteps = 99999999; - for (int i = 0; i < NSTAGES; i++) { - for (int j = 0; j < NSEXES; j++) { + for (int i = 0; i < maxNbStages; i++) { + for (int j = 0; j < maxNbSexes; j++) { densDepSett[i][j] = false; wait[i][j] = false; go2nbrLocn[i][j] = false; findMate[i][j] = false; maxStepsYr[i][j] = 99999999; s0[i][j] = 1.0; alphaS[i][j] = 0.0; betaS[i][j] = 1.0; @@ -196,12 +196,12 @@ stageParams Species::getStage(void) { void Species::setFec(short stg, short sex, float f) { // NB fecundity for stage 0 must always be zero - if (stg > 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES && f >= 0) + if (stg > 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes && f >= 0) fec[stg][sex] = f; } float Species::getFec(short stg, short sex) { - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) return fec[stg][sex]; else return 0.0; } @@ -209,7 +209,7 @@ float Species::getFec(short stg, short sex) { float Species::getMaxFec(void) { float maxfec = 0.0; if (stageStruct) { - for (int stg = 1; stg < NSTAGES; stg++) { + for (int stg = 1; stg < maxNbStages; stg++) { if (fec[stg][0] > maxfec) maxfec = fec[stg][0]; } } @@ -218,35 +218,35 @@ float Species::getMaxFec(void) { } void Species::setDev(short stg, short sex, float d) { - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES && d >= 0) + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes && d >= 0) dev[stg][sex] = d; } float Species::getDev(short stg, short sex) { - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) return dev[stg][sex]; else return 0.0; } void Species::setSurv(short stg, short sex, float s) { - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES && s >= 0) + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes && s >= 0) surv[stg][sex] = s; } float Species::getSurv(short stg, short sex) { - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) return surv[stg][sex]; else return 0.0; } void Species::setMinAge(short stg, short sex, int age) { // NB min age for stages 0 & 1 must always be zero - if (stg > 1 && stg < NSTAGES && sex >= 0 && sex < NSEXES && age >= 0) + if (stg > 1 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes && age >= 0) minAge[stg][sex] = age; } short Species::getMinAge(short stg, short sex) { - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) return minAge[stg][sex]; else return 0; } @@ -263,7 +263,7 @@ densDepParams Species::getDensDep(void) { } void Species::createDDwtFec(short mSize) { - if (mSize >= 0 && mSize < (NSTAGES * NSEXES)) { + if (mSize >= 0 && mSize < (maxNbStages * maxNbSexes)) { if (ddwtFec != 0) deleteDDwtFec(); ddwtFecDim = mSize; ddwtFec = new float* [mSize]; @@ -295,7 +295,7 @@ void Species::deleteDDwtFec(void) { } void Species::createDDwtDev(short mSize) { - if (mSize >= 0 && mSize < (NSTAGES * NSEXES)) { + if (mSize >= 0 && mSize < (maxNbStages * maxNbSexes)) { if (ddwtDev != 0) deleteDDwtDev(); ddwtDevDim = mSize; ddwtDev = new float* [mSize]; @@ -327,7 +327,7 @@ void Species::deleteDDwtDev(void) { } void Species::createDDwtSurv(short mSize) { - if (mSize >= 0 && mSize < (NSTAGES * NSEXES)) { + if (mSize >= 0 && mSize < (maxNbStages * maxNbSexes)) { if (ddwtSurv != 0) deleteDDwtSurv(); ddwtSurvDim = mSize; ddwtSurv = new float* [mSize]; @@ -511,7 +511,7 @@ emigRules Species::getEmig(void) { } void Species::setEmigTraits(const short stg, const short sex, const emigTraits e) { - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { if (e.d0 >= 0.0 && e.d0 <= 1.0) d0[stg][sex] = e.d0; alphaEmig[stg][sex] = e.alpha; betaEmig[stg][sex] = e.beta; } @@ -519,7 +519,7 @@ void Species::setEmigTraits(const short stg, const short sex, const emigTraits e emigTraits Species::getEmigTraits(short stg, short sex) { emigTraits e; - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { e.d0 = d0[stg][sex]; e.alpha = alphaEmig[stg][sex]; e.beta = betaEmig[stg][sex]; } else { @@ -529,7 +529,7 @@ emigTraits Species::getEmigTraits(short stg, short sex) { } float Species::getEmigD0(short stg, short sex) { - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { return d0[stg][sex]; } else { @@ -569,7 +569,7 @@ bool Species::useFullKernel(void) { return fullKernel; } void Species::setKernTraits(const short stg, const short sex, const trfrKernTraits k, const int resol) { - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { if (k.meanDist1 > 0.0 && k.meanDist1 >= (float)resol) meanDist1[stg][sex] = k.meanDist1; if (k.meanDist2 >= (float)resol) meanDist2[stg][sex] = k.meanDist2; if (k.probKern1 > 0.0 && k.probKern1 < 1.0) probKern1[stg][sex] = k.probKern1; @@ -578,7 +578,7 @@ void Species::setKernTraits(const short stg, const short sex, trfrKernTraits Species::getKernTraits(short stg, short sex) { trfrKernTraits k; - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { k.meanDist1 = meanDist1[stg][sex]; k.meanDist2 = meanDist2[stg][sex]; k.probKern1 = probKern1[stg][sex]; @@ -701,7 +701,7 @@ settleType Species::getSettle(void) { } void Species::setSettRules(const short stg, const short sex, const settleRules s) { - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { densDepSett[stg][sex] = s.densDep; wait[stg][sex] = s.wait; go2nbrLocn[stg][sex] = s.go2nbrLocn; findMate[stg][sex] = s.findMate; } @@ -713,7 +713,7 @@ settleRules Species::getSettRules(short stg, short sex) { s.findMate = false; s.go2nbrLocn = false; s.wait = false; - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { s.densDep = densDepSett[stg][sex]; s.wait = wait[stg][sex]; s.go2nbrLocn = go2nbrLocn[stg][sex]; s.findMate = findMate[stg][sex]; } @@ -727,7 +727,7 @@ void Species::setSteps(const short stg, const short sex, const settleSteps s) { if (s.maxSteps >= 1) maxSteps = s.maxSteps; else maxSteps = 99999999; } - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { if (s.maxStepsYr >= 1) maxStepsYr[stg][sex] = s.maxStepsYr; else maxStepsYr[stg][sex] = 99999999; } @@ -737,13 +737,13 @@ settleSteps Species::getSteps(short stg, short sex) { settleSteps s; s.minSteps = minSteps; s.maxSteps = maxSteps; - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) s.maxStepsYr = maxStepsYr[stg][sex]; + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) s.maxStepsYr = maxStepsYr[stg][sex]; else s.maxStepsYr = 99999999; return s; } void Species::setSettTraits(const short stg, const short sex, const settleTraits dd) { - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { if (dd.s0 > 0.0 && dd.s0 <= 1.0) s0[stg][sex] = dd.s0; alphaS[stg][sex] = dd.alpha; betaS[stg][sex] = dd.beta; } @@ -768,7 +768,7 @@ void Species::setSamplePatchList(const set& samplePatchList) { settleTraits Species::getSettTraits(short stg, short sex) { settleTraits dd; - if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { dd.s0 = s0[stg][sex]; dd.alpha = alphaS[stg][sex]; dd.beta = betaS[stg][sex]; } else { dd.s0 = 1.0; dd.alpha = dd.beta = 0.0; } diff --git a/Species.h b/Species.h index 0b2f254..b1e3256 100644 --- a/Species.h +++ b/Species.h @@ -470,10 +470,10 @@ class Species { float** ddwtDev; // density-dependent weights matrix for development float** ddwtSurv; // density-dependent weights matrix for survival // NB for the following arrays, sex 0 is females, sex 1 is males - float fec[NSTAGES][NSEXES]; // fecundities - float dev[NSTAGES][NSEXES]; // development probabilities - float surv[NSTAGES][NSEXES]; // survival probabilities - short minAge[NSTAGES][NSEXES]; // minimum age to enter stage + float fec[maxNbStages][maxNbSexes]; // fecundities + float dev[maxNbStages][maxNbSexes]; // development probabilities + float surv[maxNbStages][maxNbSexes]; // survival probabilities + short minAge[maxNbStages][maxNbSexes]; // minimum age to enter stage // NOTE - IN THEORY, NEXT 3 VARIABLES COULD BE COMMON, BUT WE WOULD NEED TO ENSURE THAT // ALL MATRICES ARE DELETED IF THERE IS A CHANGE IN NO. OF STAGES OR REPRODUCTION TYPE // ***** TO BE RECONSIDERED LATER ***** @@ -508,9 +508,9 @@ class Species { short emigStage; // stage which emigrates (used for stage-strucutred population // having individual variability in emigration probability) // NB for the following arrays, sex 0 is females, sex 1 is males - float d0[NSTAGES][NSEXES]; // maximum emigration probability - float alphaEmig[NSTAGES][NSEXES]; // slope of density-dependent reaction norm - float betaEmig[NSTAGES][NSEXES]; // inflection point of reaction norm (in terms of N/K) + float d0[maxNbStages][maxNbSexes]; // maximum emigration probability + float alphaEmig[maxNbStages][maxNbSexes]; // slope of density-dependent reaction norm + float betaEmig[maxNbStages][maxNbSexes]; // inflection point of reaction norm (in terms of N/K) // NB Initialisation parameters are made double to avoid conversion errors (reason unclear) // on traits maps using FloatToStr() @@ -523,9 +523,9 @@ class Species { bool indVarTrfr; bool twinKern; bool habMort; // habitat-dependent mortality - float meanDist1[NSTAGES][NSEXES]; // mean of 1st dispersal kernel (m) - float meanDist2[NSTAGES][NSEXES]; // mean of 2nd dispersal kernel (m) - float probKern1[NSTAGES][NSEXES]; // probability of dispersing with the 1st kernel + float meanDist1[maxNbStages][maxNbSexes]; // mean of 1st dispersal kernel (m) + float meanDist2[maxNbStages][maxNbSexes]; // mean of 2nd dispersal kernel (m) + float probKern1[maxNbStages][maxNbSexes]; // probability of dispersing with the 1st kernel // NB INITIAL limits are made double to avoid conversion errors (reason unclear) // on traits maps using FloatToStr() // As evolving traits are are not stage-dependent, no. of rows can be 1 @@ -559,16 +559,16 @@ class Species { bool stgDepSett; bool sexDepSett; bool indVarSett; // individual variation in settlement - bool densDepSett[NSTAGES][NSEXES]; - bool wait[NSTAGES][NSEXES]; // wait to continue moving next season (stage-structured model only) - bool go2nbrLocn[NSTAGES][NSEXES]; // settle in neighbouring cell/patch if available (ditto) - bool findMate[NSTAGES][NSEXES]; + bool densDepSett[maxNbStages][maxNbSexes]; + bool wait[maxNbStages][maxNbSexes]; // wait to continue moving next season (stage-structured model only) + bool go2nbrLocn[maxNbStages][maxNbSexes]; // settle in neighbouring cell/patch if available (ditto) + bool findMate[maxNbStages][maxNbSexes]; int minSteps; // minimum no. of steps int maxSteps; // maximum total no. of steps - int maxStepsYr[NSTAGES][NSEXES]; // maximum no. of steps in any one dispersal period - float s0[NSTAGES][NSEXES]; // maximum settlement probability - float alphaS[NSTAGES][NSEXES]; // slope of the settlement reaction norm to density - float betaS[NSTAGES][NSEXES]; // inflection point of the settlement reaction norm to density + int maxStepsYr[maxNbStages][maxNbSexes]; // maximum no. of steps in any one dispersal period + float s0[maxNbStages][maxNbSexes]; // maximum settlement probability + float alphaS[maxNbStages][maxNbSexes]; // slope of the settlement reaction norm to density + float betaS[maxNbStages][maxNbSexes]; // inflection point of the settlement reaction norm to density // other attributes int spNum; diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 33d8659..4e7dce0 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -344,11 +344,9 @@ void SubCommunity::reproduction(int resol, float epsGlobal, short rasterType, bo void SubCommunity::emigration(void) { if (subCommNum == 0) return; // no emigration from the matrix - float localK; - int npops = (int)popns.size(); - // THE FOLLOWING MAY BE MORE EFFICIENT WHILST THERE IS ONLY ONE SPECIES ... + int npops = static_cast(popns.size()); if (npops < 1) return; - localK = pPatch->getK(); + float localK = pPatch->getK(); // NOTE that even if K is zero, it could have been >0 in previous time-step, and there // might be emigrants if there is non-juvenile emigration for (int i = 0; i < npops; i++) { // all populations @@ -756,7 +754,7 @@ bool SubCommunity::outTraitsHeaders(Landscape* pLandscape, Species* pSpecies, in } } if (pSpecies->getNumberOfAdaptiveTraits() > 0) { - if (NSEXES > 1) { + if (maxNbSexes > 1) { outtraits << "\tF_meanFitness\tF_stdFitness\tM_meanFitness\tM_stdFitness"; } else { @@ -779,8 +777,8 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, bool writefile = false; if (sim.outTraitsCells && yr % sim.outIntTraitCell == 0 && !commlevel) writefile = true; - traitsums ts, poptraits; - for (int i = 0; i < NSEXES; i++) { + traitsums ts, indTraitsSums; + for (int i = 0; i < maxNbSexes; i++) { ts.ninds[i] = 0; ts.sumD0[i] = ts.ssqD0[i] = 0.0; ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; @@ -802,15 +800,15 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, Species* pSpecies; float localK; - for (int i = 0; i < npops; i++) { // all populations + for (int iPop = 0; iPop < npops; iPop++) { // all populations localK = pPatch->getK(); - if (localK > 0.0 && popns[i]->getNInds() > 0) { - pSpecies = popns[i]->getSpecies(); + if (localK > 0.0 && popns[iPop]->getNInds() > 0) { + pSpecies = popns[iPop]->getSpecies(); demogrParams dem = pSpecies->getDemogr(); emigRules emig = pSpecies->getEmig(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); - poptraits = popns[i]->getTraits(pSpecies); + indTraitsSums = popns[iPop]->getIndTraitsSums(pSpecies); if (writefile) { outtraits << rep << "\t" << yr << "\t" << gen; @@ -836,26 +834,26 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, } } double mnD0[2], mnAlpha[2], mnBeta[2], sdD0[2], sdAlpha[2], sdBeta[2]; - for (int g = 0; g < ngenes; g++) { - mnD0[g] = mnAlpha[g] = mnBeta[g] = sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + for (int iGene = 0; iGene < ngenes; iGene++) { + mnD0[iGene] = mnAlpha[iGene] = mnBeta[iGene] = sdD0[iGene] = sdAlpha[iGene] = sdBeta[iGene] = 0.0; // individuals may have been counted by sex if there was // sex dependency in another dispersal phase - if (ngenes == 2) popsize = poptraits.ninds[g]; - else popsize = poptraits.ninds[0] + poptraits.ninds[1]; + if (ngenes == 2) popsize = indTraitsSums.ninds[iGene]; + else popsize = indTraitsSums.ninds[0] + indTraitsSums.ninds[1]; if (popsize > 0) { - mnD0[g] = poptraits.sumD0[g] / (double)popsize; - mnAlpha[g] = poptraits.sumAlpha[g] / (double)popsize; - mnBeta[g] = poptraits.sumBeta[g] / (double)popsize; + mnD0[iGene] = indTraitsSums.sumD0[iGene] / (double)popsize; + mnAlpha[iGene] = indTraitsSums.sumAlpha[iGene] / (double)popsize; + mnBeta[iGene] = indTraitsSums.sumBeta[iGene] / (double)popsize; if (popsize > 1) { - sdD0[g] = poptraits.ssqD0[g] / (double)popsize - mnD0[g] * mnD0[g]; - if (sdD0[g] > 0.0) sdD0[g] = sqrt(sdD0[g]); else sdD0[g] = 0.0; - sdAlpha[g] = poptraits.ssqAlpha[g] / (double)popsize - mnAlpha[g] * mnAlpha[g]; - if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; - sdBeta[g] = poptraits.ssqBeta[g] / (double)popsize - mnBeta[g] * mnBeta[g]; - if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + sdD0[iGene] = indTraitsSums.ssqD0[iGene] / (double)popsize - mnD0[iGene] * mnD0[iGene]; + if (sdD0[iGene] > 0.0) sdD0[iGene] = sqrt(sdD0[iGene]); else sdD0[iGene] = 0.0; + sdAlpha[iGene] = indTraitsSums.ssqAlpha[iGene] / (double)popsize - mnAlpha[iGene] * mnAlpha[iGene]; + if (sdAlpha[iGene] > 0.0) sdAlpha[iGene] = sqrt(sdAlpha[iGene]); else sdAlpha[iGene] = 0.0; + sdBeta[iGene] = indTraitsSums.ssqBeta[iGene] / (double)popsize - mnBeta[iGene] * mnBeta[iGene]; + if (sdBeta[iGene] > 0.0) sdBeta[iGene] = sqrt(sdBeta[iGene]); else sdBeta[iGene] = 0.0; } else { - sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + sdD0[iGene] = sdAlpha[iGene] = sdBeta[iGene] = 0.0; } } } @@ -897,44 +895,44 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, double sdDist1[2], sdDist2[2], sdProp1[2], sdStepL[2], sdRho[2]; double mnDP[2], mnGB[2], mnAlphaDB[2], mnBetaDB[2]; double sdDP[2], sdGB[2], sdAlphaDB[2], sdBetaDB[2]; - for (int g = 0; g < ngenes; g++) { - mnDist1[g] = mnDist2[g] = mnProp1[g] = mnStepL[g] = mnRho[g] = 0.0; - sdDist1[g] = sdDist2[g] = sdProp1[g] = sdStepL[g] = sdRho[g] = 0.0; - mnDP[g] = mnGB[g] = mnAlphaDB[g] = mnBetaDB[g] = 0.0; - sdDP[g] = sdGB[g] = sdAlphaDB[g] = sdBetaDB[g] = 0.0; + for (int iGene = 0; iGene < ngenes; iGene++) { + mnDist1[iGene] = mnDist2[iGene] = mnProp1[iGene] = mnStepL[iGene] = mnRho[iGene] = 0.0; + sdDist1[iGene] = sdDist2[iGene] = sdProp1[iGene] = sdStepL[iGene] = sdRho[iGene] = 0.0; + mnDP[iGene] = mnGB[iGene] = mnAlphaDB[iGene] = mnBetaDB[iGene] = 0.0; + sdDP[iGene] = sdGB[iGene] = sdAlphaDB[iGene] = sdBetaDB[iGene] = 0.0; // individuals may have been counted by sex if there was // sex dependency in another dispersal phase - if (ngenes == 2) popsize = poptraits.ninds[g]; - else popsize = poptraits.ninds[0] + poptraits.ninds[1]; + if (ngenes == 2) popsize = indTraitsSums.ninds[iGene]; + else popsize = indTraitsSums.ninds[0] + indTraitsSums.ninds[1]; if (popsize > 0) { - mnDist1[g] = poptraits.sumDist1[g] / (double)popsize; - mnDist2[g] = poptraits.sumDist2[g] / (double)popsize; - mnProp1[g] = poptraits.sumProp1[g] / (double)popsize; - mnStepL[g] = poptraits.sumStepL[g] / (double)popsize; - mnRho[g] = poptraits.sumRho[g] / (double)popsize; - mnDP[g] = poptraits.sumDP[g] / (double)popsize; - mnGB[g] = poptraits.sumGB[g] / (double)popsize; - mnAlphaDB[g] = poptraits.sumAlphaDB[g] / (double)popsize; - mnBetaDB[g] = poptraits.sumBetaDB[g] / (double)popsize; + mnDist1[iGene] = indTraitsSums.sumDist1[iGene] / (double)popsize; + mnDist2[iGene] = indTraitsSums.sumDist2[iGene] / (double)popsize; + mnProp1[iGene] = indTraitsSums.sumProp1[iGene] / (double)popsize; + mnStepL[iGene] = indTraitsSums.sumStepL[iGene] / (double)popsize; + mnRho[iGene] = indTraitsSums.sumRho[iGene] / (double)popsize; + mnDP[iGene] = indTraitsSums.sumDP[iGene] / (double)popsize; + mnGB[iGene] = indTraitsSums.sumGB[iGene] / (double)popsize; + mnAlphaDB[iGene] = indTraitsSums.sumAlphaDB[iGene] / (double)popsize; + mnBetaDB[iGene] = indTraitsSums.sumBetaDB[iGene] / (double)popsize; if (popsize > 1) { - sdDist1[g] = poptraits.ssqDist1[g] / (double)popsize - mnDist1[g] * mnDist1[g]; - if (sdDist1[g] > 0.0) sdDist1[g] = sqrt(sdDist1[g]); else sdDist1[g] = 0.0; - sdDist2[g] = poptraits.ssqDist2[g] / (double)popsize - mnDist2[g] * mnDist2[g]; - if (sdDist2[g] > 0.0) sdDist2[g] = sqrt(sdDist2[g]); else sdDist2[g] = 0.0; - sdProp1[g] = poptraits.ssqProp1[g] / (double)popsize - mnProp1[g] * mnProp1[g]; - if (sdProp1[g] > 0.0) sdProp1[g] = sqrt(sdProp1[g]); else sdProp1[g] = 0.0; - sdStepL[g] = poptraits.ssqStepL[g] / (double)popsize - mnStepL[g] * mnStepL[g]; - if (sdStepL[g] > 0.0) sdStepL[g] = sqrt(sdStepL[g]); else sdStepL[g] = 0.0; - sdRho[g] = poptraits.ssqRho[g] / (double)popsize - mnRho[g] * mnRho[g]; - if (sdRho[g] > 0.0) sdRho[g] = sqrt(sdRho[g]); else sdRho[g] = 0.0; - sdDP[g] = poptraits.ssqDP[g] / (double)popsize - mnDP[g] * mnDP[g]; - if (sdDP[g] > 0.0) sdDP[g] = sqrt(sdDP[g]); else sdDP[g] = 0.0; - sdGB[g] = poptraits.ssqGB[g] / (double)popsize - mnGB[g] * mnGB[g]; - if (sdGB[g] > 0.0) sdGB[g] = sqrt(sdGB[g]); else sdGB[g] = 0.0; - sdAlphaDB[g] = poptraits.ssqAlphaDB[g] / (double)popsize - mnAlphaDB[g] * mnAlphaDB[g]; - if (sdAlphaDB[g] > 0.0) sdAlphaDB[g] = sqrt(sdAlphaDB[g]); else sdAlphaDB[g] = 0.0; - sdBetaDB[g] = poptraits.ssqBetaDB[g] / (double)popsize - mnBetaDB[g] * mnBetaDB[g]; - if (sdBetaDB[g] > 0.0) sdBetaDB[g] = sqrt(sdBetaDB[g]); else sdBetaDB[g] = 0.0; + sdDist1[iGene] = indTraitsSums.ssqDist1[iGene] / (double)popsize - mnDist1[iGene] * mnDist1[iGene]; + if (sdDist1[iGene] > 0.0) sdDist1[iGene] = sqrt(sdDist1[iGene]); else sdDist1[iGene] = 0.0; + sdDist2[iGene] = indTraitsSums.ssqDist2[iGene] / (double)popsize - mnDist2[iGene] * mnDist2[iGene]; + if (sdDist2[iGene] > 0.0) sdDist2[iGene] = sqrt(sdDist2[iGene]); else sdDist2[iGene] = 0.0; + sdProp1[iGene] = indTraitsSums.ssqProp1[iGene] / (double)popsize - mnProp1[iGene] * mnProp1[iGene]; + if (sdProp1[iGene] > 0.0) sdProp1[iGene] = sqrt(sdProp1[iGene]); else sdProp1[iGene] = 0.0; + sdStepL[iGene] = indTraitsSums.ssqStepL[iGene] / (double)popsize - mnStepL[iGene] * mnStepL[iGene]; + if (sdStepL[iGene] > 0.0) sdStepL[iGene] = sqrt(sdStepL[iGene]); else sdStepL[iGene] = 0.0; + sdRho[iGene] = indTraitsSums.ssqRho[iGene] / (double)popsize - mnRho[iGene] * mnRho[iGene]; + if (sdRho[iGene] > 0.0) sdRho[iGene] = sqrt(sdRho[iGene]); else sdRho[iGene] = 0.0; + sdDP[iGene] = indTraitsSums.ssqDP[iGene] / (double)popsize - mnDP[iGene] * mnDP[iGene]; + if (sdDP[iGene] > 0.0) sdDP[iGene] = sqrt(sdDP[iGene]); else sdDP[iGene] = 0.0; + sdGB[iGene] = indTraitsSums.ssqGB[iGene] / (double)popsize - mnGB[iGene] * mnGB[iGene]; + if (sdGB[iGene] > 0.0) sdGB[iGene] = sqrt(sdGB[iGene]); else sdGB[iGene] = 0.0; + sdAlphaDB[iGene] = indTraitsSums.ssqAlphaDB[iGene] / (double)popsize - mnAlphaDB[iGene] * mnAlphaDB[iGene]; + if (sdAlphaDB[iGene] > 0.0) sdAlphaDB[iGene] = sqrt(sdAlphaDB[iGene]); else sdAlphaDB[iGene] = 0.0; + sdBetaDB[iGene] = indTraitsSums.ssqBetaDB[iGene] / (double)popsize - mnBetaDB[iGene] * mnBetaDB[iGene]; + if (sdBetaDB[iGene] > 0.0) sdBetaDB[iGene] = sqrt(sdBetaDB[iGene]); else sdBetaDB[iGene] = 0.0; } } } @@ -990,26 +988,26 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT // ngenes = 1; double mnS0[2], mnAlpha[2], mnBeta[2], sdS0[2], sdAlpha[2], sdBeta[2]; - for (int g = 0; g < ngenes; g++) { - mnS0[g] = mnAlpha[g] = mnBeta[g] = sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + for (int iGene = 0; iGene < ngenes; iGene++) { + mnS0[iGene] = mnAlpha[iGene] = mnBeta[iGene] = sdS0[iGene] = sdAlpha[iGene] = sdBeta[iGene] = 0.0; // individuals may have been counted by sex if there was // sex dependency in another dispersal phase - if (ngenes == 2) popsize = poptraits.ninds[g]; - else popsize = poptraits.ninds[0] + poptraits.ninds[1]; + if (ngenes == 2) popsize = indTraitsSums.ninds[iGene]; + else popsize = indTraitsSums.ninds[0] + indTraitsSums.ninds[1]; if (popsize > 0) { - mnS0[g] = poptraits.sumS0[g] / (double)popsize; - mnAlpha[g] = poptraits.sumAlphaS[g] / (double)popsize; - mnBeta[g] = poptraits.sumBetaS[g] / (double)popsize; + mnS0[iGene] = indTraitsSums.sumS0[iGene] / (double)popsize; + mnAlpha[iGene] = indTraitsSums.sumAlphaS[iGene] / (double)popsize; + mnBeta[iGene] = indTraitsSums.sumBetaS[iGene] / (double)popsize; if (popsize > 1) { - sdS0[g] = poptraits.ssqS0[g] / (double)popsize - mnS0[g] * mnS0[g]; - if (sdS0[g] > 0.0) sdS0[g] = sqrt(sdS0[g]); else sdS0[g] = 0.0; - sdAlpha[g] = poptraits.ssqAlphaS[g] / (double)popsize - mnAlpha[g] * mnAlpha[g]; - if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; - sdBeta[g] = poptraits.ssqBetaS[g] / (double)popsize - mnBeta[g] * mnBeta[g]; - if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + sdS0[iGene] = indTraitsSums.ssqS0[iGene] / (double)popsize - mnS0[iGene] * mnS0[iGene]; + if (sdS0[iGene] > 0.0) sdS0[iGene] = sqrt(sdS0[iGene]); else sdS0[iGene] = 0.0; + sdAlpha[iGene] = indTraitsSums.ssqAlphaS[iGene] / (double)popsize - mnAlpha[iGene] * mnAlpha[iGene]; + if (sdAlpha[iGene] > 0.0) sdAlpha[iGene] = sqrt(sdAlpha[iGene]); else sdAlpha[iGene] = 0.0; + sdBeta[iGene] = indTraitsSums.ssqBetaS[iGene] / (double)popsize - mnBeta[iGene] * mnBeta[iGene]; + if (sdBeta[iGene] > 0.0) sdBeta[iGene] = sqrt(sdBeta[iGene]); else sdBeta[iGene] = 0.0; } else { - sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + sdS0[iGene] = sdAlpha[iGene] = sdBeta[iGene] = 0.0; } } } @@ -1029,27 +1027,28 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, } } } + if (pSpecies->getNumberOfAdaptiveTraits() > 0) { ngenes = pSpecies->isDiploid() + 1; double mnFitness[2], sdFitness[2]; - for (int g = 0; g < ngenes; g++) { - mnFitness[g] = sdFitness[g] = 0.0; + for (int iGene = 0; iGene < ngenes; iGene++) { + mnFitness[iGene] = sdFitness[iGene] = 0.0; - if (ngenes == 2) popsize = poptraits.ninds[g]; - else popsize = poptraits.ninds[0] + poptraits.ninds[1]; + if (ngenes == 2) popsize = indTraitsSums.ninds[iGene]; + else popsize = indTraitsSums.ninds[0] + indTraitsSums.ninds[1]; if (popsize > 0) { - mnFitness[g] = poptraits.sumFitness[g] / (double)popsize; + mnFitness[iGene] = indTraitsSums.sumFitness[iGene] / (double)popsize; if (popsize > 1) { - sdFitness[g] = poptraits.ssqFitness[g] / (double)popsize - mnFitness[g] * mnFitness[g]; - if (sdFitness[g] > 0.0) sdFitness[g] = sqrt(sdFitness[g]); else sdFitness[g] = 0.0; + sdFitness[iGene] = indTraitsSums.ssqFitness[iGene] / (double)popsize - mnFitness[iGene] * mnFitness[iGene]; + if (sdFitness[iGene] > 0.0) sdFitness[iGene] = sqrt(sdFitness[iGene]); else sdFitness[iGene] = 0.0; } else { - sdFitness[g] = 0.0; + sdFitness[iGene] = 0.0; } } } if (writefile) { - if (NSEXES > 1) { + if (maxNbSexes > 1) { outtraits << "\t" << mnFitness[0] << "\t" << sdFitness[0]; outtraits << "\t" << mnFitness[1] << "\t" << sdFitness[1]; } @@ -1062,35 +1061,40 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT if (writefile) outtraits << endl; - for (int s = 0; s < NSEXES; s++) { - ts.ninds[s] += poptraits.ninds[s]; - ts.sumD0[s] += poptraits.sumD0[s]; ts.ssqD0[s] += poptraits.ssqD0[s]; - ts.sumAlpha[s] += poptraits.sumAlpha[s]; ts.ssqAlpha[s] += poptraits.ssqAlpha[s]; - ts.sumBeta[s] += poptraits.sumBeta[s]; ts.ssqBeta[s] += poptraits.ssqBeta[s]; - ts.sumDist1[s] += poptraits.sumDist1[s]; ts.ssqDist1[s] += poptraits.ssqDist1[s]; - ts.sumDist2[s] += poptraits.sumDist2[s]; ts.ssqDist2[s] += poptraits.ssqDist2[s]; - ts.sumProp1[s] += poptraits.sumProp1[s]; ts.ssqProp1[s] += poptraits.ssqProp1[s]; - ts.sumDP[s] += poptraits.sumDP[s]; ts.ssqDP[s] += poptraits.ssqDP[s]; - ts.sumGB[s] += poptraits.sumGB[s]; ts.ssqGB[s] += poptraits.ssqGB[s]; - ts.sumAlphaDB[s] += poptraits.sumAlphaDB[s]; ts.ssqAlphaDB[s] += poptraits.ssqAlphaDB[s]; - ts.sumBetaDB[s] += poptraits.sumBetaDB[s]; ts.ssqBetaDB[s] += poptraits.ssqBetaDB[s]; - ts.sumStepL[s] += poptraits.sumStepL[s]; ts.ssqStepL[s] += poptraits.ssqStepL[s]; - ts.sumRho[s] += poptraits.sumRho[s]; ts.ssqRho[s] += poptraits.ssqRho[s]; - ts.sumS0[s] += poptraits.sumS0[s]; ts.ssqS0[s] += poptraits.ssqS0[s]; - ts.sumAlphaS[s] += poptraits.sumAlphaS[s]; ts.ssqAlphaS[s] += poptraits.ssqAlphaS[s]; - ts.sumBetaS[s] += poptraits.sumBetaS[s]; ts.ssqBetaS[s] += poptraits.ssqBetaS[s]; - ts.sumFitness[s] += poptraits.sumFitness[s]; ts.ssqFitness[s] += poptraits.ssqFitness[s]; -#if RSDEBUG - //DEBUGLOG << "SubCommunity::outTraits(): i=" << i << " popns[i]=" << popns[i] - // << " s=" << s - //// << " poptraits.sumRho[s]= " << poptraits.sumRho[s] - //// << " ts.sumRho[s]= " << ts.sumRho[s] - // << " poptraits.sumDP[s]= " << poptraits.sumDP[s] << " poptraits.ssqDP[s]= " << poptraits.ssqDP[s] - // << " ts.sumDP[s]= " << ts.sumDP[s] << " ts.ssqDP[s]= " << ts.ssqDP[s] - // << " poptraits.sumGB[s]= " << poptraits.sumGB[s] << " poptraits.ssqGB[s]= " << poptraits.ssqGB[s] - // << " ts.sumGB[s]= " << ts.sumGB[s] << " ts.ssqGB[s]= " << ts.ssqGB[s] - // << endl; -#endif + for (int iSex = 0; iSex < maxNbSexes; iSex++) { + ts.ninds[iSex] += indTraitsSums.ninds[iSex]; + ts.sumD0[iSex] += indTraitsSums.sumD0[iSex]; + ts.ssqD0[iSex] += indTraitsSums.ssqD0[iSex]; + ts.sumAlpha[iSex] += indTraitsSums.sumAlpha[iSex]; + ts.ssqAlpha[iSex] += indTraitsSums.ssqAlpha[iSex]; + ts.sumBeta[iSex] += indTraitsSums.sumBeta[iSex]; + ts.ssqBeta[iSex] += indTraitsSums.ssqBeta[iSex]; + ts.sumDist1[iSex] += indTraitsSums.sumDist1[iSex]; + ts.ssqDist1[iSex] += indTraitsSums.ssqDist1[iSex]; + ts.sumDist2[iSex] += indTraitsSums.sumDist2[iSex]; + ts.ssqDist2[iSex] += indTraitsSums.ssqDist2[iSex]; + ts.sumProp1[iSex] += indTraitsSums.sumProp1[iSex]; + ts.ssqProp1[iSex] += indTraitsSums.ssqProp1[iSex]; + ts.sumDP[iSex] += indTraitsSums.sumDP[iSex]; + ts.ssqDP[iSex] += indTraitsSums.ssqDP[iSex]; + ts.sumGB[iSex] += indTraitsSums.sumGB[iSex]; + ts.ssqGB[iSex] += indTraitsSums.ssqGB[iSex]; + ts.sumAlphaDB[iSex] += indTraitsSums.sumAlphaDB[iSex]; + ts.ssqAlphaDB[iSex] += indTraitsSums.ssqAlphaDB[iSex]; + ts.sumBetaDB[iSex] += indTraitsSums.sumBetaDB[iSex]; + ts.ssqBetaDB[iSex] += indTraitsSums.ssqBetaDB[iSex]; + ts.sumStepL[iSex] += indTraitsSums.sumStepL[iSex]; + ts.ssqStepL[iSex] += indTraitsSums.ssqStepL[iSex]; + ts.sumRho[iSex] += indTraitsSums.sumRho[iSex]; + ts.ssqRho[iSex] += indTraitsSums.ssqRho[iSex]; + ts.sumS0[iSex] += indTraitsSums.sumS0[iSex]; + ts.ssqS0[iSex] += indTraitsSums.ssqS0[iSex]; + ts.sumAlphaS[iSex] += indTraitsSums.sumAlphaS[iSex]; + ts.ssqAlphaS[iSex] += indTraitsSums.ssqAlphaS[iSex]; + ts.sumBetaS[iSex] += indTraitsSums.sumBetaS[iSex]; + ts.ssqBetaS[iSex] += indTraitsSums.ssqBetaS[iSex]; + ts.sumFitness[iSex] += indTraitsSums.sumFitness[iSex]; + ts.ssqFitness[iSex] += indTraitsSums.ssqFitness[iSex]; } } } diff --git a/SubCommunity.h b/SubCommunity.h index f24830d..0bf9ba5 100644 --- a/SubCommunity.h +++ b/SubCommunity.h @@ -57,7 +57,7 @@ using namespace std; //--------------------------------------------------------------------------- struct traitCanvas { // canvases for drawing variable traits - int* pcanvas[NTRAITS]; // dummy variables for batch version + int* pcanvas[maxNbTraitsGUI]; // dummy variables for batch version }; class SubCommunity { From e7615e562eca43c510966b016ab46508229c8576 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 23 Feb 2024 13:52:51 +0000 Subject: [PATCH 059/332] indentation and better names --- Species.cpp | 21 ++++++++++++++------- Species.h | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Species.cpp b/Species.cpp index a07dca4..60f0cc3 100644 --- a/Species.cpp +++ b/Species.cpp @@ -177,9 +177,12 @@ void Species::setStage(const stageParams s) { if (s.maxAge >= 1) maxAge = s.maxAge; if (s.survival >= 0 && s.survival <= 2) survival = s.survival; if (s.probRep > 0.0 && s.probRep <= 1.0) probRep = s.probRep; - fecDens = s.fecDens; fecStageDens = s.fecStageDens; - devDens = s.devDens; devStageDens = s.devStageDens; - survDens = s.survDens; survStageDens = s.survStageDens; + fecDens = s.fecDens; + fecStageDens = s.fecStageDens; + devDens = s.devDens; + devStageDens = s.devStageDens; + survDens = s.survDens; + survStageDens = s.survStageDens; disperseOnLoss = s.disperseOnLoss; } @@ -541,12 +544,16 @@ float Species::getEmigD0(short stg, short sex) { // Transfer functions -void Species::setTrfr(const trfrRules t) { - moveModel = t.moveModel; stgDepTrfr = t.stgDep; sexDepTrfr = t.sexDep; - distMort = t.distMort; indVarTrfr = t.indVar; +void Species::setTrfrRules(const trfrRules t) { + moveModel = t.moveModel; + stgDepTrfr = t.stgDep; + sexDepTrfr = t.sexDep; + distMort = t.distMort; + indVarTrfr = t.indVar; twinKern = t.twinKern; habMort = t.habMort; - moveType = t.moveType; costMap = t.costMap; + moveType = t.moveType; + costMap = t.costMap; //setGenome(); } diff --git a/Species.h b/Species.h index b1e3256..f4a141a 100644 --- a/Species.h +++ b/Species.h @@ -333,7 +333,7 @@ class Species { // transfer parameter functions - void setTrfr( // Set transfer rules + void setTrfrRules( // Set transfer rules const trfrRules // structure holding transfer rules ); trfrRules getTrfr(void); // Get transfer rules From abc9492cf3b8b005db557582ab02f1a666710b7e Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 23 Feb 2024 15:58:45 +0000 Subject: [PATCH 060/332] ReadEmigFile, CheckEmigFile are a slightly better place --- Community.cpp | 16 ++++++++-------- Individual.cpp | 2 +- Model.cpp | 10 +++++----- Population.cpp | 44 ++++++++++++++++++++++---------------------- Species.cpp | 26 +++++++++++++++++--------- Species.h | 8 ++++---- SubCommunity.cpp | 16 ++++++++-------- 7 files changed, 65 insertions(+), 57 deletions(-) diff --git a/Community.cpp b/Community.cpp index 5df18f6..ddc5fbd 100644 --- a/Community.cpp +++ b/Community.cpp @@ -673,9 +673,9 @@ bool Community::outRangeHeaders(Species* pSpecies, int landNr) // NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER // ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL - demogrParams dem = pSpecies->getDemogr(); - stageParams sstruct = pSpecies->getStage(); - emigRules emig = pSpecies->getEmig(); + demogrParams dem = pSpecies->getDemogrParams(); + stageParams sstruct = pSpecies->getStageParams(); + emigRules emig = pSpecies->getEmigRules(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); @@ -789,9 +789,9 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) // NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER // ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL - demogrParams dem = pSpecies->getDemogr(); - stageParams sstruct = pSpecies->getStage(); - emigRules emig = pSpecies->getEmig(); + demogrParams dem = pSpecies->getDemogrParams(); + stageParams sstruct = pSpecies->getStageParams(); + emigRules emig = pSpecies->getEmigRules(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); @@ -1290,7 +1290,7 @@ void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int //simView v = paramsSim->getViews(); //landData land = pLandscape->getLandData(); //landOrigin origin = pLandscape->getOrigin(); - emigRules emig = pSpecies->getEmig(); + emigRules emig = pSpecies->getEmigRules(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); double mn, sd; @@ -1500,7 +1500,7 @@ bool Community::outTraitsRowsHeaders(Species* pSpecies, int landNr) { } string name; - emigRules emig = pSpecies->getEmig(); + emigRules emig = pSpecies->getEmigRules(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); simParams sim = paramsSim->getSim(); diff --git a/Individual.cpp b/Individual.cpp index f15dff8..21a5706 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -233,7 +233,7 @@ void Individual::setUpGenes(Species* pSpecies, int resol) { void Individual::setQTLPhenotypes(Species* pSpecies, int resol) { - const emigRules emig = pSpecies->getEmig(); + const emigRules emig = pSpecies->getEmigRules(); const trfrRules trfr = pSpecies->getTrfr(); const settleType sett = pSpecies->getSettle(); diff --git a/Model.cpp b/Model.cpp index cc2ebd6..9668abf 100644 --- a/Model.cpp +++ b/Model.cpp @@ -40,8 +40,8 @@ int RunModel(Landscape* pLandscape, int seqsim) landParams ppLand = pLandscape->getLandParams(); envGradParams grad = paramsGrad->getGradient(); envStochParams env = paramsStoch->getStoch(); - demogrParams dem = pSpecies->getDemogr(); - stageParams sstruct = pSpecies->getStage(); + demogrParams dem = pSpecies->getDemogrParams(); + stageParams sstruct = pSpecies->getStageParams(); //emigRules emig = pSpecies->getEmig(); trfrRules trfr = pSpecies->getTrfr(); initParams init = paramsInit->getInit(); @@ -905,9 +905,9 @@ void OutParameters(Landscape* pLandscape) genLandParams ppGenLand = pLandscape->getGenLandParams(); envGradParams grad = paramsGrad->getGradient(); envStochParams env = paramsStoch->getStoch(); - demogrParams dem = pSpecies->getDemogr(); - stageParams sstruct = pSpecies->getStage(); - emigRules emig = pSpecies->getEmig(); + demogrParams dem = pSpecies->getDemogrParams(); + stageParams sstruct = pSpecies->getStageParams(); + emigRules emig = pSpecies->getEmigRules(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); settleRules srules; diff --git a/Population.cpp b/Population.cpp index e1dbf44..7bb3737 100644 --- a/Population.cpp +++ b/Population.cpp @@ -64,9 +64,9 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) // << " added population to patch " << endl; #endif - demogrParams dem = pSpecies->getDemogr(); - stageParams sstruct = pSpecies->getStage(); - emigRules emig = pSpecies->getEmig(); + demogrParams dem = pSpecies->getDemogrParams(); + stageParams sstruct = pSpecies->getStageParams(); + emigRules emig = pSpecies->getEmigRules(); trfrRules trfr = pSpecies->getTrfr(); //trfrSMSTraits sms = pSpecies->getSMSTraits(); settleType sett = pSpecies->getSettle(); @@ -236,7 +236,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { ts.sumFitness[sex] = ts.ssqFitness[sex] = 0.0; } - emigRules emig = pSpecies->getEmig(); + emigRules emig = pSpecies->getEmigRules(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); @@ -463,7 +463,7 @@ popStats Population::getStats(void) int ninds; float fec; bool breeders[2] = { false, false }; - demogrParams dem = pSpecies->getDemogr(); + demogrParams dem = pSpecies->getDemogrParams(); p.pSpecies = pSpecies; p.pPatch = pPatch; p.spNum = pSpecies->getSpNum(); @@ -577,9 +577,9 @@ void Population::reproduction(const float localK, const float envval, const int //envGradParams grad = paramsGrad->getGradient(); envStochParams env = paramsStoch->getStoch(); - demogrParams dem = pSpecies->getDemogr(); - stageParams sstruct = pSpecies->getStage(); - emigRules emig = pSpecies->getEmig(); + demogrParams dem = pSpecies->getDemogrParams(); + stageParams sstruct = pSpecies->getStageParams(); + emigRules emig = pSpecies->getEmigRules(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); @@ -896,7 +896,7 @@ void Population::fledge(void) // << " njuvs=" << (int)juvs.size() // << endl; #endif - demogrParams dem = pSpecies->getDemogr(); + demogrParams dem = pSpecies->getDemogrParams(); if (dem.stageStruct) { // juveniles are added to the individuals vector inds.insert(inds.end(), juvs.begin(), juvs.end()); @@ -962,9 +962,9 @@ void Population::emigration(float localK) { int nsexes; double disp, Pdisp, NK; - demogrParams dem = pSpecies->getDemogr(); - stageParams sstruct = pSpecies->getStage(); - emigRules emig = pSpecies->getEmig(); + demogrParams dem = pSpecies->getDemogrParams(); + stageParams sstruct = pSpecies->getStageParams(); + emigRules emig = pSpecies->getEmigRules(); emigTraits eparams; indStats ind; @@ -1505,8 +1505,8 @@ void Population::survival0(float localK, short option0, short option1) // 1 - development and survival // 2 - survival only (when survival is annual) densDepParams ddparams = pSpecies->getDensDep(); - demogrParams dem = pSpecies->getDemogr(); - stageParams sstruct = pSpecies->getStage(); + demogrParams dem = pSpecies->getDemogrParams(); + stageParams sstruct = pSpecies->getStageParams(); // get surrent population size int ninds = (int)inds.size(); @@ -1747,7 +1747,7 @@ void Population::survival1(void) void Population::ageIncrement(void) { int ninds = (int)inds.size(); - stageParams sstruct = pSpecies->getStage(); + stageParams sstruct = pSpecies->getStageParams(); for (int i = 0; i < ninds; i++) { inds[i]->ageIncrement(sstruct.maxAge); } @@ -1797,8 +1797,8 @@ bool Population::outPopHeaders(int landNr, bool patchModel) { // NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER // ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL - demogrParams dem = pSpecies->getDemogr(); - stageParams sstruct = pSpecies->getStage(); + demogrParams dem = pSpecies->getDemogrParams(); + stageParams sstruct = pSpecies->getStageParams(); if (sim.batchMode) { name = paramsSim->getDir(2) + "Batch" + Int2Str(sim.batchNum) + "_" @@ -1844,7 +1844,7 @@ void Population::outPopulation(int rep, int yr, int gen, float eps, Cell* pCell; // NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER - demogrParams dem = pSpecies->getDemogr(); + demogrParams dem = pSpecies->getDemogrParams(); popStats p; outPop << rep << "\t" << yr << "\t" << gen; @@ -1974,8 +1974,8 @@ void Population::outIndsHeaders(int rep, int landNr, bool patchModel) } string name; - demogrParams dem = pSpecies->getDemogr(); - emigRules emig = pSpecies->getEmig(); + demogrParams dem = pSpecies->getDemogrParams(); + emigRules emig = pSpecies->getEmigRules(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); simParams sim = paramsSim->getSim(); @@ -2038,8 +2038,8 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, pathSteps steps; Cell* pCell; landParams ppLand = pLandscape->getLandParams(); - demogrParams dem = pSpecies->getDemogr(); - emigRules emig = pSpecies->getEmig(); + demogrParams dem = pSpecies->getDemogrParams(); + emigRules emig = pSpecies->getEmigRules(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); short spNum = pSpecies->getSpNum(); diff --git a/Species.cpp b/Species.cpp index 60f0cc3..1d3e338 100644 --- a/Species.cpp +++ b/Species.cpp @@ -120,7 +120,7 @@ void Species::setDemogr(const demogrParams d) { if (d.lambda > 0.0) lambda = d.lambda; } -demogrParams Species::getDemogr(void) { +demogrParams Species::getDemogrParams(void) { demogrParams d; d.repType = repType; d.repSeasons = repSeasons; @@ -186,7 +186,7 @@ void Species::setStage(const stageParams s) { disperseOnLoss = s.disperseOnLoss; } -stageParams Species::getStage(void) { +stageParams Species::getStageParams(void) { stageParams s; s.nStages = nStages; s.repInterval = repInterval; s.maxAge = maxAge; s.survival = survival; s.probRep = probRep; @@ -499,31 +499,39 @@ set Species::getChromosomeEnds() const { //--------------------------------------------------------------------------- // Emigration functions -void Species::setEmig(const emigRules e) { - densDepEmig = e.densDep; stgDepEmig = e.stgDep; sexDepEmig = e.sexDep; +void Species::setEmigRules(const emigRules e) { + densDepEmig = e.densDep; + stgDepEmig = e.stgDep; + sexDepEmig = e.sexDep; indVarEmig = e.indVar; if (e.emigStage >= 0) emigStage = e.emigStage; //setGenome(); } -emigRules Species::getEmig(void) { +emigRules Species::getEmigRules(void) { emigRules e; - e.densDep = densDepEmig; e.stgDep = stgDepEmig; e.sexDep = sexDepEmig; - e.indVar = indVarEmig; e.emigStage = emigStage; + e.densDep = densDepEmig; + e.stgDep = stgDepEmig; + e.sexDep = sexDepEmig; + e.indVar = indVarEmig; + e.emigStage = emigStage; return e; } void Species::setEmigTraits(const short stg, const short sex, const emigTraits e) { if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { if (e.d0 >= 0.0 && e.d0 <= 1.0) d0[stg][sex] = e.d0; - alphaEmig[stg][sex] = e.alpha; betaEmig[stg][sex] = e.beta; + alphaEmig[stg][sex] = e.alpha; + betaEmig[stg][sex] = e.beta; } } emigTraits Species::getEmigTraits(short stg, short sex) { emigTraits e; if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { - e.d0 = d0[stg][sex]; e.alpha = alphaEmig[stg][sex]; e.beta = betaEmig[stg][sex]; + e.d0 = d0[stg][sex]; + e.alpha = alphaEmig[stg][sex]; + e.beta = betaEmig[stg][sex]; } else { e.d0 = e.alpha = e.beta = 0.0; diff --git a/Species.h b/Species.h index f4a141a..648d7d8 100644 --- a/Species.h +++ b/Species.h @@ -187,11 +187,11 @@ class Species { void setStage( // Set stage structure parameters const stageParams // structure holding stage structure parameters ); - stageParams getStage(void); // Get stage structure parameters + stageParams getStageParams(void); // Get stage structure parameters void setDemogr( // Set general demographic parameters const demogrParams // structure holding general demographic parameters ); - demogrParams getDemogr(void); // Get general demographic parameters + demogrParams getDemogrParams(void); // Get general demographic parameters short getRepType(void); bool stageStructured(void); void setDensDep( // Set demographic density dependence coefficients @@ -313,10 +313,10 @@ class Species { // emigration parameter functions - void setEmig( // Set emigration rules + void setEmigRules( // Set emigration rules const emigRules // structure holding emigration rules ); - emigRules getEmig(void); // Get emigration rules + emigRules getEmigRules(void); // Get emigration rules void setEmigTraits( // Set emigration trait parameters const short, // stage const short, // sex diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 4e7dce0..3a3d96e 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -118,9 +118,9 @@ void SubCommunity::initialInd(Landscape* pLandscape, Species* pSpecies, Patch* pPatch, Cell* pCell, int ix) { - demogrParams dem = pSpecies->getDemogr(); - stageParams sstruct = pSpecies->getStage(); - emigRules emig = pSpecies->getEmig(); + demogrParams dem = pSpecies->getDemogrParams(); + stageParams sstruct = pSpecies->getStageParams(); + emigRules emig = pSpecies->getEmigRules(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); short stg, age, repInt; @@ -267,9 +267,9 @@ void SubCommunity::patchChange(void) { if (localK <= 0.0) { // patch in dynamic landscape has become unsuitable for (int i = 0; i < npops; i++) { // all populations pSpecies = popns[i]->getSpecies(); - demogrParams dem = pSpecies->getDemogr(); + demogrParams dem = pSpecies->getDemogrParams(); if (dem.stageStruct) { - stageParams sstruct = pSpecies->getStage(); + stageParams sstruct = pSpecies->getStageParams(); if (sstruct.disperseOnLoss) popns[i]->allEmigrate(); else popns[i]->extirpate(); } @@ -660,7 +660,7 @@ bool SubCommunity::outTraitsHeaders(Landscape* pLandscape, Species* pSpecies, in } string name; - emigRules emig = pSpecies->getEmig(); + emigRules emig = pSpecies->getEmigRules(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); simParams sim = paramsSim->getSim(); @@ -804,8 +804,8 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, localK = pPatch->getK(); if (localK > 0.0 && popns[iPop]->getNInds() > 0) { pSpecies = popns[iPop]->getSpecies(); - demogrParams dem = pSpecies->getDemogr(); - emigRules emig = pSpecies->getEmig(); + demogrParams dem = pSpecies->getDemogrParams(); + emigRules emig = pSpecies->getEmigRules(); trfrRules trfr = pSpecies->getTrfr(); settleType sett = pSpecies->getSettle(); indTraitsSums = popns[iPop]->getIndTraitsSums(pSpecies); From 705b3f1ef3d725564ac514868a11197556b0b8ae Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 26 Feb 2024 18:34:42 +0000 Subject: [PATCH 061/332] progress towards making ReadTransfer a better place --- Community.cpp | 8 ++++---- Individual.cpp | 16 ++++++++-------- Individual.h | 4 ++-- Model.cpp | 8 ++++---- Population.cpp | 16 ++++++++-------- Species.cpp | 18 +++++++++--------- Species.h | 18 +++++++++--------- SubCommunity.cpp | 6 +++--- 8 files changed, 47 insertions(+), 47 deletions(-) diff --git a/Community.cpp b/Community.cpp index ddc5fbd..d520272 100644 --- a/Community.cpp +++ b/Community.cpp @@ -676,7 +676,7 @@ bool Community::outRangeHeaders(Species* pSpecies, int landNr) demogrParams dem = pSpecies->getDemogrParams(); stageParams sstruct = pSpecies->getStageParams(); emigRules emig = pSpecies->getEmigRules(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); #if RSDEBUG @@ -792,7 +792,7 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) demogrParams dem = pSpecies->getDemogrParams(); stageParams sstruct = pSpecies->getStageParams(); emigRules emig = pSpecies->getEmigRules(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); outrange << rep << "\t" << yr << "\t" << gen; @@ -1291,7 +1291,7 @@ void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int //landData land = pLandscape->getLandData(); //landOrigin origin = pLandscape->getOrigin(); emigRules emig = pSpecies->getEmigRules(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); double mn, sd; @@ -1501,7 +1501,7 @@ bool Community::outTraitsRowsHeaders(Species* pSpecies, int landNr) { string name; emigRules emig = pSpecies->getEmigRules(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); simParams sim = paramsSim->getSim(); diff --git a/Individual.cpp b/Individual.cpp index 21a5706..4651d09 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -234,7 +234,7 @@ void Individual::setUpGenes(Species* pSpecies, int resol) { void Individual::setQTLPhenotypes(Species* pSpecies, int resol) { const emigRules emig = pSpecies->getEmigRules(); - const trfrRules trfr = pSpecies->getTrfr(); + const transferRules trfr = pSpecies->getTransferRules(); const settleType sett = pSpecies->getSettle(); // record phenotypic traits @@ -246,7 +246,7 @@ void Individual::setQTLPhenotypes(Species* pSpecies, int resol) { this->setSettlementTraits(pSpecies, sett.sexDep); } -void Individual::setTransferTraits(Species* pSpecies, trfrRules trfr, int resol) { +void Individual::setTransferTraits(Species* pSpecies, transferRules trfr, int resol) { if (trfr.moveModel) { if (trfr.moveType == 1) { setSMSTraits(pSpecies); @@ -414,7 +414,7 @@ emigTraits Individual::getEmigTraits(void) { // Set phenotypic transfer by kernel traits void Individual::setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel, int resol) { - trfrKernTraits k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; + trfrKernelParams k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; if (sexDep && this->sex == MAL) { k.meanDist1 = getTrait(KERNEL_MEANDIST_1_M)->express(); @@ -453,8 +453,8 @@ void Individual::setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel // Get phenotypic emigration traits -trfrKernTraits Individual::getKernTraits(void) { - trfrKernTraits k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; +trfrKernelParams Individual::getKernTraits(void) { + trfrKernelParams k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; if (pTrfrData != 0) { auto& pKernel = dynamic_cast(*pTrfrData); @@ -625,7 +625,7 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, int dispersing = 1; double xrand, yrand, meandist, dist, r1, rndangle, nx, ny; float localK; - trfrKernTraits kern; + trfrKernelParams kern; Cell* pCell; Patch* pPatch; locn loc = pCurrCell->getLocn(); @@ -633,7 +633,7 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, landData land = pLandscape->getLandData(); bool usefullkernel = pSpecies->useFullKernel(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); settleRules sett = pSpecies->getSettRules(stage, sex); pCell = NULL; @@ -833,7 +833,7 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, landData land = pLandscape->getLandData(); simParams sim = paramsSim->getSim(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); trfrCRWTraits movt = pSpecies->getCRWTraits(); settleSteps settsteps = pSpecies->getSteps(stage, sex); diff --git a/Individual.h b/Individual.h index 1fa1bf8..443cb44 100644 --- a/Individual.h +++ b/Individual.h @@ -265,13 +265,13 @@ class Individual { void setEmigTraits(Species* pSpecies, bool sexDep, bool densityDep); - void setTransferTraits(Species* pSpecies, trfrRules trfr, int resol); + void setTransferTraits(Species* pSpecies, transferRules trfr, int resol); emigTraits getEmigTraits(void); // Get phenotypic emigration traits void setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel, int resol); - trfrKernTraits getKernTraits(void); // Get phenotypic transfer by kernel traits + trfrKernelParams getKernTraits(void); // Get phenotypic transfer by kernel traits void setSMSTraits(Species* pSpecies); diff --git a/Model.cpp b/Model.cpp index 9668abf..d24d24f 100644 --- a/Model.cpp +++ b/Model.cpp @@ -43,7 +43,7 @@ int RunModel(Landscape* pLandscape, int seqsim) demogrParams dem = pSpecies->getDemogrParams(); stageParams sstruct = pSpecies->getStageParams(); //emigRules emig = pSpecies->getEmig(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); initParams init = paramsInit->getInit(); simParams sim = paramsSim->getSim(); simView v = paramsSim->getViews(); @@ -705,7 +705,7 @@ int RunModel(Landscape* pLandscape, int seqsim) pLandscape->resetPatches(); } if (ppLand.dynamic) { - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); if (trfr.moveModel && trfr.moveType == 1) { // SMS if (ixcostchg > 0) { // apply any cost changes to reset landscape to original configuration @@ -908,7 +908,7 @@ void OutParameters(Landscape* pLandscape) demogrParams dem = pSpecies->getDemogrParams(); stageParams sstruct = pSpecies->getStageParams(); emigRules emig = pSpecies->getEmigRules(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); settleRules srules; settleSteps ssteps; @@ -1530,7 +1530,7 @@ void OutParameters(Landscape* pLandscape) else { // kernel string meandist = "MEAN DISTANCE"; string probkern = "PROB. KERNEL I"; - trfrKernTraits kern0, kern1; + trfrKernelParams kern0, kern1; outPar << "dispersal kernel" << endl << "TYPE: \t"; if (trfr.twinKern) outPar << "double "; outPar << "negative exponential" << endl; diff --git a/Population.cpp b/Population.cpp index 7bb3737..9038272 100644 --- a/Population.cpp +++ b/Population.cpp @@ -67,7 +67,7 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) demogrParams dem = pSpecies->getDemogrParams(); stageParams sstruct = pSpecies->getStageParams(); emigRules emig = pSpecies->getEmigRules(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); //trfrSMSTraits sms = pSpecies->getSMSTraits(); settleType sett = pSpecies->getSettle(); initParams init = paramsInit->getInit(); @@ -237,7 +237,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { } emigRules emig = pSpecies->getEmigRules(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); int ninds = (int)inds.size(); @@ -294,7 +294,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { } } else { - trfrKernTraits k = inds[iInd]->getKernTraits(); + trfrKernelParams k = inds[iInd]->getKernTraits(); if (trfr.sexDep) g = sex; else g = 0; ts.sumDist1[g] += k.meanDist1; @@ -580,7 +580,7 @@ void Population::reproduction(const float localK, const float envval, const int demogrParams dem = pSpecies->getDemogrParams(); stageParams sstruct = pSpecies->getStageParams(); emigRules emig = pSpecies->getEmigRules(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); if (dem.repType == 0) nsexes = 1; else nsexes = 2; @@ -1175,7 +1175,7 @@ int Population::transfer(Landscape* pLandscape, short landIx) landData ppLand = pLandscape->getLandData(); short reptype = pSpecies->getRepType(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); settleType settletype = pSpecies->getSettle(); settleRules sett; settleTraits settDD; @@ -1976,7 +1976,7 @@ void Population::outIndsHeaders(int rep, int landNr, bool patchModel) string name; demogrParams dem = pSpecies->getDemogrParams(); emigRules emig = pSpecies->getEmigRules(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); simParams sim = paramsSim->getSim(); @@ -2040,7 +2040,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, landParams ppLand = pLandscape->getLandParams(); demogrParams dem = pSpecies->getDemogrParams(); emigRules emig = pSpecies->getEmigRules(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); short spNum = pSpecies->getSpNum(); @@ -2128,7 +2128,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, } // end of CRW } else { // kernel - trfrKernTraits k = inds[i]->getKernTraits(); + trfrKernelParams k = inds[i]->getKernTraits(); if (trfr.twinKern) { outInds << "\t" << k.meanDist1 << "\t" << k.meanDist2 << "\t" << k.probKern1; diff --git a/Species.cpp b/Species.cpp index 1d3e338..1b84c20 100644 --- a/Species.cpp +++ b/Species.cpp @@ -552,7 +552,7 @@ float Species::getEmigD0(short stg, short sex) { // Transfer functions -void Species::setTrfrRules(const trfrRules t) { +void Species::setTrfrRules(const transferRules t) { moveModel = t.moveModel; stgDepTrfr = t.stgDep; sexDepTrfr = t.sexDep; @@ -565,8 +565,8 @@ void Species::setTrfrRules(const trfrRules t) { //setGenome(); } -trfrRules Species::getTrfr(void) { - trfrRules t; +transferRules Species::getTransferRules(void) { + transferRules t; t.moveModel = moveModel; t.stgDep = stgDepTrfr; t.sexDep = sexDepTrfr; t.distMort = distMort; t.indVar = indVarTrfr; t.twinKern = twinKern; @@ -582,7 +582,7 @@ void Species::setFullKernel(bool k) { bool Species::useFullKernel(void) { return fullKernel; } void Species::setKernTraits(const short stg, const short sex, - const trfrKernTraits k, const int resol) + const trfrKernelParams k, const int resol) { if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { if (k.meanDist1 > 0.0 && k.meanDist1 >= (float)resol) meanDist1[stg][sex] = k.meanDist1; @@ -591,8 +591,8 @@ void Species::setKernTraits(const short stg, const short sex, } } -trfrKernTraits Species::getKernTraits(short stg, short sex) { - trfrKernTraits k; +trfrKernelParams Species::getKernTraits(short stg, short sex) { + trfrKernelParams k; if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { k.meanDist1 = meanDist1[stg][sex]; k.meanDist2 = meanDist2[stg][sex]; @@ -616,7 +616,7 @@ trfrMortParams Species::getMortParams(void) { return m; } -void Species::setMovtTraits(const trfrMovtTraits m) { +void Species::setMovtTraits(const trfrMovtParams m) { if (m.pr >= 1) pr = m.pr; if (m.prMethod >= 1 && m.prMethod <= 3) prMethod = m.prMethod; if (m.memSize >= 1 && m.memSize <= 14) memSize = m.memSize; @@ -631,8 +631,8 @@ void Species::setMovtTraits(const trfrMovtTraits m) { straigtenPath = m.straigtenPath; } -trfrMovtTraits Species::getMovtTraits(void) { - trfrMovtTraits m; +trfrMovtParams Species::getMovtTraits(void) { + trfrMovtParams m; m.pr = pr; m.prMethod = prMethod; m.memSize = memSize; m.goalType = goalType; m.dp = dp; m.gb = gb; m.alphaDB = alphaDB; m.betaDB = betaDB; m.stepMort = stepMort; m.stepLength = stepLength; m.rho = rho; diff --git a/Species.h b/Species.h index 648d7d8..25c604d 100644 --- a/Species.h +++ b/Species.h @@ -100,7 +100,7 @@ struct emigTraits { // structures for transfer parameters -struct trfrRules { +struct transferRules { bool moveModel; bool stgDep; bool sexDep; bool distMort; bool indVar; bool twinKern; @@ -108,7 +108,7 @@ struct trfrRules { short moveType; bool costMap; short movtTrait[2]; }; -struct trfrKernTraits { +struct trfrKernelParams { float meanDist1; float meanDist2; float probKern1; @@ -116,7 +116,7 @@ struct trfrKernTraits { struct trfrMortParams { float fixedMort; float mortAlpha; float mortBeta; }; -struct trfrMovtTraits { +struct trfrMovtParams { short pr; short prMethod; short memSize; short goalType; float dp; float gb; float alphaDB; int betaDB; float stepMort; float stepLength; float rho; @@ -334,9 +334,9 @@ class Species { // transfer parameter functions void setTrfrRules( // Set transfer rules - const trfrRules // structure holding transfer rules + const transferRules // structure holding transfer rules ); - trfrRules getTrfr(void); // Get transfer rules + transferRules getTransferRules(void); // Get transfer rules void setFullKernel( // Set fullKernel condition bool // fullKernel value ); @@ -344,10 +344,10 @@ class Species { void setKernTraits( // Set transfer by kernel parameters const short, // stage const short, // sex - const trfrKernTraits, // structure holding transfer by kernel parameters + const trfrKernelParams, // structure holding transfer by kernel parameters const int // Landscape resolution ); - trfrKernTraits getKernTraits( // Get transfer by kernel parameters + trfrKernelParams getKernTraits( // Get transfer by kernel parameters short, // stage short // sex ); @@ -356,9 +356,9 @@ class Species { ); trfrMortParams getMortParams(void); // Get transfer mortality parameters void setMovtTraits( // Set transfer movement model parameters - const trfrMovtTraits // structure holding transfer movement model parameters + const trfrMovtParams // structure holding transfer movement model parameters ); - trfrMovtTraits getMovtTraits(void); // Get transfer movement model traits + trfrMovtParams getMovtTraits(void); // Get transfer movement model traits trfrCRWTraits getCRWTraits(void); // Get CRW traits trfrSMSTraits getSMSTraits(void); // Get SMS traits // Return dimension of habitat-dependent step mortality and costs matrices diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 3a3d96e..0ccada2 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -121,7 +121,7 @@ void SubCommunity::initialInd(Landscape* pLandscape, Species* pSpecies, demogrParams dem = pSpecies->getDemogrParams(); stageParams sstruct = pSpecies->getStageParams(); emigRules emig = pSpecies->getEmigRules(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); short stg, age, repInt; Individual* pInd; @@ -661,7 +661,7 @@ bool SubCommunity::outTraitsHeaders(Landscape* pLandscape, Species* pSpecies, in string name; emigRules emig = pSpecies->getEmigRules(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); simParams sim = paramsSim->getSim(); @@ -806,7 +806,7 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, pSpecies = popns[iPop]->getSpecies(); demogrParams dem = pSpecies->getDemogrParams(); emigRules emig = pSpecies->getEmigRules(); - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); indTraitsSums = popns[iPop]->getIndTraitsSums(pSpecies); From 8a38c29bfb127303085baa790e095778c8dbe7b5 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 27 Feb 2024 12:13:46 +0000 Subject: [PATCH 062/332] finish improving ReadTransfer readability --- Individual.cpp | 4 ++-- Model.cpp | 8 ++++---- Species.cpp | 8 ++++---- Species.h | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 4651d09..386e17e 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -922,7 +922,7 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, rho = 0.99; // to promote leaving natal patch path->out = 0; } - if (movt.straigtenPath && path->settleStatus > 0) { + if (movt.straightenPath && path->settleStatus > 0) { // individual is in a patch and has already determined whether to settle rho = 0.99; // to promote leaving the patch path->out = 0; @@ -1043,7 +1043,7 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, //get weights for directional persistence.... if ((path->out > 0 && path->out <= (movt.pr + 1)) || natalPatch - || (movt.straigtenPath && path->settleStatus > 0)) { + || (movt.straightenPath && path->settleStatus > 0)) { // inflate directional persistence to promote leaving the patch if (indvar) nbr = getSimDir(current.x, current.y, 10.0f * pSMS.dp); else nbr = getSimDir(current.x, current.y, 10.0f * movt.dp); diff --git a/Model.cpp b/Model.cpp index d24d24f..ac006d8 100644 --- a/Model.cpp +++ b/Model.cpp @@ -1456,10 +1456,10 @@ void OutParameters(Landscape* pLandscape) outPar << endl << "DISPERSAL - TRANSFER: \t"; if (trfr.moveModel) { - bool straigtenPath; + bool straightenPath; if (trfr.moveType == 1) { // SMS trfrSMSTraits move = pSpecies->getSMSTraits(); - straigtenPath = move.straigtenPath; + straightenPath = move.straightenPath; if (trfr.costMap) { outPar << "SMS\tcosts from imported cost map" << endl; #if !RS_RCPP @@ -1496,7 +1496,7 @@ void OutParameters(Landscape* pLandscape) } else { // CRW trfrCRWTraits move = pSpecies->getCRWTraits(); - straigtenPath = move.straigtenPath; + straightenPath = move.straightenPath; outPar << "CRW" << endl; string lgth = "STEP LENGTH (m) "; string corr = "STEP CORRELATION"; @@ -1504,7 +1504,7 @@ void OutParameters(Landscape* pLandscape) outPar << corr << ": " << move.rho << endl; } outPar << "STRAIGHTEN PATH AFTER DECISION NOT TO SETTLE: "; - if (straigtenPath) outPar << "yes" << endl; + if (straightenPath) outPar << "yes" << endl; else outPar << "no" << endl; outPar << "STEP MORTALITY:\t" << endl; if (trfr.habMort) diff --git a/Species.cpp b/Species.cpp index 1b84c20..cb50c00 100644 --- a/Species.cpp +++ b/Species.cpp @@ -76,7 +76,7 @@ Species::Species(void) //costMapFile = "NULL"; fixedMort = 0.0; mortAlpha = 0.0; mortBeta = 1.0; habDimTrfr = 0; - straigtenPath = false; + straightenPath = false; fullKernel = false; // initialise settlement parameters stgDepSett = false; sexDepSett = false; indVarSett = false; @@ -628,7 +628,7 @@ void Species::setMovtTraits(const trfrMovtParams m) { if (m.stepMort >= 0.0 && m.stepMort < 1.0) stepMort = m.stepMort; if (m.stepLength > 0.0) stepLength = m.stepLength; if (m.rho > 0.0 && m.rho < 1.0) rho = m.rho; - straigtenPath = m.straigtenPath; + straightenPath = m.straightenPath; } trfrMovtParams Species::getMovtTraits(void) { @@ -642,7 +642,7 @@ trfrMovtParams Species::getMovtTraits(void) { trfrCRWTraits Species::getCRWTraits(void) { trfrCRWTraits m; m.stepMort = stepMort; m.stepLength = stepLength; m.rho = rho; - m.straigtenPath = straigtenPath; + m.straightenPath = straightenPath; return m; } @@ -650,7 +650,7 @@ trfrSMSTraits Species::getSMSTraits(void) { trfrSMSTraits m; m.pr = pr; m.prMethod = prMethod; m.memSize = memSize; m.goalType = goalType; m.dp = dp; m.gb = gb; m.alphaDB = alphaDB; m.betaDB = betaDB; m.stepMort = stepMort; - m.straigtenPath = straigtenPath; + m.straightenPath = straightenPath; return m; } diff --git a/Species.h b/Species.h index 25c604d..d02db63 100644 --- a/Species.h +++ b/Species.h @@ -120,18 +120,18 @@ struct trfrMovtParams { short pr; short prMethod; short memSize; short goalType; float dp; float gb; float alphaDB; int betaDB; float stepMort; float stepLength; float rho; - bool straigtenPath; + bool straightenPath; }; struct trfrCRWTraits { float stepMort; float stepLength; float rho; - bool straigtenPath; + bool straightenPath; }; struct trfrSMSTraits { short pr; short prMethod; short memSize; short goalType; float dp; float gb; float alphaDB; int betaDB; float stepMort; - bool straigtenPath; + bool straightenPath; }; // structures for settlement parameters @@ -549,7 +549,7 @@ class Species { short habDimTrfr; // dimension of habitat-dependent step mortality and costs matrices int* habCost; // habitat costs bool costMap; // import cost map from file? - bool straigtenPath; // straighten path after decision not to settle + bool straightenPath; // straighten path after decision not to settle bool fullKernel; // used to indicate special case when density-independent emigration // is 1.0, and kernel-based movement within the natal cell is used // to determine philopatry From 689366af88f57421bb48fa0a1d6b971b354689ad Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 27 Feb 2024 16:42:18 +0000 Subject: [PATCH 063/332] improve ReadTransfer, still messy but best I can do for now --- Community.cpp | 10 +++++----- Individual.cpp | 2 +- Model.cpp | 12 ++++++------ Population.cpp | 12 ++++++------ Species.cpp | 4 ++-- Species.h | 2 +- SubCommunity.cpp | 8 ++++---- 7 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Community.cpp b/Community.cpp index d520272..aa3f3f0 100644 --- a/Community.cpp +++ b/Community.cpp @@ -730,7 +730,7 @@ bool Community::outRangeHeaders(Species* pSpecies, int landNr) } } if (trfr.indVar) { - if (trfr.moveModel) { + if (trfr.usesMovtProc) { if (trfr.moveType == 1) { outrange << "\tmeanDP\tstdDP\tmeanGB\tstdGB"; outrange << "\tmeanAlphaDB\tstdAlphaDB\tmeanBetaDB\tstdBetaDB"; @@ -940,7 +940,7 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) } if (trfr.indVar) { - if (trfr.moveModel) { + if (trfr.usesMovtProc) { // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT ngenes = 1; } @@ -997,7 +997,7 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) } } } - if (trfr.moveModel) { + if (trfr.usesMovtProc) { if (trfr.moveType == 1) { outrange << "\t" << mnDP[0] << "\t" << sdDP[0]; outrange << "\t" << mnGB[0] << "\t" << sdGB[0]; @@ -1354,7 +1354,7 @@ void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int } if (trfr.indVar) { - if (trfr.moveModel) { + if (trfr.usesMovtProc) { if (trfr.moveType == 2) { // CRW // NB - CURRENTLY CANNOT BE SEX-DEPENDENT... if (popsize > 0) mn = ts.sumStepL[0] / (double)popsize; else mn = 0.0; @@ -1544,7 +1544,7 @@ bool Community::outTraitsRowsHeaders(Species* pSpecies, int landNr) { } } if (trfr.indVar) { - if (trfr.moveModel) { + if (trfr.usesMovtProc) { if (trfr.moveType == 2) { outtraitsrows << "\tmeanStepLength\tstdStepLength\tmeanRho\tstdRho"; } diff --git a/Individual.cpp b/Individual.cpp index 386e17e..30609a7 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -247,7 +247,7 @@ void Individual::setQTLPhenotypes(Species* pSpecies, int resol) { } void Individual::setTransferTraits(Species* pSpecies, transferRules trfr, int resol) { - if (trfr.moveModel) { + if (trfr.usesMovtProc) { if (trfr.moveType == 1) { setSMSTraits(pSpecies); } diff --git a/Model.cpp b/Model.cpp index ac006d8..33e6283 100644 --- a/Model.cpp +++ b/Model.cpp @@ -455,7 +455,7 @@ int RunModel(Landscape* pLandscape, int seqsim) pLandscape->resetConnectMatrix(); if (ppLand.dynamic && updateland) { - if (trfr.moveModel && trfr.moveType == 1) { // SMS + if (trfr.usesMovtProc && trfr.moveType == 1) { // SMS if (!trfr.costMap) pLandscape->resetCosts(); // in case habitats have changed } // apply effects of landscape change to species present in changed patches @@ -706,7 +706,7 @@ int RunModel(Landscape* pLandscape, int seqsim) } if (ppLand.dynamic) { transferRules trfr = pSpecies->getTransferRules(); - if (trfr.moveModel && trfr.moveType == 1) { // SMS + if (trfr.usesMovtProc && trfr.moveType == 1) { // SMS if (ixcostchg > 0) { // apply any cost changes to reset landscape to original configuration // (provided that at least one has already occurred) @@ -1411,7 +1411,7 @@ void OutParameters(Landscape* pLandscape) else { // not density-dependent string initprob = "INITIAL EMIGRATION PROB. "; outPar << "density-independent" << endl; - if (!trfr.moveModel) { // transfer by kernel + if (!trfr.usesMovtProc) { // transfer by kernel outPar << "USE FULL KERNEL TO DETERMINE EMIGRATION: "; if (pSpecies->useFullKernel()) outPar << "yes"; else outPar << "no"; @@ -1455,7 +1455,7 @@ void OutParameters(Landscape* pLandscape) outPar << endl << "DISPERSAL - TRANSFER: \t"; - if (trfr.moveModel) { + if (trfr.usesMovtProc) { bool straightenPath; if (trfr.moveType == 1) { // SMS trfrSMSTraits move = pSpecies->getSMSTraits(); @@ -1607,7 +1607,7 @@ void OutParameters(Landscape* pLandscape) outPar << endl << "DISPERSAL - SETTLEMENT:" << endl; - if (trfr.moveModel) { + if (trfr.usesMovtProc) { string plusmating = "+ mating requirements"; ssteps = pSpecies->getSteps(0, 0); @@ -1920,7 +1920,7 @@ void OutParameters(Landscape* pLandscape) outPar << endl; } else outPar << "no" << endl; - if (trfr.moveModel && trfr.moveType == 1) { + if (trfr.usesMovtProc && trfr.moveType == 1) { outPar << "SMS HEAT MAPS: "; if (sim.saveVisits) outPar << "yes" << endl; else outPar << "no" << endl; diff --git a/Population.cpp b/Population.cpp index 9038272..e2590f6 100644 --- a/Population.cpp +++ b/Population.cpp @@ -260,7 +260,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { ts.ssqBeta[g] += e.beta * e.beta; // transfer traits - if (trfr.moveModel) { + if (trfr.usesMovtProc) { switch (trfr.moveType) { @@ -1193,7 +1193,7 @@ int Population::transfer(Landscape* pLandscape, short landIx) //DEBUGLOG << "Population::transfer(): 1111: i = " << i << " ID = " << inds[i]->getId() // << endl; #endif - if (trfr.moveModel) { + if (trfr.usesMovtProc) { #if RSDEBUG //pCell = inds[i]->getLocn(1); //locn loc = pCell->getLocn(); @@ -1357,7 +1357,7 @@ int Population::transfer(Landscape* pLandscape, short landIx) ndispersers--; } else { // does not recruit - if (trfr.moveModel) { + if (trfr.usesMovtProc) { ind.status = 1; // continue dispersing, unless ... // ... maximum steps has been exceeded pathSteps steps = inds[i]->getSteps(); @@ -1391,7 +1391,7 @@ int Population::transfer(Landscape* pLandscape, short landIx) } } #endif - if (!trfr.moveModel && sett.go2nbrLocn && (ind.status == 3 || ind.status == 6)) + if (!trfr.usesMovtProc && sett.go2nbrLocn && (ind.status == 3 || ind.status == 6)) { // for kernel-based transfer only ... // determine whether recruitment to a neighbouring cell is possible @@ -2002,7 +2002,7 @@ void Population::outIndsHeaders(int rep, int landNr, bool patchModel) else outInds << "\tEP"; } if (trfr.indVar) { - if (trfr.moveModel) { + if (trfr.usesMovtProc) { if (trfr.moveType == 1) { // SMS outInds << "\tDP\tGB\tAlphaDB\tBetaDB"; } @@ -2110,7 +2110,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, } } // end of if (emig.indVar) if (trfr.indVar) { - if (trfr.moveModel) { + if (trfr.usesMovtProc) { if (trfr.moveType == 1) { // SMS trfrSMSTraits s = inds[i]->getSMSTraits(); outInds << "\t" << s.dp << "\t" << s.gb; diff --git a/Species.cpp b/Species.cpp index cb50c00..e215b1f 100644 --- a/Species.cpp +++ b/Species.cpp @@ -553,7 +553,7 @@ float Species::getEmigD0(short stg, short sex) { // Transfer functions void Species::setTrfrRules(const transferRules t) { - moveModel = t.moveModel; + moveModel = t.usesMovtProc; stgDepTrfr = t.stgDep; sexDepTrfr = t.sexDep; distMort = t.distMort; @@ -567,7 +567,7 @@ void Species::setTrfrRules(const transferRules t) { transferRules Species::getTransferRules(void) { transferRules t; - t.moveModel = moveModel; t.stgDep = stgDepTrfr; t.sexDep = sexDepTrfr; + t.usesMovtProc = moveModel; t.stgDep = stgDepTrfr; t.sexDep = sexDepTrfr; t.distMort = distMort; t.indVar = indVarTrfr; t.twinKern = twinKern; t.habMort = habMort; diff --git a/Species.h b/Species.h index d02db63..94421c3 100644 --- a/Species.h +++ b/Species.h @@ -101,7 +101,7 @@ struct emigTraits { // structures for transfer parameters struct transferRules { - bool moveModel; bool stgDep; bool sexDep; + bool usesMovtProc; bool stgDep; bool sexDep; bool distMort; bool indVar; bool twinKern; bool habMort; diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 0ccada2..f2395d7 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -149,7 +149,7 @@ void SubCommunity::initialInd(Landscape* pLandscape, Species* pSpecies, else { if (iind.sex == 1) probmale = 1.0; else probmale = 0.0; } - pInd = new Individual(pCell, pPatch, stg, age, repInt, probmale, trfr.moveModel, trfr.moveType); + pInd = new Individual(pCell, pPatch, stg, age, repInt, probmale, trfr.usesMovtProc, trfr.moveType); // add new individual to the population // NB THIS WILL NEED TO BE CHANGED FOR MULTIPLE SPECIES... @@ -717,7 +717,7 @@ bool SubCommunity::outTraitsHeaders(Landscape* pLandscape, Species* pSpecies, in } } if (trfr.indVar) { - if (trfr.moveModel) { + if (trfr.usesMovtProc) { if (trfr.moveType == 1) { outtraits << "\tmeanDP\tstdDP\tmeanGB\tstdGB"; outtraits << "\tmeanAlphaDB\tstdAlphaDB\tmeanBetaDB\tstdBetaDB"; @@ -879,7 +879,7 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, } if (trfr.indVar) { - if (trfr.moveModel) { + if (trfr.usesMovtProc) { // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT ngenes = 1; } @@ -937,7 +937,7 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, } } if (writefile) { - if (trfr.moveModel) { + if (trfr.usesMovtProc) { if (trfr.moveType == 1) { outtraits << "\t" << mnDP[0] << "\t" << sdDP[0]; outtraits << "\t" << mnGB[0] << "\t" << sdGB[0]; From 8fe6c32a7d14f4437006db9f9ed6aac98d990184 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 27 Feb 2024 17:41:45 +0000 Subject: [PATCH 064/332] imrpove some ReadFile() funcs --- Parameters.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Parameters.h b/Parameters.h index e1bacee..a3ae0c5 100644 --- a/Parameters.h +++ b/Parameters.h @@ -261,7 +261,8 @@ struct initParams { }; struct initInd { - int year, patchID, x, y; short species, sex, age, stage; + int year, patchID, x, y; + short species, sex, age, stage; }; class paramInit { From ca61c8175abe82e7e46e77af5bb1cf0117a78b29 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 29 Feb 2024 17:43:25 +0000 Subject: [PATCH 065/332] SpeciesTrait input should be in batch, not RScore --- Species.h | 2 +- SpeciesTrait.cpp | 201 +++++------------------------------------------ SpeciesTrait.h | 25 +++--- 3 files changed, 36 insertions(+), 192 deletions(-) diff --git a/Species.h b/Species.h index 94421c3..c26a788 100644 --- a/Species.h +++ b/Species.h @@ -491,7 +491,7 @@ class Species { int genomeSize; bool diploid; bool mutationsOn; - int numberOfNeutralLoci; + int numberOfNeutralLoci = 0; int numberOfAdaptiveTraits; float recombinationRate; std::set samplePatchList; diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index a536b9a..dd1a45b 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -2,186 +2,25 @@ #include "SpeciesTrait.h" //could be handled in header file but here for now for flexibility -SpeciesTrait::SpeciesTrait(vector parameters, Species* pSpecies) { - - bool neutralPresent = false; - if (ploidy == 0) this->ploidy = pSpecies->isDiploid() ? 2 : 1; - - this->sex = stringToSex(parameters[2]); - TraitType traitType = stringToTraitType(parameters[1], this->sex); - this->positions = stringToLoci(parameters[3], parameters[4], pSpecies); - this->expressionType = stringToExpressionType(parameters[5]); - this->initialDistribution = stringToDistributionType(parameters[6]); - this->initialParameters = stringToParameterMap(parameters[7]); - this->dominanceDistribution = stringToDistributionType(parameters[8]); - this->dominanceParameters = stringToParameterMap(parameters[9]); - - if (traitType == SNP || traitType == ADAPTIVE) - this->inherited = true; - else - this->inherited = (parameters[10] == "true") ? true : false; - - if (this->isInherited()) { - this->mutationDistribution = stringToDistributionType(parameters[11]); - this->mutationParameters = stringToParameterMap(parameters[12]); - this->mutationRate = stof(parameters[13]); - } - - // error outputting for different traits - if (traitType == SNP) { - if (mutationDistribution != KAM && mutationDistribution != SSM) - cout << endl << "Traits file: ERROR - Neutral marker mutation distribution must be KAM or SSM (max = 256))" << endl; - - if (pSpecies->getNumberOfNeutralLoci() > 0) - cout << endl << "Traits file: WARNING - can only have one set of neutral markers, overwriting previous" << endl; - else pSpecies->setNumberOfNeutralLoci(static_cast(positions.size())); - } -} - -TraitType SpeciesTrait::stringToTraitType(const std::string& str, sex_t sex) const { - - // Non-dispersal traits - if (str == "neutral") return SNP; - else if (str == "adaptive") return ADAPTIVE; - // Sex-invariant dispersal traits - else if (str == "sms_directionalPersistence") return SMS_DP; - else if (str == "sms_goalBias") return SMS_GB; - else if (str == "sms_alphaDB") return SMS_ALPHADB; - else if (str == "sms_betaDB") return SMS_BETADB; - // Sex-specific dispersal traits - else if (sex == MAL) { - if (str == "emigration_d0") return E_D0_M; - else if (str == "emigration_alpha") return E_ALPHA_M; - else if (str == "emigration_beta") return E_BETA_M; - else if (str == "settlement_s0") return S_S0_M; - else if (str == "settlement_alpha") return S_ALPHA_M; - else if (str == "settlement_beta") return S_BETA_M; - else if (str == "kernel_meanDistance1") return KERNEL_MEANDIST_1_M; - else if (str == "kernel_meanDistance2") return KERNEL_MEANDIST_2_M; - else if (str == "kernel_probability") return KERNEL_PROBABILITY_M; - else if (str == "crw_stepLength") return CRW_STEPLENGTH_M; - else if (str == "crw_stepCorrelation") return CRW_STEPCORRELATION_M; - else throw logic_error(str + " is not a valid trait type."); - } - else { - if (str == "emigration_d0") return E_D0_F; - else if (str == "emigration_alpha") return E_ALPHA_F; - else if (str == "emigration_beta") return E_BETA_F; - else if (str == "settlement_s0") return S_S0_F; - else if (str == "settlement_alpha") return S_ALPHA_F; - else if (str == "settlement_beta") return S_BETA_F; - else if (str == "kernel_meanDistance1") return KERNEL_MEANDIST_1_F; - else if (str == "kernel_meanDistance2") return KERNEL_MEANDIST_2_F; - else if (str == "kernel_probability") return KERNEL_PROBABILITY_F; - else if (str == "crw_stepLength") return CRW_STEPLENGTH_F; - else if (str == "crw_stepCorrelation") return CRW_STEPCORRELATION_F; - else throw logic_error(str + " is not a valid trait type."); - } -} - -ExpressionType SpeciesTrait::stringToExpressionType(const std::string& str) const { - if (str == "average") return AVERAGE; - else if (str == "additive") return ADDITIVE; - else if (str == "multiplicative") return MULTIPLICATIVE; - else if (str == "#") return NEUTRAL; - else throw logic_error(str + " is not a valid gene expression type."); -} - -DistributionType SpeciesTrait::stringToDistributionType(const std::string& str) const +SpeciesTrait::SpeciesTrait( + const TraitType& traitType, const sex_t& sx, + const set& pos, const ExpressionType& expr, + const DistributionType& initDist, const map initParams, + const DistributionType& dominanceDist, const map dominanceParams, + bool isInherited, const float& mutRate, + const DistributionType& mutationDist, const map mutationParams, + Species* pSpecies) : + sex{sx}, + positions{pos}, + expressionType{expr}, + initialDistribution{initDist}, + initialParameters{initParams}, + dominanceDistribution{dominanceDist}, + dominanceParameters{dominanceParams}, + inherited{isInherited}, + mutationDistribution{mutationDist}, + mutationParameters{mutationParams}, + mutationRate{mutRate} { - if (str == "#") return NONE; - else if (str == "uniform") return UNIFORM; - else if (str == "normal") return NORMAL; - else if (str == "gamma") return GAMMA; - else if (str == "scaled") return SCALED; - else if (str == "negExp") return NEGEXP; - else if (str == "KAM") return KAM; - else if (str == "SSM") return SSM; - else throw logic_error(str + " is not a valid distribution type."); -} - -map SpeciesTrait::stringToParameterMap(string parameters) const { - - map paramMap; - if (parameters != "#") { - parameters.erase(remove(parameters.begin(), parameters.end(), '\"'), parameters.end()); - stringstream ss(parameters); - - string value, valueWithin; - while (std::getline(ss, value, ',')) { - stringstream sss(value); - vector paramValue; - while (std::getline(sss, valueWithin, '=')) { - paramValue.push_back(valueWithin); - } - - if (paramValue.size() == 2) { - parameter_t parameterT = paramValue[0]; - float value = stof(paramValue[1]); - paramMap.emplace(parameterT, value); - } - else - cout << endl << "Traits file: ERROR - parameter values for a distribution missing, should be e.g. 'mean=0,standard_deviation=0.5' or if not applicable put #" << endl; - } - } - return paramMap; -} - -set SpeciesTrait::selectRandomLociPositions(int nbLoci, Species* pSpecies) const { - - int genomeSize = pSpecies->getGenomeSize(); - set positions; - for (int i = 0; i < nbLoci; ++i) - positions.insert(pRandom->IRandom(0, genomeSize)); - return positions; -} - - -set SpeciesTrait::stringToLoci(string pos, string nLoci, Species* pSpecies) const { - - set positions; - - if (pos != "random") { - - // Parse comma-separated list from input string - stringstream ss(pos); - string value, valueWithin; - // Read comma-separated positions - while (std::getline(ss, value, ',')) { - stringstream sss(value); - vector positionRange; - // Read single positions and dash-separated ranges - while (std::getline(sss, valueWithin, '-')) { - positionRange.push_back(stoi(valueWithin)); - } - switch (positionRange.size()) - { - case 1: // single position - if (positionRange[0] > pSpecies->getGenomeSize()) - throw logic_error("Traits file: ERROR - trait positions must not exceed genome size"); - positions.insert(positionRange[0]); - break; - case 2: // dash-separated range - if (positionRange[0] > pSpecies->getGenomeSize() || positionRange[1] > pSpecies->getGenomeSize()) { - throw logic_error("Traits file: ERROR - trait positions must not exceed genome size"); - } - for (int i = positionRange[0]; i < positionRange[1] + 1; ++i) { - positions.insert(i); - } - break; - default: // zero or more than 2 values between commas: error - throw logic_error("Traits file: ERROR - incorrectly formatted position range."); - break; - } - } - - for (auto position : positions) { - if (position > pSpecies->getGenomeSize()) - cout << endl << "Traits file: ERROR - trait positions " << position << " must not exceed genome size" << endl; - } - } - else { - positions = selectRandomLociPositions(stoi(nLoci), pSpecies); - } - return positions; + if (ploidy == 0) this->ploidy = pSpecies->isDiploid() ? 2 : 1; } diff --git a/SpeciesTrait.h b/SpeciesTrait.h index 9a634cb..2880686 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -29,7 +29,21 @@ class SpeciesTrait { public: - SpeciesTrait(vector parameters, Species* pSpecies); + SpeciesTrait( + const TraitType& traitType, + const sex_t& sex, + const set& pos, + const ExpressionType& expr, + const DistributionType& initDist, + const map initParams, + const DistributionType& dominanceDist, + const map dominanceParams, + bool isInherited, + const float& mutationRate, + const DistributionType& mutationDist, + const map mutationParams, + Species* pSpecies + ); // Getters sex_t getSex() const { return sex; } @@ -45,14 +59,5 @@ class SpeciesTrait { DistributionType getInitialDistribution() const { return initialDistribution; }; map getInitialParameters() const { return initialParameters; }; ExpressionType getExpressionType() const { return expressionType; }; - - DistributionType stringToDistributionType(const std::string& str) const; - ExpressionType stringToExpressionType(const std::string& str) const; - map stringToParameterMap(string parameters) const; - - set selectRandomLociPositions(int noLoci, Species* pSpecies) const; - - set stringToLoci(string pos, string nLoci, Species* pSpecies) const; - TraitType stringToTraitType(const std::string& str, sex_t sex) const; }; #endif \ No newline at end of file From 9367d6b5ddea4917dcf0bd8987ee4e8c229804db Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 1 Mar 2024 13:54:19 +0000 Subject: [PATCH 066/332] rename adaptive mentions into genetic load --- GeneticLoad.cpp | 51 +++++++++++++++++-------------------------------- Parameters.h | 2 +- Species.cpp | 6 +++--- 3 files changed, 22 insertions(+), 37 deletions(-) diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index aa93e8d..0f9e61c 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -22,10 +22,10 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) case UNIFORM: { if (mutationParameters.count(MAX) != 1) - cout << endl << ("Error:: adaptive mutation uniform distribution parameter must contain one max value (e.g. max= ) \n"); + cout << endl << ("Error:: genetic load mutation uniform distribution parameter must contain one max value (e.g. max= ) \n"); if (mutationParameters.count(MIN) != 1) - cout << endl << ("Error:: adaptive mutation uniform distribution parameter must contain one min value (e.g. min= ) \n"); + cout << endl << ("Error:: genetic load mutation uniform distribution parameter must contain one min value (e.g. min= ) \n"); break; } @@ -33,34 +33,34 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) { if (mutationParameters.count(MEAN) != 1) - cout << endl << ("Error:: adaptive mutation distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); + cout << endl << ("Error:: genetic load mutation distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); if (mutationParameters.count(SDEV) != 1) - cout << endl << ("Error:: adaptive mutation distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); + cout << endl << ("Error:: genetic load mutation distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); break; } case GAMMA: { if (mutationParameters.count(SHAPE) != 1) - cout << endl << ("Error:: adaptive mutation distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); + cout << endl << ("Error:: genetic load mutation distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); if (mutationParameters.count(SCALE) != 1) - cout << endl << ("Error:: adaptive mutation distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); + cout << endl << ("Error:: genetic load mutation distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); break; } case NEGEXP: { if (mutationParameters.count(MEAN) != 1) - cout << endl << ("Error:: adaptive mutation distribution set to negative exponential (negative decay) so parameters must contain one mean value (e.g. mean= ) \n"); + cout << endl << ("Error:: genetic load mutation distribution set to negative exponential (negative decay) so parameters must contain one mean value (e.g. mean= ) \n"); break; } default: { - cout << endl << ("Error:: wrong parameter value for adaptive mutation model, must be uniform/normal/gamma/negExp \n"); + cout << endl << ("Error:: wrong parameter value for genetic load mutation model, must be uniform/normal/gamma/negExp \n"); } } @@ -71,10 +71,10 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) case UNIFORM: { if (dominanceParameters.count(MAX) != 1) - cout << endl << ("Error:: adaptive dominance uniform distribution parameter must contain one max value (e.g. max= ) \n"); + cout << endl << ("Error:: genetic load dominance uniform distribution parameter must contain one max value (e.g. max= ) \n"); if (dominanceParameters.count(MIN) != 1) - cout << endl << ("Error:: adaptive dominance uniform distribution parameter must contain one min value (e.g. min= ) \n"); + cout << endl << ("Error:: genetic load dominance uniform distribution parameter must contain one min value (e.g. min= ) \n"); break; } @@ -82,27 +82,27 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) { if (dominanceParameters.count(MEAN) != 1) - cout << endl << ("Error:: adaptive dominance distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); + cout << endl << ("Error:: genetic load dominance distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); if (dominanceParameters.count(SDEV) != 1) - cout << endl << ("Error:: adaptive dominance distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); + cout << endl << ("Error:: genetic load dominance distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); break; } case GAMMA: { if (dominanceParameters.count(SHAPE) != 1) - cout << endl << ("Error:: adaptive dominance distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); + cout << endl << ("Error:: genetic load dominance distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); if (dominanceParameters.count(SCALE) != 1) - cout << endl << ("Error:: adaptive dominance distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); + cout << endl << ("Error:: genetic load dominance distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); break; } case NEGEXP: { if (dominanceParameters.count(MEAN) != 1) - cout << endl << ("Error:: adaptive dominance distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); + cout << endl << ("Error:: genetic load dominance distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); break; } @@ -113,28 +113,13 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) default: { - cout << endl << ("Error:: wrong parameter value for adaptive dominance model, must be uniform/normal/gamma/negExp/scaled \n"); + cout << endl << ("Error:: wrong parameter value for genetic load dominance model, must be uniform/normal/gamma/negExp/scaled \n"); break; //should return false } } DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); map initialParameters = pSpeciesTrait->getInitialParameters(); - - //switch (expressionType) { - //case MULTIPLICATIVE: - //{ - // _express_func_ptr = &AdaptiveTrait::expressMulti; - // break; - //} - //default: - //{ - // cout << endl << ("wrong parameter value for parameter \"expression of adaptive mutations\", must be multiplicative \n"); - // break; //should return false - //} - - //} - } @@ -237,7 +222,7 @@ float GeneticLoad::drawDominance(float selCoef) { default: { - cout << endl << ("Error:: wrong parameter value for adaptive dominance model, must be uniform/normal/gamma/negExp/scaled \n"); + cout << endl << ("Error:: wrong parameter value for genetic load dominance model, must be uniform/normal/gamma/negExp/scaled \n"); break; //should return false } } @@ -289,7 +274,7 @@ float GeneticLoad::drawSelectionCoef() { } default: { - cout << endl << ("Error:: wrong parameter value for adaptive mutation model, must be uniform/normal/gamma/negExp/scaled \n"); + cout << endl << ("Error:: wrong parameter value for genetic load mutation model, must be uniform/normal/gamma/negExp/scaled \n"); break; //should return false } } diff --git a/Parameters.h b/Parameters.h index a3ae0c5..88fc434 100644 --- a/Parameters.h +++ b/Parameters.h @@ -117,7 +117,7 @@ const rgb draw_wheel(int); enum TraitType { SNP, - ADAPTIVE, ADAPTIVE1, ADAPTIVE2, ADAPTIVE3, ADAPTIVE4, ADAPTIVE5, + GENETIC_LOAD, ADAPTIVE1, ADAPTIVE2, ADAPTIVE3, ADAPTIVE4, ADAPTIVE5, E_D0_F, E_ALPHA_F, E_BETA_F, S_S0_F, S_ALPHA_F, S_BETA_F, diff --git a/Species.cpp b/Species.cpp index e215b1f..203bbda 100644 --- a/Species.cpp +++ b/Species.cpp @@ -417,8 +417,8 @@ int Species::getNumberOfAdaptiveTraits() const void Species::addTrait(TraitType traitType, const SpeciesTrait& trait) { TraitType traitT = traitType; - //hack to deal with multiple adaptive traits, could be handled better - if (traitType == ADAPTIVE) { + //hack to deal with multiple genetic load traits, could be handled better + if (traitType == GENETIC_LOAD) { int n = incrementAdaptiveTraits(); switch (n) { @@ -449,7 +449,7 @@ void Species::addTrait(TraitType traitType, const SpeciesTrait& trait) { } default: { - cout << endl << ("Error:: Too many adaptive traits in Traits file, max = 5 \n"); + cout << endl << ("Error:: Too many genetic load traits in Traits file, max = 5 \n"); break; //should return false } } From ec275efe076ee40b9f0116754b5543590d73bb87 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 1 Mar 2024 18:14:13 +0000 Subject: [PATCH 067/332] allow more sex_t states for input handling --- Community.cpp | 16 ---- Individual.cpp | 14 ++-- Model.cpp | 204 +++++------------------------------------------ Parameters.cpp | 3 +- Parameters.h | 10 ++- Population.cpp | 9 --- SNPTrait.h | 2 - Species.cpp | 15 ++-- SubCommunity.cpp | 39 +-------- TTrait.h | 11 --- TraitFactory.h | 6 +- 11 files changed, 45 insertions(+), 284 deletions(-) diff --git a/Community.cpp b/Community.cpp index aa3f3f0..3b83179 100644 --- a/Community.cpp +++ b/Community.cpp @@ -75,16 +75,6 @@ void Community::initialise(Species* pSpecies, int year) spratio = ppLand.spResol / ppLand.resol; -#if RSDEBUG - DEBUGLOG << endl << "Community::initialise(): this=" << this - << " seedType=" << init.seedType << " freeType=" << init.freeType - << " minSeedX=" << init.minSeedX << " minSeedY=" << init.minSeedY - << " maxSeedX=" << init.maxSeedX << " maxSeedY=" << init.maxSeedY - << " indsFile=" << init.indsFile - << " nsubcomms=" << nsubcomms << " spratio=" << spratio - << endl; -#endif - switch (init.seedType) { case 0: // free initialisation @@ -312,12 +302,6 @@ void Community::initialise(Species* pSpecies, int year) } // end of switch (init.seedType) -#if RSDEBUG - DEBUGLOG << "Community::initialise(): this=" << this - << " nsubcomms=" << nsubcomms - << endl; -#endif - } // Add manually selected patches/cells to the selected set for initialisation diff --git a/Individual.cpp b/Individual.cpp index 30609a7..4494f58 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -184,7 +184,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi if (newTrait->getMutationRate() > 0 && pSpecies->areMutationsOn()) newTrait->mutate(); } - if (trait == ADAPTIVE1 || trait == ADAPTIVE2 || trait == ADAPTIVE3 || trait == ADAPTIVE4 || trait == ADAPTIVE5) + if (trait == GENETIC_LOAD1 || trait == GENETIC_LOAD2 || trait == GENETIC_LOAD3 || trait == GENETIC_LOAD4 || trait == GENETIC_LOAD5) fitness *= newTrait->express(); spTraitTable.insert(make_pair(trait, move(newTrait))); @@ -209,7 +209,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother) { if (newTrait->getMutationRate() > 0 && pSpecies->areMutationsOn()) newTrait->mutate(); } - if (trait == ADAPTIVE1 || trait == ADAPTIVE2 || trait == ADAPTIVE3 || trait == ADAPTIVE4 || trait == ADAPTIVE5) + if (trait == GENETIC_LOAD1 || trait == GENETIC_LOAD2 || trait == GENETIC_LOAD3 || trait == GENETIC_LOAD4 || trait == GENETIC_LOAD5) fitness *= newTrait->express(); spTraitTable.insert(make_pair(trait, move(newTrait))); @@ -393,11 +393,11 @@ void Individual::setEmigTraits(Species* pSpecies, bool sexDep, bool densityDep) } pEmigTraits = make_unique(); - pEmigTraits->d0 = (float)(e.d0); - pEmigTraits->alpha = (float)(e.alpha); - pEmigTraits->beta = (float)(e.beta); - if (pEmigTraits->d0 < 0.0) pEmigTraits->d0 = 0.0; - if (pEmigTraits->d0 > 1.0) pEmigTraits->d0 = 1.0; + pEmigTraits->d0 = e.d0; + pEmigTraits->alpha = e.alpha; + pEmigTraits->beta = e.beta; + if (pEmigTraits->d0 < 0.0) throw runtime_error("d0 value has become negative."); + if (pEmigTraits->d0 > 1.0) throw runtime_error("d0 value has exceeded 1."); return; } diff --git a/Model.cpp b/Model.cpp index 33e6283..eb8012c 100644 --- a/Model.cpp +++ b/Model.cpp @@ -75,16 +75,7 @@ int RunModel(Landscape* pLandscape, int seqsim) int npatches = pLandscape->patchCount(); for (int i = 0; i < npatches; i++) { ppp = pLandscape->getPatchData(i); -#if RSDEBUG - //DEBUGLOG << "RunModel(): i = " << i - // << " ppp.pPatch = " << ppp.pPatch << " ppp.patchNum = " << ppp.patchNum - // << endl; -#endif pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES - // if (i == 0 || ppp.pPatch->getK() > 0.0) { - // // SET UP SUB-COMMUNITY FOR MATRIX PATCH AND ANY PATCH HAVING NON-ZERO CARRYING CAPACITY - // pComm->addSubComm(ppp.pPatch,ppp.patchNum); - // } } if (init.seedType == 0 && init.freeType < 2 && init.initFrzYr > 0) { // restrict available landscape to initialised region @@ -102,15 +93,8 @@ int RunModel(Landscape* pLandscape, int seqsim) // Loop through replicates for (int rep = 0; rep < sim.reps; rep++) { -#if RSDEBUG - DEBUGLOG << endl << "RunModel(): starting simulation=" << sim.simulation << " rep=" << rep << endl; -#endif #if RS_RCPP && !R_CMD Rcpp::Rcout << endl << "starting replicate " << rep << endl; -#else -#if BATCH - cout << endl << "starting replicate " << rep << endl; -#endif #endif if (sim.saveVisits && !ppLand.generated) { @@ -126,54 +110,36 @@ int RunModel(Landscape* pLandscape, int seqsim) int ncostchanges = pLandscape->numCostChanges(); int ixpchchg = 0; int ixcostchg = 0; -#if RSDEBUG - DEBUGLOG << "RunModel(): npatchchanges=" << npatchchanges << " ncostchanges=" << ncostchanges << endl; -#endif if (ppLand.generated) { -#if RSDEBUG - DEBUGLOG << endl << "RunModel(): generating new landscape ..." << endl; -#endif // delete previous community (if any) // Note: this must be BEFORE the landscape is reset (as a sub-community accesses // its corresponding patch upon deletion) if (pComm != 0) delete pComm; // generate new cell-based landscape pLandscape->resetLand(); -#if RSDEBUG - DEBUGLOG << "RunModel(): finished resetting landscape" << endl << endl; -#endif pLandscape->generatePatches(pSpecies); if (v.viewLand || sim.saveMaps) { pLandscape->setLandMap(); pLandscape->drawLandscape(rep, 0, ppLand.landNum); } -#if RSDEBUG - DEBUGLOG << endl << "RunModel(): finished generating patches" << endl; -#endif pComm = new Community(pLandscape); // set up community // set up a sub-community associated with each patch (incl. the matrix) pLandscape->updateCarryingCapacity(pSpecies, 0, 0); patchData ppp; int npatches = pLandscape->patchCount(); -#if RSDEBUG - DEBUGLOG << "RunModel(): patch count is " << npatches << endl; -#endif for (int i = 0; i < npatches; i++) { ppp = pLandscape->getPatchData(i); -#if RSWIN64 -#if LINUX_CLUSTER + #if RSWIN64 + #if LINUX_CLUSTER pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES -#else + #else SubCommunity* pSubComm = pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES -#endif -#else + #endif + #else pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES -#endif + #endif } -#if RSDEBUG - DEBUGLOG << endl << "RunModel(): finished generating populations" << endl; -#endif } if (init.seedType == 0 && init.freeType < 2 && init.initFrzYr > 0) { // restrict available landscape to initialised region @@ -220,13 +186,7 @@ int RunModel(Landscape* pLandscape, int seqsim) } } } -#if RSDEBUG - DEBUGLOG << "RunModel(): completed opening output files" << endl; -#endif if (!filesOK) { -#if RSDEBUG - DEBUGLOG << "RunModel(): PROBLEM - closing output files" << endl; -#endif // close any files which may be open if (sim.outRange) { pComm->outRangeHeaders(pSpecies, -999); @@ -245,11 +205,11 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outputWCFstat) { pComm->openWCFstatFile(pSpecies, -999); } -#if RS_RCPP && !R_CMD + #if RS_RCPP && !R_CMD return Rcpp::List::create(Rcpp::Named("Errors") = 666); -#else + #else return 666; -#endif + #endif } if (env.stoch && !env.local) { @@ -272,22 +232,13 @@ int RunModel(Landscape* pLandscape, int seqsim) // set up populations in the community pLandscape->updateCarryingCapacity(pSpecies, 0, 0); -#if RSDEBUG - DEBUGLOG << "RunModel(): completed updating carrying capacity" << endl; -#endif - // if (init.seedType != 2) { pComm->initialise(pSpecies, -1); - // } bool updateland = false; int landIx = 0; // landscape change index -#if RSDEBUG - DEBUGLOG << "RunModel(): completed initialisation, rep=" << rep - << " pSpecies=" << pSpecies << endl; -#endif -#if BATCH && RS_RCPP && !R_CMD + #if BATCH && RS_RCPP && !R_CMD Rcpp::Rcout << "RunModel(): completed initialisation " << endl; -#endif + #endif // open a new individuals file for each replicate if (sim.outInds) @@ -299,26 +250,17 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outputPairwiseFst) { pComm->openPairwiseFSTFile(pSpecies, pLandscape, ppLand.landNum, rep); } -#if RSDEBUG - // output initialised Individuals - if (sim.outInds) - pComm->outInds(rep, -1, -1, -1); -#endif -#if RS_RCPP + #if RS_RCPP // open a new movement paths file for each replicate if (sim.outPaths) pLandscape->outPathsHeaders(rep, 0); -#endif + #endif // years loop for (yr = 0; yr < sim.years; yr++) { -#if RSDEBUG - DEBUGLOG << endl << "RunModel(): starting simulation=" << sim.simulation - << " rep=" << rep << " yr=" << yr << endl; -#endif -#if RS_RCPP && !R_CMD + #if RS_RCPP && !R_CMD Rcpp::checkUserInterrupt(); -#endif + #endif bool updateCC = false; if (yr < 4 || (yr < 31 && yr % 10 == 0) @@ -328,11 +270,11 @@ int RunModel(Landscape* pLandscape, int seqsim) || (yr < 300001 && yr % 100000 == 0) || (yr < 3000001 && yr % 1000000 == 0) ) { -#if RS_RCPP && !R_CMD + #if RS_RCPP && !R_CMD Rcpp::Rcout << "starting year " << yr << "..." << endl; -#else + #else cout << "starting year " << yr << endl; -#endif + #endif } if (init.seedType == 0 && init.freeType < 2) { // apply any range restrictions @@ -348,13 +290,6 @@ int RunModel(Landscape* pLandscape, int seqsim) commStats s = pComm->getStats(); int minY = s.maxY - init.restrictRows; if (minY < 0) minY = 0; -#if RSDEBUG - DEBUGLOG << "RunModel(): restriction yr=" << yr - << " s.minY=" << s.minY << " s.maxY=" << s.maxY - << " init.restrictRows=" << init.restrictRows - << " minY=" << minY - << endl; -#endif pLandscape->setLandLimits(ppLand.minX, minY, ppLand.maxX, ppLand.maxY); updateCC = true; } @@ -362,11 +297,6 @@ int RunModel(Landscape* pLandscape, int seqsim) if (yr == init.finalFrzYr) { // apply final range restriction commStats s = pComm->getStats(); -#if RSDEBUG - DEBUGLOG << "RunModel(): final restriction yr=" << yr - << " s.minY=" << s.minY << " s.maxY=" << s.maxY - << endl; -#endif pLandscape->setLandLimits(ppLand.minX, s.minY, ppLand.maxX, s.maxY); updateCC = true; } @@ -386,13 +316,6 @@ int RunModel(Landscape* pLandscape, int seqsim) updateCC = true; } if (ppLand.dynamic) { -#if RSDEBUG - DEBUGLOG << "RunModel(): yr=" << yr << " landChg.chgnum=" << landChg.chgnum - << " landChg.chgyear=" << landChg.chgyear - << " npatchchanges=" << npatchchanges << " ncostchanges=" << ncostchanges - << " ixpchchg=" << ixpchchg << " ixcostchg=" << ixcostchg - << endl; -#endif if (yr == landChg.chgyear) { // apply landscape change landIx = landChg.chgnum; updateland = updateCC = true; @@ -422,9 +345,6 @@ int RunModel(Landscape* pLandscape, int seqsim) pLandscape->resetPatches(); // reset patch limits } if (landChg.costfile != "NULL") { // apply any SMS cost changes -#if RSDEBUG - DEBUGLOG << "RunModel(): yr=" << yr << " landChg.costfile=" << landChg.costfile << endl; -#endif Cell* pCell; costchange = pLandscape->getCostChange(ixcostchg++); while (costchange.chgnum <= landIx && ixcostchg <= ncostchanges) { @@ -482,21 +402,6 @@ int RunModel(Landscape* pLandscape, int seqsim) for (int gen = 0; gen < dem.repSeasons; gen++) // generation loop { -#if RSDEBUG - // TEMPORARY RANDOM STREAM CHECK - //if (yr%1 == 0 && gen == 0) - if (yr % 1 == 0) - { - DEBUGLOG << endl << "RunModel(): start of gen " << gen << " in year " << yr - << " for rep " << rep << " ("; - for (int i = 0; i < 5; i++) { - int rrrr = pRandom->IRandom(1000, 2000); - DEBUGLOG << " " << rrrr; - } - DEBUGLOG << " )" << endl; - } -#endif - if (v.viewPop || (sim.saveMaps && yr % sim.mapInt == 0)) { if (updateland && gen == 0) { pLandscape->drawLandscape(rep, landIx, ppLand.landNum); @@ -536,23 +441,13 @@ int RunModel(Landscape* pLandscape, int seqsim) if (dem.stageStruct && (sim.outRange || sim.outPop)) RangePopOutput(pComm, rep, yr, gen); -#if RSDEBUG - DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed reproduction" << endl; -#endif - // Dispersal pComm->emigration(); -#if RSDEBUG - DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed emigration" << endl; -#endif #if RS_RCPP pComm->dispersal(landIx, yr); #else pComm->dispersal(landIx); #endif // RS_RCPP -#if RSDEBUG - DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed dispersal" << endl; -#endif // survival part 0 if (dem.stageStruct) { @@ -570,41 +465,24 @@ int RunModel(Landscape* pLandscape, int seqsim) else { // non-structured population pComm->survival(0, 1, 1); } -#if RSDEBUG - DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed survival part 0" << endl; -#endif - // output Individuals if (sim.outInds && yr >= sim.outStartInd && yr % sim.outIntInd == 0) pComm->outInds(rep, yr, gen, -1); // output Genetics - //auto start = high_resolution_clock::now(); if ((sim.outputWCFstat || sim.outputPairwiseFst) && yr % sim.outputGeneticInterval == 0) { if (pLandscape) pComm->sampleIndividuals(pSpecies); pComm->outNeutralGenetics(pSpecies, rep, yr, gen, sim.outputPerLocusWCFstat, sim.outputPairwiseFst); } - //auto stop = high_resolution_clock::now(); - // auto duration = duration_cast(stop - start); - //cout << "genetic output took " << duration.count() << endl; - // survival part 1 if (dem.stageStruct) { - // if (sstruct.survival != 2) { // at reproduction or between reproduction events pComm->survival(1, 0, 1); - // } } else { // non-structured population pComm->survival(1, 0, 1); } -#if RSDEBUG - DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed survival part 1" << endl; -#endif } // end of the generation loop -#if RSDEBUG - DEBUGLOG << "RunModel(): yr=" << yr << " completed generation loop" << endl; -#endif totalInds = pComm->totalInds(); if (totalInds <= 0) { yr++; break; } @@ -617,9 +495,6 @@ int RunModel(Landscape* pLandscape, int seqsim) if (dem.stageStruct && sstruct.survival == 2) { // annual survival - all stages pComm->survival(0, 1, 2); pComm->survival(1, 0, 1); -#if RSDEBUG - DEBUGLOG << "RunModel(): yr=" << yr << " completed annual survival" << endl; -#endif } if (dem.stageStruct) { @@ -627,9 +502,6 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outInds && yr >= sim.outStartInd && yr % sim.outIntInd == 0) pComm->outInds(rep, yr, -1, -1); // list any individuals dying having reached maximum age pComm->survival(1, 0, 1); // delete any such individuals -#if RSDEBUG - DEBUGLOG << "RunModel(): yr=" << yr << " completed Age_increment and final survival" << endl; -#endif totalInds = pComm->totalInds(); if (totalInds <= 0) { yr++; break; } } @@ -651,9 +523,6 @@ int RunModel(Landscape* pLandscape, int seqsim) PreReproductionOutput(pLandscape, pComm, rep, yr, 0); if (sim.outRange || sim.outPop) RangePopOutput(pComm, rep, yr, 0); -#if RSDEBUG - DEBUGLOG << "RunModel(): yr=" << yr << " completed final summary output" << endl; -#endif pComm->resetPopns(); @@ -661,12 +530,6 @@ int RunModel(Landscape* pLandscape, int seqsim) if (grad.gradient) paramsGrad->resetOptY(); pLandscape->resetLandLimits(); -#if RSDEBUG - DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << "reset" - << " npatchchanges=" << npatchchanges << " ncostchanges=" << ncostchanges - << " ixpchchg=" << ixpchchg << " ixcostchg=" << ixcostchg - << endl; -#endif if (ppLand.patchModel && ppLand.dynamic && ixpchchg > 0) { // apply any patch changes to reset landscape to original configuration // (provided that at least one has already occurred) @@ -675,15 +538,6 @@ int RunModel(Landscape* pLandscape, int seqsim) Cell* pCell; patchchange = pLandscape->getPatchChange(ixpchchg++); while (patchchange.chgnum <= 666666 && ixpchchg <= npatchchanges) { -#if RSDEBUG - //DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << "reset" - // << " npatchchanges=" << npatchchanges << " ixpchchg=" << ixpchchg - // << " patchchange.chgnum=" << patchchange.chgnum - // << " .oldpatch=" << patchchange.oldpatch - // << " .newpatch=" << patchchange.newpatch - // << " .x=" << patchchange.x << " .y=" << patchchange.y - // << endl; -#endif // move cell from original patch to new patch pCell = pLandscape->findCell(patchchange.x, patchchange.y); if (patchchange.oldpatch != 0) { // not matrix @@ -713,15 +567,6 @@ int RunModel(Landscape* pLandscape, int seqsim) Cell* pCell; costchange = pLandscape->getCostChange(ixcostchg++); while (costchange.chgnum <= 666666 && ixcostchg <= ncostchanges) { -#if RSDEBUG - //DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << landIx - // << " ncostchanges=" << ncostchanges << " ixcostchg=" << ixcostchg - // << " costchange.chgnum=" << costchange.chgnum - // << " .x=" << costchange.x << " .y=" << costchange.y - // << " .oldcost=" << costchange.oldcost - // << " .newcost=" << costchange.newcost - // << endl; -#endif pCell = pLandscape->findCell(costchange.x, costchange.y); if (pCell != 0) { pCell->setCost(costchange.newcost); @@ -734,16 +579,6 @@ int RunModel(Landscape* pLandscape, int seqsim) if (!trfr.costMap) pLandscape->resetCosts(); // in case habitats have changed } } - // if (landIx < pLandscape->numLandChanges()) { // get next change - // landChg = pLandscape->getLandChange(landIx); - // } - // else { - // landChg.chgyear = 9999999; - // } -#if RSDEBUG - DEBUGLOG << "RunModel(): yr=" << yr << " completed reset" - << endl; -#endif if (sim.outConnect && ppLand.patchModel) pLandscape->resetConnectMatrix(); // set connectivity matrix to zeroes @@ -764,9 +599,6 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outPaths) pLandscape->outPathsHeaders(rep, -999); #endif -#if RSDEBUG - DEBUGLOG << endl << "RunModel(): finished rep=" << rep << endl; -#endif } // end of the replicates loop diff --git a/Parameters.cpp b/Parameters.cpp index 0ea711b..dd4a335 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -392,7 +392,8 @@ string paramSim::getDir(int option) { const sex_t stringToSex(const std::string& str) { if (str == "female") return FEM; else if (str == "male") return MAL; - else throw logic_error("Traits file: ERROR - sex can either be 'female' or 'male'."); + else if (str == "n/a") return NA; + else return INVALID_SEX; } set convertStringToPatches(const string& str, const int& nb_rnd_patches, const vector& existingPatches) { diff --git a/Parameters.h b/Parameters.h index 88fc434..6903574 100644 --- a/Parameters.h +++ b/Parameters.h @@ -117,7 +117,7 @@ const rgb draw_wheel(int); enum TraitType { SNP, - GENETIC_LOAD, ADAPTIVE1, ADAPTIVE2, ADAPTIVE3, ADAPTIVE4, ADAPTIVE5, + GENETIC_LOAD, GENETIC_LOAD1, GENETIC_LOAD2, GENETIC_LOAD3, GENETIC_LOAD4, GENETIC_LOAD5, E_D0_F, E_ALPHA_F, E_BETA_F, S_S0_F, S_ALPHA_F, S_BETA_F, @@ -131,7 +131,9 @@ enum TraitType { KERNEL_MEANDIST_1_F, KERNEL_MEANDIST_2_F, KERNEL_PROBABILITY_F, KERNEL_MEANDIST_1_M, KERNEL_MEANDIST_2_M, KERNEL_PROBABILITY_M, - SMS_DP, SMS_GB, SMS_ALPHADB, SMS_BETADB + SMS_DP, SMS_GB, SMS_ALPHADB, SMS_BETADB, + + INVALID_TRAIT // for error handling }; typedef std::string parameter_t; @@ -161,7 +163,9 @@ set convertStringToChromosomeEnds(string, int); //sex types typedef enum { - FEM = 0, MAL = 1 + FEM = 0, MAL = 1, + NA, // not applicable. e.g. fro SNP or genetic load trait + INVALID_SEX // error } sex_t; const sex_t stringToSex(const std::string& str); diff --git a/Population.cpp b/Population.cpp index e2590f6..cbc09c1 100644 --- a/Population.cpp +++ b/Population.cpp @@ -59,16 +59,11 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) patchPopn pp = patchPopn(); pp.pSp = (intptr)pSpecies; pp.pPop = (intptr)this; pPatch->addPopn(pp); -#if RSDEBUG - //DEBUGLOG << "Population::Population(): this=" << this - // << " added population to patch " << endl; -#endif demogrParams dem = pSpecies->getDemogrParams(); stageParams sstruct = pSpecies->getStageParams(); emigRules emig = pSpecies->getEmigRules(); transferRules trfr = pSpecies->getTransferRules(); - //trfrSMSTraits sms = pSpecies->getSMSTraits(); settleType sett = pSpecies->getSettle(); initParams init = paramsInit->getInit(); @@ -123,10 +118,6 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) else { // non-structured - all individuals go into stage 1 n = ninds; } - // for (int sex = 0; sex < nSexes; sex++) { - // if (n < nSexes) n = nSexes; // to ensure at least one individual of each age is created - // subPops.push_back(new SubPop(loc,stg,sex,n/nSexes)); - // } // establish initial age distribution minage = maxage = stg; if (dem.stageStruct) { diff --git a/SNPTrait.h b/SNPTrait.h index 5bea21c..d367099 100644 --- a/SNPTrait.h +++ b/SNPTrait.h @@ -19,8 +19,6 @@ class SNPTrait : public TTrait { SpeciesTrait* pProtoTrait; - //vector> mutations; - map> genes; //position > void (SNPTrait::* _mutate_func_ptr) (void); diff --git a/Species.cpp b/Species.cpp index 203bbda..ec463bc 100644 --- a/Species.cpp +++ b/Species.cpp @@ -424,27 +424,27 @@ void Species::addTrait(TraitType traitType, const SpeciesTrait& trait) { switch (n) { case 1: { - traitT = ADAPTIVE1; + traitT = GENETIC_LOAD1; break; } case 2: { - traitT = ADAPTIVE2; + traitT = GENETIC_LOAD2; break; } case 3: { - traitT = ADAPTIVE3; + traitT = GENETIC_LOAD3; break; } case 4: { - traitT = ADAPTIVE4; + traitT = GENETIC_LOAD4; break; } case 5: { - traitT = ADAPTIVE5; + traitT = GENETIC_LOAD5; break; } default: @@ -465,11 +465,6 @@ void Species::clearTraitTable() { spTraitTable.clear(); } -//map>& Species::getTraitTable(void) -//{ -// return traitTable; -//} - set Species::getTraitTypes() { auto kv = std::ranges::views::keys(spTraitTable); set keys{ kv.begin(), kv.end() }; diff --git a/SubCommunity.cpp b/SubCommunity.cpp index f2395d7..d15166e 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -61,19 +61,11 @@ void SubCommunity::setInitial(bool b) { initial = b; } void SubCommunity::initialise(Landscape* pLandscape, Species* pSpecies) { - //patchLimits limits; - //locn loc; int ncells; landParams ppLand = pLandscape->getLandParams(); initParams init = paramsInit->getInit(); -#if RSDEBUG - //DEBUGLOG << "SubCommunity::initialise(): subCommNum=" << subCommNum - // << " seedType="<< init.seedType - // << " popns.size()="<< popns.size() - // << endl; -#endif + // determine size of initial population -//int hx,nInds; int nInds = 0; if (subCommNum == 0 // matrix patch || !initial) // not in initial region or distribution @@ -102,10 +94,6 @@ void SubCommunity::initialise(Landscape* pLandscape, Species* pSpecies) else nInds = 0; } - // create new population (even if it has no individuals) - //popns.push_back(new Population(pSpecies,pPatch,nInds)); - //newPopn(pSpecies,pPatch,nInds); - // create new population only if it is non-zero or the matrix popn if (subCommNum == 0 || nInds > 0) { newPopn(pLandscape, pSpecies, pPatch, nInds); @@ -126,8 +114,6 @@ void SubCommunity::initialInd(Landscape* pLandscape, Species* pSpecies, short stg, age, repInt; Individual* pInd; float probmale; - // bool movt; - // short moveType; // create new population if not already in existence int npopns = (int)popns.size(); @@ -168,18 +154,9 @@ void SubCommunity::initialInd(Landscape* pLandscape, Species* pSpecies, Population* SubCommunity::newPopn(Landscape* pLandscape, Species* pSpecies, Patch* pPatch, int nInds) { -#if RSDEBUG - //DEBUGLOG << "SubCommunity::newPopn(): subCommNum = " << subCommNum - // << " pPatch = " << pPatch << " nInds = "<< nInds << endl; -#endif landParams land = pLandscape->getLandParams(); int npopns = (int)popns.size(); popns.push_back(new Population(pSpecies, pPatch, nInds, land.resol)); -#if RSDEBUG - //DEBUGLOG << "SubCommunity::newPopn(): subCommNum = " << subCommNum - // << " npopns = " << npopns << " popns[npopns] = " << popns[npopns] - // << endl; -#endif return popns[npopns]; } @@ -188,14 +165,8 @@ popStats SubCommunity::getPopStats(void) { p.pSpecies = 0; p.spNum = 0; p.nInds = p.nAdults = p.nNonJuvs = 0; p.breeding = false; p.pPatch = pPatch; // FOR SINGLE SPECIES IMPLEMENTATION, THERE IS ONLY ONE POPULATION IN THE PATCH - //p = popns[0]->getStats(); int npops = (int)popns.size(); for (int i = 0; i < npops; i++) { // all populations -#if RSDEBUG - //DEBUGLOG << "SubCommunity::getPopStats(): npops = " << npops - // << " i = " << i - // << " popns[i] = " << popns[i] << endl; -#endif pop = popns[i]->getStats(); p.pSpecies = pop.pSpecies; p.spNum = pop.spNum; @@ -203,14 +174,6 @@ popStats SubCommunity::getPopStats(void) { p.nNonJuvs += pop.nNonJuvs; p.nAdults += pop.nAdults; p.breeding = pop.breeding; -#if RSDEBUG - //DEBUGLOG << "SubCommunity::getPopStats():" - // << " p.pSpecies = " << p.pSpecies - // << " p.pPatch = " << p.pPatch - // << " p.spNum = " << p.spNum - // << " p.nInds = " << p.nInds - // << endl; -#endif } return p; } diff --git a/TTrait.h b/TTrait.h index 733fbbd..71395c3 100644 --- a/TTrait.h +++ b/TTrait.h @@ -17,22 +17,11 @@ class TTrait { virtual void mutate() = 0; virtual unique_ptr clone() const = 0; //copies parameters (if not static) not gene seqeunces - - /** Inheritance procedure, creates a new trait from mother's and father's traits - * @param mother the mother's trait - * @param father the father's trait - **/ virtual void inherit(TTrait*, set const& , sex_t, int ) = 0; - /** sequence accessor. - * @return the sequence pointer - **/ - // virtual void** get_sequence() const = 0; virtual int getNLoci() const = 0; virtual float getMutationRate() const = 0; virtual bool isInherited() const = 0; - //virtual vector>> get_mutations() const = 0; - //virtual vector> get_mutations() const = 0; virtual float getSelectionCoefAtLoci(short chromosome, int i) const = 0; virtual int countHeterozygoteLoci() const = 0; virtual bool isHeterozygoteAtLocus(int loci) const = 0; diff --git a/TraitFactory.h b/TraitFactory.h index 73836e3..50a6208 100644 --- a/TraitFactory.h +++ b/TraitFactory.h @@ -18,7 +18,11 @@ class TraitFactory if (traitType == SNP) { return make_unique(protoTrait); } - else if (traitType == ADAPTIVE1 || traitType == ADAPTIVE2 || traitType == ADAPTIVE3 || traitType == ADAPTIVE4 || traitType == ADAPTIVE5) { + else if (traitType == GENETIC_LOAD1 + || traitType == GENETIC_LOAD2 + || traitType == GENETIC_LOAD3 + || traitType == GENETIC_LOAD4 + || traitType == GENETIC_LOAD5) { return make_unique(protoTrait); } else { From 0fa3eec836af28a2d167147c40868acfdc600a9a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 1 Mar 2024 18:44:25 +0000 Subject: [PATCH 068/332] progress enabling sex-indepdt QTL traits --- Individual.cpp | 81 ++++++++++++++++++++++++++++++++++++-------------- Parameters.h | 7 ++++- 2 files changed, 65 insertions(+), 23 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 4494f58..de75d93 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -377,18 +377,30 @@ void Individual::setSettPatch(const settlePatch s) { void Individual::setEmigTraits(Species* pSpecies, bool sexDep, bool densityDep) { emigTraits e; e.d0 = e.alpha = e.beta = 0.0; - if (sexDep && this->getSex() == MAL) { - e.d0 = this->getTrait(E_D0_M)->express(); - if (densityDep) { - e.alpha = getTrait(E_ALPHA_M)->express(); - e.beta = getTrait(E_BETA_M)->express(); + if (sexDep) { + if (this->getSex() == MAL) { + e.d0 = this->getTrait(E_D0_M)->express(); + if (densityDep) { + e.alpha = getTrait(E_ALPHA_M)->express(); + e.beta = getTrait(E_BETA_M)->express(); + } } - } + else if (this->getSex() == FEM) { + e.d0 = this->getTrait(E_D0_F)->express(); + if (densityDep) { + e.alpha = getTrait(E_ALPHA_F)->express(); + e.beta = getTrait(E_BETA_F)->express(); + } + } + else { + throw runtime_error("Attempt to express invalid emigration trait sex."); + } + } else { - e.d0 = this->getTrait(E_D0_F)->express(); + e.d0 = this->getTrait(E_D0)->express(); if (densityDep) { - e.alpha = getTrait(E_ALPHA_F)->express(); - e.beta = getTrait(E_BETA_F)->express(); + e.alpha = getTrait(E_ALPHA)->express(); + e.beta = getTrait(E_BETA)->express(); } } @@ -415,22 +427,37 @@ emigTraits Individual::getEmigTraits(void) { void Individual::setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel, int resol) { trfrKernelParams k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; - if (sexDep && this->sex == MAL) { - k.meanDist1 = getTrait(KERNEL_MEANDIST_1_M)->express(); - if (twinKernel) { // twin kernel - k.meanDist2 = getTrait(KERNEL_MEANDIST_2_M)->express(); - k.probKern1 = getTrait(KERNEL_PROBABILITY_M)->express(); + if (sexDep) { + if (this->sex == MAL) { + k.meanDist1 = getTrait(KERNEL_MEANDIST_1_M)->express(); + + if (twinKernel) { // twin kernel + k.meanDist2 = getTrait(KERNEL_MEANDIST_2_M)->express(); + k.probKern1 = getTrait(KERNEL_PROBABILITY_M)->express(); + } + } + else if (this->sex == FEM) { + k.meanDist1 = getTrait(KERNEL_MEANDIST_1_F)->express(); + + if (twinKernel) { // twin kernel + k.meanDist2 = getTrait(KERNEL_MEANDIST_2_F)->express(); + k.probKern1 = getTrait(KERNEL_PROBABILITY_F)->express(); + } + } + else { + throw runtime_error("Attempt to express invalid kernel transfer trait sex."); } } else { - k.meanDist1 = getTrait(KERNEL_MEANDIST_1_F)->express(); + k.meanDist1 = getTrait(KERNEL_MEANDIST_1)->express(); if (twinKernel) { // twin kernel - k.meanDist2 = getTrait(KERNEL_MEANDIST_2_F)->express(); - k.probKern1 = getTrait(KERNEL_PROBABILITY_F)->express(); + k.meanDist2 = getTrait(KERNEL_MEANDIST_2)->express(); + k.probKern1 = getTrait(KERNEL_PROBABILITY)->express(); } } + float meanDist1 = (float)(k.meanDist1); float meanDist2 = (float)(k.meanDist2); float probKern1 = (float)(k.probKern1); @@ -521,13 +548,23 @@ trfrSMSTraits Individual::getSMSTraits(void) { // Set phenotypic transfer by CRW traits void Individual::setCRWTraits(Species* pSpecies, bool sexDep) { trfrCRWTraits c; c.stepLength = c.rho = 0.0; - if (sexDep && this->sex == MAL) { - c.stepLength = getTrait(CRW_STEPLENGTH_M)->express(); - c.rho = getTrait(CRW_STEPCORRELATION_M)->express(); + + if (sexDep) { + if (this->sex == MAL) { + c.stepLength = getTrait(CRW_STEPLENGTH_M)->express(); + c.rho = getTrait(CRW_STEPCORRELATION_M)->express(); + } + else if (this->sex == FEM) { + c.stepLength = getTrait(CRW_STEPLENGTH_F)->express(); + c.rho = getTrait(CRW_STEPCORRELATION_F)->express(); + } + else { + throw runtime_error("Attempt to express invalid CRW transfer trait sex."); + } } else { - c.stepLength = getTrait(CRW_STEPLENGTH_F)->express(); - c.rho = getTrait(CRW_STEPCORRELATION_F)->express(); + c.stepLength = getTrait(CRW_STEPLENGTH)->express(); + c.rho = getTrait(CRW_STEPCORRELATION)->express(); } auto& pCRW = dynamic_cast(*pTrfrData); diff --git a/Parameters.h b/Parameters.h index 6903574..89f6798 100644 --- a/Parameters.h +++ b/Parameters.h @@ -119,21 +119,26 @@ enum TraitType { SNP, GENETIC_LOAD, GENETIC_LOAD1, GENETIC_LOAD2, GENETIC_LOAD3, GENETIC_LOAD4, GENETIC_LOAD5, + E_D0, E_ALPHA, E_BETA, + S_S0, S_ALPHA, S_BETA, + E_D0_F, E_ALPHA_F, E_BETA_F, S_S0_F, S_ALPHA_F, S_BETA_F, E_D0_M, E_ALPHA_M, E_BETA_M, S_S0_M, S_ALPHA_M, S_BETA_M, + CRW_STEPLENGTH, CRW_STEPCORRELATION, CRW_STEPLENGTH_F, CRW_STEPCORRELATION_F, CRW_STEPLENGTH_M, CRW_STEPCORRELATION_M, + KERNEL_MEANDIST_1, KERNEL_MEANDIST_2, KERNEL_PROBABILITY, KERNEL_MEANDIST_1_F, KERNEL_MEANDIST_2_F, KERNEL_PROBABILITY_F, KERNEL_MEANDIST_1_M, KERNEL_MEANDIST_2_M, KERNEL_PROBABILITY_M, SMS_DP, SMS_GB, SMS_ALPHADB, SMS_BETADB, - INVALID_TRAIT // for error handling + INVALID_TRAIT // error }; typedef std::string parameter_t; From c004b48633e47e204245ce4b6462aa496b6f972d Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 5 Mar 2024 21:35:14 +0000 Subject: [PATCH 069/332] progress on verifying trait input --- Individual.cpp | 23 ++++---------------- Individual.h | 2 +- Landscape.cpp | 59 ++++++++++++++++++++++++++------------------------ Parameters.cpp | 2 +- Parameters.h | 2 -- 5 files changed, 37 insertions(+), 51 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index de75d93..4127fbf 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -252,7 +252,7 @@ void Individual::setTransferTraits(Species* pSpecies, transferRules trfr, int re setSMSTraits(pSpecies); } else - setCRWTraits(pSpecies, trfr.sexDep); + setCRWTraits(pSpecies); } else setKernelTraits(pSpecies, trfr.sexDep, trfr.twinKern, resol); @@ -546,26 +546,11 @@ trfrSMSTraits Individual::getSMSTraits(void) { // Set phenotypic transfer by CRW traits -void Individual::setCRWTraits(Species* pSpecies, bool sexDep) { +void Individual::setCRWTraits(Species* pSpecies) { trfrCRWTraits c; c.stepLength = c.rho = 0.0; - if (sexDep) { - if (this->sex == MAL) { - c.stepLength = getTrait(CRW_STEPLENGTH_M)->express(); - c.rho = getTrait(CRW_STEPCORRELATION_M)->express(); - } - else if (this->sex == FEM) { - c.stepLength = getTrait(CRW_STEPLENGTH_F)->express(); - c.rho = getTrait(CRW_STEPCORRELATION_F)->express(); - } - else { - throw runtime_error("Attempt to express invalid CRW transfer trait sex."); - } - } - else { - c.stepLength = getTrait(CRW_STEPLENGTH)->express(); - c.rho = getTrait(CRW_STEPCORRELATION)->express(); - } + c.stepLength = getTrait(CRW_STEPLENGTH)->express(); + c.rho = getTrait(CRW_STEPCORRELATION)->express(); auto& pCRW = dynamic_cast(*pTrfrData); pCRW.stepLength = (float)(c.stepLength); diff --git a/Individual.h b/Individual.h index 443cb44..b60a2f3 100644 --- a/Individual.h +++ b/Individual.h @@ -277,7 +277,7 @@ class Individual { trfrSMSTraits getSMSTraits(void); // Get phenotypic transfer by SMS traits - void setCRWTraits(Species* pSpecies, bool sexDep); + void setCRWTraits(Species* pSpecies); trfrCRWTraits getCRWTraits(void); // Get phenotypic transfer by CRW traits diff --git a/Landscape.cpp b/Landscape.cpp index 9f293f1..4ea77e3 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -1878,17 +1878,24 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string } #endif - dimX = ncols; dimY = nrows; minX = maxY = 0; maxX = dimX - 1; maxY = dimY - 1; + dimX = ncols; + dimY = nrows; + minX = maxY = 0; + maxX = dimX - 1; + maxY = dimY - 1; + if (fileNum == 0) { // set initialisation limits to landscape limits init.minSeedX = init.minSeedY = 0; - init.maxSeedX = maxX; init.maxSeedY = maxY; + init.maxSeedX = maxX; + init.maxSeedY = maxY; paramsInit->setInit(init); } if (fileNum == 0) { if (patchModel) { - for (int i = 0; i < 5; i++) pfile >> header >> pfloat; + for (int i = 0; i < 5; i++) + pfile >> header >> pfloat; pfile >> header >> pchnodata; } #if RS_RCPP @@ -1937,37 +1944,33 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string #endif p = (int)pfloat; #if RS_RCPP - } - else { - // corrupt file stream + } else { // corrupt file stream #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; -#endif - StreamErrorR(pchfile); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 132; - } + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR(pchfile); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 132; + } #endif } #if RS_RCPP - } - else { - // corrupt file stream + } else { // corrupt file stream #if RS_RCPP && !R_CMD Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - StreamErrorR(habfile); - hfile.close(); - hfile.clear(); - if (patchModel) { - pfile.close(); - pfile.clear(); + StreamErrorR(habfile); + hfile.close(); + hfile.clear(); + if (patchModel) { + pfile.close(); + pfile.clear(); + } + return 135; } - return 135; - } #endif if (h == habnodata) addNewCellToLand(x, y, -1); // add cell only to landscape @@ -1993,8 +1996,8 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string if (patchModel) { if (p < 0 || p == pchnodata) { // invalid patch code #if RS_RCPP && !R_CMD - if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; - else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; + if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; #endif hfile.close(); hfile.clear(); pfile.close(); pfile.clear(); diff --git a/Parameters.cpp b/Parameters.cpp index dd4a335..f4bef04 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -392,7 +392,7 @@ string paramSim::getDir(int option) { const sex_t stringToSex(const std::string& str) { if (str == "female") return FEM; else if (str == "male") return MAL; - else if (str == "n/a") return NA; + else if (str == "#") return NA; else return INVALID_SEX; } diff --git a/Parameters.h b/Parameters.h index 89f6798..6a97c37 100644 --- a/Parameters.h +++ b/Parameters.h @@ -129,8 +129,6 @@ enum TraitType { S_S0_M, S_ALPHA_M, S_BETA_M, CRW_STEPLENGTH, CRW_STEPCORRELATION, - CRW_STEPLENGTH_F, CRW_STEPCORRELATION_F, - CRW_STEPLENGTH_M, CRW_STEPCORRELATION_M, KERNEL_MEANDIST_1, KERNEL_MEANDIST_2, KERNEL_PROBABILITY, KERNEL_MEANDIST_1_F, KERNEL_MEANDIST_2_F, KERNEL_PROBABILITY_F, From e186b64466ba9954bf6fb5f103dbcf7d6c00fc11 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 18 Mar 2024 13:45:09 +0100 Subject: [PATCH 070/332] check expression type --- Parameters.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Parameters.h b/Parameters.h index 6a97c37..2aad955 100644 --- a/Parameters.h +++ b/Parameters.h @@ -153,7 +153,7 @@ constexpr auto SCALE = "scale"; enum DistributionType { UNIFORM, NORMAL, GAMMA, NEGEXP, SCALED, KAM, SSM, NONE }; -enum ExpressionType { AVERAGE, ADDITIVE, NEUTRAL, MULTIPLICATIVE }; +enum ExpressionType { AVERAGE, ADDITIVE, NOTEXPR, MULTIPLICATIVE }; /** Param's types **/ typedef enum { KERNEL, SMS, CRW} movement_t; From dee75edbb1ca5231a49520c96d0458783cf0d51d Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 18 Mar 2024 14:51:22 +0100 Subject: [PATCH 071/332] check init distribution --- Parameters.h | 3 --- SNPTrait.h | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Parameters.h b/Parameters.h index 2aad955..f03b895 100644 --- a/Parameters.h +++ b/Parameters.h @@ -147,9 +147,6 @@ constexpr auto MIN = "min"; constexpr auto MAX = "max"; constexpr auto SHAPE = "shape"; constexpr auto SCALE = "scale"; -//enums - -//enum GeneType { SNP, MICROSATELLITE, QTL, DELETERIOUS }; enum DistributionType { UNIFORM, NORMAL, GAMMA, NEGEXP, SCALED, KAM, SSM, NONE }; diff --git a/SNPTrait.h b/SNPTrait.h index d367099..c4d87b5 100644 --- a/SNPTrait.h +++ b/SNPTrait.h @@ -42,9 +42,9 @@ class SNPTrait : public TTrait { virtual unique_ptr clone() const override { return std::make_unique(*this); } - virtual void inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) override; + virtual void inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) override; - virtual void mutate() override { (this->*_mutate_func_ptr) (); } + virtual void mutate() override { (this->*_mutate_func_ptr) (); } virtual int getNLoci() const override { return pProtoTrait->getPositionsSize(); } From 77ddc6f4bb0fb09eecb567d25fa2386d8baca73a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 19 Mar 2024 15:28:23 +0100 Subject: [PATCH 072/332] progress checking chromosome ends --- Parameters.cpp | 99 -------------------------------------------------- Parameters.h | 7 ---- 2 files changed, 106 deletions(-) diff --git a/Parameters.cpp b/Parameters.cpp index f4bef04..5821779 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -389,105 +389,6 @@ string paramSim::getDir(int option) { return s; } -const sex_t stringToSex(const std::string& str) { - if (str == "female") return FEM; - else if (str == "male") return MAL; - else if (str == "#") return NA; - else return INVALID_SEX; -} - -set convertStringToPatches(const string& str, const int& nb_rnd_patches, const vector& existingPatches) { - - set patches; - - if (str == "random") { - if (nb_rnd_patches > existingPatches.size()) { - throw logic_error("Genetics file: ERROR - Nb of patches to randomly sample exceeds nb of existing patches."); - } else { - // Sample without replacement - std::sample( - existingPatches.begin(), - existingPatches.end(), - std::inserter(patches, patches.end()), - nb_rnd_patches, - pRandom->getRNG() - ); - } - } else if (str == "all") { - // Copy all patches into sampled patches - std::copy(existingPatches.begin(), - existingPatches.end(), - std::inserter(patches, patches.end()) - ); - } else { - // comma-separated list of patches - stringstream ss(str); - string strPch; - int pch; - bool patchExists; - // Read comma-separated values - while (std::getline(ss, strPch, ',')) { - pch = std::stoi(strPch); - patchExists = std::find(existingPatches.begin(), existingPatches.end(), pch) != existingPatches.end(); - if (!patchExists) - throw logic_error("Genetics file: ERROR - sampled patch does not exist."); - else { - patches.insert(pch); - } - } - } - return patches; -} - -set convertStringToChromosomeEnds(string str, int genomeSize) { - set chromosomeEnds; - if (str == "#") - chromosomeEnds.insert(genomeSize - 1); // last position in genome - else { - // Parse comma-separated list from input string - stringstream ss(str); - string strPos; - int pos; - // Read comma-separated positions - while (std::getline(ss, strPos, ',')) { - pos = std::stoi(strPos); - if (pos > genomeSize) - throw logic_error("Genetics file: ERROR - chromosome ends must not exceed genome size."); - else { - chromosomeEnds.insert(pos); - } - } - } - return chromosomeEnds; -} - -set convertStringToStages(const string& str, const int& nbStages) { - set stages; - if (str == "all") { - for (int stg = 0; stg < nbStages; ++stg) { - stages.insert(stg); - } - } - else { - // Parse comma-separated list from input string - stringstream ss(str); - string strStg; - int stg; - // Read comma-separated values - while (std::getline(ss, strStg, ',')) { - stg = std::stoi(strStg); - if (stg > nbStages - 1) - throw logic_error("Genetics file: ERROR - sampled stage exceeds number of stages."); - else { - stages.insert(stg); - } - } - } - return stages; -} - - - #if RS_RCPP bool paramSim::getReturnPopRaster(void) { return ReturnPopRaster; } bool paramSim::getCreatePopFile(void) { return CreatePopFile; } diff --git a/Parameters.h b/Parameters.h index f03b895..36ff4ba 100644 --- a/Parameters.h +++ b/Parameters.h @@ -155,12 +155,6 @@ enum ExpressionType { AVERAGE, ADDITIVE, NOTEXPR, MULTIPLICATIVE }; /** Param's types **/ typedef enum { KERNEL, SMS, CRW} movement_t; -//GeneType convertToGeneType(const string& ); - -set convertStringToPatches(const string&, const int&, const vector&); -set convertStringToStages(const string&, const int&); -set convertStringToChromosomeEnds(string, int); - //sex types typedef enum { FEM = 0, MAL = 1, @@ -168,7 +162,6 @@ typedef enum { INVALID_SEX // error } sex_t; -const sex_t stringToSex(const std::string& str); //--------------------------------------------------------------------------- // Environmental gradient parameters From bc5f9dc13cd8e7b654767d028201ce547ebb650f Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 28 Mar 2024 13:54:22 +0000 Subject: [PATCH 073/332] progress testing geneticsFile, standing bug in sampled pops --- Community.cpp | 79 ++++++++++-------------------------- Individual.cpp | 7 ++++ Landscape.cpp | 14 +------ Model.cpp | 3 -- NeutralStatsManager.cpp | 47 +++++----------------- NeutralStatsManager.h | 12 +++--- Population.cpp | 89 ++--------------------------------------- 7 files changed, 51 insertions(+), 200 deletions(-) diff --git a/Community.cpp b/Community.cpp index 3b83179..6716157 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1633,7 +1633,7 @@ void Community::sampleIndividuals(Species* pSpecies) { for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + auto pPop = (Population*)patch->getPopn((intptr)pSpecies); pPop->sampleIndsWithoutReplacement(n, stages); } } @@ -1644,7 +1644,6 @@ void Community::sampleIndividuals(Species* pSpecies) { bool Community::openWCFstatFile(Species* pSpecies, int landNr) { - if (landNr == -999) { // close the file if (outwcfstat.is_open()) outwcfstat.close(); outwcfstat.clear(); @@ -1654,13 +1653,6 @@ bool Community::openWCFstatFile(Species* pSpecies, int landNr) string name; simParams sim = paramsSim->getSim(); - -#if RSDEBUG - DEBUGLOG << "Community::outNeutralGeneticHeaders(): simulation=" << sim.simulation - << " sim.batchMode=" << sim.batchMode - << " landNr=" << landNr << endl; -#endif - if (sim.batchMode) { name = paramsSim->getDir(2) + "Batch" + Int2Str(sim.batchNum) + "_" @@ -1673,14 +1665,8 @@ bool Community::openWCFstatFile(Species* pSpecies, int landNr) } outwcfstat.open(name.c_str()); outwcfstat << "Rep\tYear\tRepSeason\tnExtantPatches\tnIndividuals\tfst\tfis\tfit\tmeanAllelePerLocus\tmeanAllelePerLocusPatches\tmeanFixedLoci\tmeanFixedLociPatches\tmeanObHeterozygosity"; - - outwcfstat << endl; -#if RSDEBUG - DEBUGLOG << "Community::outwcfstat(): finished" << endl; -#endif - return outwcfstat.is_open(); } @@ -1691,7 +1677,6 @@ bool Community::openWCFstatFile(Species* pSpecies, int landNr) bool Community::openWCPerLocusFstatFile(Species* pSpecies, Landscape* pLandscape, const int landNr, const int rep) { - const set patchList = pSpecies->getSamplePatches(); if (landNr == -999) { // close the file @@ -1703,13 +1688,6 @@ bool Community::openWCPerLocusFstatFile(Species* pSpecies, Landscape* pLandscape string name; simParams sim = paramsSim->getSim(); - -#if RSDEBUG - DEBUGLOG << "Community::outNeutralGeneticHeaders(): simulation=" << sim.simulation - << " sim.batchMode=" << sim.batchMode - << " landNr=" << landNr << endl; -#endif - if (sim.batchMode) { name = paramsSim->getDir(2) + "Batch" + Int2Str(sim.batchNum) + "_" @@ -1721,22 +1699,14 @@ bool Community::openWCPerLocusFstatFile(Species* pSpecies, Landscape* pLandscape else { name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Rep" + Int2Str(rep) + "_perLocusNeutralGenetics.txt"; } + outperlocusfstat.open(name.c_str()); outperlocusfstat << "Year\tRepSeason\tlocus\tfst\tfis\tfit\tpopHet"; - - - for (int patchId : patchList) { outperlocusfstat << "\tpatch_" + Int2Str(patchId) + "_Het"; } - - outperlocusfstat << endl; -#if RSDEBUG - DEBUGLOG << "Community::outperlocusfstat(): finished" << endl; -#endif - return outperlocusfstat.is_open(); } @@ -1757,13 +1727,6 @@ bool Community::openPairwiseFSTFile(Species* pSpecies, Landscape* pLandscape, co string name; simParams sim = paramsSim->getSim(); - -#if RSDEBUG - DEBUGLOG << "Community::outNeutralGeneticHeaders(): simulation=" << sim.simulation - << " sim.batchMode=" << sim.batchMode - << " landNr=" << landNr << endl; -#endif - if (sim.batchMode) { name = paramsSim->getDir(2) + "Batch" + Int2Str(sim.batchNum) + "_" @@ -1777,16 +1740,9 @@ bool Community::openPairwiseFSTFile(Species* pSpecies, Landscape* pLandscape, co } outpairwisefst.open(name.c_str()); outpairwisefst << "Year\tRepSeason\tpatchA\tpatchB\tfst"; - outpairwisefst << endl; -#if RSDEBUG - DEBUGLOG << "Community::outpairwisefst(): finished" << endl; -#endif - return outpairwisefst.is_open(); - - } // ---------------------------------------------------------------------------------------- @@ -1796,13 +1752,16 @@ bool Community::openPairwiseFSTFile(Species* pSpecies, Landscape* pLandscape, co void Community::writeWCFstatFile(int rep, int yr, int gen) { outwcfstat << rep << "\t" << yr << "\t" << gen << "\t"; - - outwcfstat << pNeutralStatistics->getNExtantPatchs() << "\t" << pNeutralStatistics->getNIndividuals() << "\t"; - - outwcfstat << pNeutralStatistics->getFstWC() << "\t" << pNeutralStatistics->getFisWC() << "\t" << pNeutralStatistics->getFitWC() << "\t"; - - outwcfstat << pNeutralStatistics->getNbAllGlobal() << "\t" << pNeutralStatistics->getNbAllLocal() << "\t" << pNeutralStatistics->getFixLocGlobal() - << "\t" << pNeutralStatistics->getFixLocLocal() << "\t" << pNeutralStatistics->getHo(); + outwcfstat << pNeutralStatistics->getNExtantPatchs() + << "\t" << pNeutralStatistics->getNIndividuals() << "\t"; + outwcfstat << pNeutralStatistics->getFstWC() << "\t" + << pNeutralStatistics->getFisWC() << "\t" + << pNeutralStatistics->getFitWC() << "\t"; + outwcfstat << pNeutralStatistics->getMeanNbAllPerLocus() + << "\t" << pNeutralStatistics->getMeanNbAllPerLocusPerPatch() << "\t" + << pNeutralStatistics->getTotalFixdAlleles() + << "\t" << pNeutralStatistics->getMeanFixdAllelesPerPatch() + << "\t" << pNeutralStatistics->getHo(); outwcfstat << endl; } @@ -1819,8 +1778,10 @@ void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const for (int position : positions) { outperlocusfstat << yr << "\t" << gen << "\t" << position << "\t"; - outperlocusfstat << pNeutralStatistics->get_fst_WC_loc(thisLocus) << "\t" << pNeutralStatistics->get_fis_WC_loc(thisLocus) << - "\t" << pNeutralStatistics->get_fit_WC_loc(thisLocus) << "\t" << pNeutralStatistics->get_ho_loc(thisLocus); + outperlocusfstat << pNeutralStatistics->get_fst_WC_loc(thisLocus) << "\t" + << pNeutralStatistics->get_fis_WC_loc(thisLocus) << "\t" + << pNeutralStatistics->get_fit_WC_loc(thisLocus) << "\t" + << pNeutralStatistics->get_ho_loc(thisLocus); for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); @@ -1847,7 +1808,9 @@ void Community::writePairwiseFSTFile(Species* pSpecies, const int yr, const int int i = 0; for (int patchId : patchList) { outpairwisefst << yr << "\t" << gen << "\t"; - outpairwisefst << patchId << "\t" << patchId << "\t" << pNeutralStatistics->getPairwiseFst(i, i) << endl; + outpairwisefst << patchId << "\t" << patchId << "\t" + << pNeutralStatistics->getPairwiseFst(i, i) + << endl; ++i; } @@ -1857,7 +1820,9 @@ void Community::writePairwiseFSTFile(Species* pSpecies, const int yr, const int int j = i + 1; for (int patchIdB : patchList | std::views::drop(j)) { outpairwisefst << yr << "\t" << gen << "\t"; - outpairwisefst << patchIdA << "\t" << patchIdB << "\t" << pNeutralStatistics->getPairwiseFst(i, j) << endl; + outpairwisefst << patchIdA << "\t" << patchIdB << "\t" + << pNeutralStatistics->getPairwiseFst(i, j) + << endl; ++j; } ++i; diff --git a/Individual.cpp b/Individual.cpp index 4127fbf..0eb9758 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -152,7 +152,11 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi // Draw recombination events for maternal genome if (pSpecies->getRecombinationRate() > 0.0) events = pRandom->Poisson(genomeSize * pSpecies->getRecombinationRate()); + // if poisson exceeds genomeSize, bound to genomeSize? int nbrCrossOvers = events + maternalRecomPositions.size(); + if (nbrCrossOvers > genomeSize) { + nbrCrossOvers = genomeSize; + } while (maternalRecomPositions.size() < nbrCrossOvers) { // Sample recombination sites maternalRecomPositions.insert(pRandom->IRandom(0, genomeSize)); @@ -162,6 +166,9 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi if (pSpecies->getRecombinationRate() > 0.0) events = pRandom->Poisson(genomeSize * pSpecies->getRecombinationRate()); nbrCrossOvers = events + paternalRecomPositions.size(); + if (nbrCrossOvers > genomeSize) { + nbrCrossOvers = genomeSize; + } while (paternalRecomPositions.size() < nbrCrossOvers) { paternalRecomPositions.insert(pRandom->IRandom(0, genomeSize)); } diff --git a/Landscape.cpp b/Landscape.cpp index 4ea77e3..0d5d75b 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -555,8 +555,6 @@ void Landscape::generatePatches(Species* pSpecies) Cell* pCell; vector ArtLandscape; - - setCellArray(); int patchnum = 0; // initial patch number for cell-based landscape @@ -654,15 +652,13 @@ void Landscape::generatePatches(Species* pSpecies) } simParams sim = paramsSim->getSim(); - if (pSpecies->getNumberOfNeutralLoci() > 0 && (sim.outputWCFstat || sim.outputPairwiseFst)) { + if (pSpecies->getNumberOfNeutralLoci() > 0 && (sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat)) { string cellsToSample = pSpecies->getNSampleCellsFst(); int n = (cellsToSample == "all") ? -9999 : stoi(cellsToSample); - auto patchesToSample = samplePatches(n, (cellsToSample == "all")); pSpecies->setSamplePatchList(patchesToSample); - } } @@ -698,8 +694,6 @@ void Landscape::allocatePatches(Species* pSpecies) for (int x = 0; x < dimX; x++) { if (cells[y][x] != 0) { // not no-data cell pCell = cells[y][x]; - // hx = pCell->getHabIndex(); - // habK = pSpecies->getHabK(hx); habK = 0.0; int nhab = pCell->nHabitats(); for (int i = 0; i < nhab; i++) { @@ -725,7 +719,6 @@ void Landscape::allocatePatches(Species* pSpecies) pCell = cells[y][x]; habK = 0.0; int nhab = pCell->nHabitats(); - // for (int i = 0; i < nHab; i++) for (int i = 0; i < nhab; i++) { habK += pSpecies->getHabK(i) * pCell->getHabitat(i) / 100.0f; @@ -771,7 +764,7 @@ void Landscape::allocatePatches(Species* pSpecies) } // end of switch (rasterType) simParams sim = paramsSim->getSim(); - if (pSpecies->getNumberOfNeutralLoci() > 0 && (sim.outputWCFstat || sim.outputPairwiseFst)) { + if (pSpecies->getNumberOfNeutralLoci() > 0 && (sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat)) { string cellsToSample = pSpecies->getNSampleCellsFst(); int n = (cellsToSample == "all") ? -9999 : stoi(cellsToSample); @@ -920,12 +913,9 @@ set Landscape::samplePatches(int n, bool all) { if (!all) { - auto rng = pRandom->getRNG(); - sample(allPatches.begin(), allPatches.end(), std::back_inserter(sampledPatches), n, rng); - } else sampledPatches = allPatches; diff --git a/Model.cpp b/Model.cpp index eb8012c..d6cc617 100644 --- a/Model.cpp +++ b/Model.cpp @@ -69,8 +69,6 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm = new Community(pLandscape); // set up community // set up a sub-community associated with each patch (incl. the matrix) pLandscape->updateCarryingCapacity(pSpecies, 0, 0); - // if (ppLand.rasterType <= 2 && ppLand.dmgLoaded) - // pLandscape->updateDamageIndices(); patchData ppp; int npatches = pLandscape->patchCount(); for (int i = 0; i < npatches; i++) { @@ -473,7 +471,6 @@ int RunModel(Landscape* pLandscape, int seqsim) if ((sim.outputWCFstat || sim.outputPairwiseFst) && yr % sim.outputGeneticInterval == 0) { if (pLandscape) pComm->sampleIndividuals(pSpecies); pComm->outNeutralGenetics(pSpecies, rep, yr, gen, sim.outputPerLocusWCFstat, sim.outputPairwiseFst); - } if (dem.stageStruct) { pComm->survival(1, 0, 1); diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 3c0b15a..8b77aa0 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -130,37 +130,37 @@ void NeutralStatsManager::setLociDiversityCounter(set const& patchList, con } } - _nb_alleles_local = (nbpatch ? pop_mean / nbpatch : nanf("NULL")); - _nb_alleles_global = 0; + meanNbAllelesPerLocusPerPatch = (nbpatch ? pop_mean / nbpatch : nanf("NULL")); + meanNbAllelesPerLocus = 0; for (i = 0; i < nLoci; ++i) for (j = 0; j < nAlleles; ++j) - _nb_alleles_global += pop_div[i][j]; + meanNbAllelesPerLocus += pop_div[i][j]; - _nb_alleles_global /= nLoci; + meanNbAllelesPerLocus /= nLoci; for (i = 0; i < nLoci; ++i) delete[] pop_div[i]; delete[] pop_div; //number of fixed loci, local and global counters: - _fix_loc_local = 0; + meanNbFixedAllelesPerPatch = 0; for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); for (i = 0; i < nLoci; ++i) for (j = 0; j < nAlleles; ++j) - _fix_loc_local += (pPop->getAlleleFrequency(i, j) == 1); + meanNbFixedAllelesPerPatch += (pPop->getAlleleFrequency(i, j) == 1); } - _fix_loc_local /= nbpatch; - _fix_loc_global = 0; + meanNbFixedAllelesPerPatch /= nbpatch; + totNbFixedAlleles = 0; //globally: for (i = 0; i < nLoci; ++i) for (j = 0; j < nAlleles; ++j) - _fix_loc_global += (globalAlleleTable[i].getFrequency(j) == 1); + totNbFixedAlleles += (globalAlleleTable[i].getFrequency(j) == 1); } // ---------------------------------------------------------------------------------------- @@ -241,8 +241,7 @@ void NeutralStatsManager::calculateHt(Species* pSpecies, Landscape* pLandscape, void NeutralStatsManager::calculateHo2(set const& patchList, const int nbInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape) { - vector hetero(nbrLoci, 0); - + vector hetero(nbrLoci, 0); double nLoci = nbInds * nbrLoci; for (int patchId : patchList) { @@ -592,12 +591,6 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd const auto patch = pLandscape->findPatch(patchVect[i]); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); -//#if RSDEBUG -// DEBUGLOG << "OutputPairwiseStats: 644 " -// << " population " << patch->getPatchNum() << " popSize[i] " << pop_sizes[i] << endl; -// // << endl; -//#endif - for (int l = 0; l < nLoci; ++l) { for (int u = 0; u < nAlleles; ++u) { @@ -618,14 +611,6 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd denominator += pop_sizes[i] * var + pop_weights[i] * pq; //common denominator -//#if RSDEBUG -// DEBUGLOG << "OutputPairwiseStats: 671 " -// << " loci " << l << " allele " << u << " frequency " << p << " pq " << pq << " var " << var << " num " << num << -// " numerator[i][i] " << numerator[i][i] << " numerator_W " << numerator_W << " denominator " << denominator -// << endl; -//#endif - - } // end for allele }// end for locus }//end for pop @@ -636,11 +621,6 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd _fst_matrix.set(i, i, 1 - (numerator[i][i] * sum_weights / denominator)); else _fst_matrix.set(i, i, 0.0); -//#if RSDEBUG -// DEBUGLOG << "OutputPairwiseStats: 717 " -// << " result " << 1 - (numerator[i][i] * sum_weights / denominator) << " in matrix " << getPairwiseFst(i, i) -// << endl; -//#endif } _fst_WH = 1 - ((numerator_W * sum_weights) / (denominator * tot_size)); //equ. 9 Weir & Hill 2002 @@ -673,13 +653,6 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd _fst_matrix.set(i, j, 1 - ((numerator[i][j] * sum_weights) / (2 * denominator))); else _fst_matrix.set(i, j, 0.0); - -//#if RSDEBUG -// DEBUGLOG << "OutputPairwiseStats: 717 " -// << " result " << 1 - ((numerator[i][j] * sum_weights) / (2 * denominator)) << " in matrix " << getPairwiseFst(i, j) -// << endl; -//#endif - } } delete[] pop_weights; diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index 4b269e0..8760781 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -105,8 +105,8 @@ class NeutralStatsManager { private: int _n_extantPopulations, _n_individuals; /**F-statistics*/ - double _ho, _hs, _ht, _hsnei, _htnei, _nb_alleles_local, _nb_alleles_global, - _fst, _fis, _fit, _fix_loc_local, _fix_loc_global; + double _ho, _hs, _ht, _hsnei, _htnei, meanNbAllelesPerLocusPerPatch, meanNbAllelesPerLocus, + _fst, _fis, _fit, meanNbFixedAllelesPerPatch, totNbFixedAlleles; /**Weir & Hill (2002) F-stat estimates.*/ double _fst_WH; /**Weir & Cockerham (1984) F-stat estimates.*/ @@ -152,10 +152,10 @@ class NeutralStatsManager { int getNExtantPatchs() const { return _n_extantPopulations; } int getNIndividuals() const { return _n_individuals; } double getWeightedFst() { return _fst_WH; } - double getNbAllLocal() const { return _nb_alleles_local; } - double getNbAllGlobal() const { return _nb_alleles_global; } - double getFixLocLocal() const { return _fix_loc_local; } - double getFixLocGlobal() const { return _fix_loc_global; } + double getMeanNbAllPerLocusPerPatch() const { return meanNbAllelesPerLocusPerPatch; } + double getMeanNbAllPerLocus() const { return meanNbAllelesPerLocus; } + double getMeanFixdAllelesPerPatch() const { return meanNbFixedAllelesPerPatch; } + double getTotalFixdAlleles() const { return totNbFixedAlleles; } double getPairwiseFst(int i, int j) { return _fst_matrix.get(i, j); } double get_fst_WC_loc(int i) const { return _fst_WC_loc[i]; } double get_fis_WC_loc(int i) const { return _fis_WC_loc[i]; } diff --git a/Population.cpp b/Population.cpp index cbc09c1..ff5deba 100644 --- a/Population.cpp +++ b/Population.cpp @@ -553,11 +553,6 @@ void Population::reproduction(const float localK, const float envval, const int // get population size at start of reproduction int ninds = (int)inds.size(); -#if RSDEBUG -//DEBUGLOG << "Population::reproduction(): this=" << this -// << " ninds=" << ninds -// << endl; -#endif // RSDEBUG if (ninds == 0) return; int nsexes, stage, sex, njuvs, nj, nmales, nfemales; @@ -574,15 +569,10 @@ void Population::reproduction(const float localK, const float envval, const int transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); - if (dem.repType == 0) nsexes = 1; else nsexes = 2; + if (dem.repType == 0) + nsexes = 1; + else nsexes = 2; -#if RSDEBUG -//DEBUGLOG << "Population::reproduction(): this=" << this -// << " pSpecies=" << pSpecies -// << " localK=" << localK << " envval=" << envval << " resol=" << resol -// << " sstruct.nStages=" << sstruct.nStages << " nsexes=" << nsexes << " ninds=" << ninds -// << endl; -#endif // set up local copy of species fecundity table float fec[maxNbStages][maxNbSexes]; @@ -595,28 +585,15 @@ void Population::reproduction(const float localK, const float envval, const int } else fec[stg][sex] = pSpecies->getFec(stg, sex); - // if (sex == 0 && fec[stg][sex] > dem.lambda) dem.lambda = fec[stg][sex]; } else { // non-structured population if (stg == 1) fec[stg][sex] = dem.lambda; // adults else fec[stg][sex] = 0.0; // juveniles } -#if RSDEBUG - //if (ninds > 0) { - //DEBUGLOG << "Population::reproduction(): fec[" << stg << "][" << sex << "] = " << fec[stg][sex] - // << endl; - //} -#endif } } if (dem.stageStruct) { -#if RSDEBUG - //if (ninds > 0) { - // DEBUGLOG << "Population::reproduction(): ninds=" << ninds << " localK=" << localK - // << " effect of density dependence:" << endl; - //} -#endif // apply environmental effects and density dependence // to all non-zero female non-juvenile stages for (int stg = 1; stg < nStages; stg++) { @@ -648,26 +625,12 @@ void Population::reproduction(const float localK, const float envval, const int weight = pSpecies->getDDwtFec(stg, effstg); } effect += (float)nInds[effstg][effsex] * weight; -#if RSDEBUG - //if (ninds > 0) { - // DEBUGLOG << " effstg=" << effstg << " effsex=" << effsex << " nInds=" << nInds[effstg][effsex]; - // DEBUGLOG << " weight=" << weight << " effect=" << effect - // << endl; - //} -#endif } } } else // not stage-specific effect = (float)totalPop(); if (localK > 0.0) fec[stg][0] *= exp(-effect / localK); -#if RSDEBUG - //if (ninds > 0) { - // DEBUGLOG << " eff popn=" << effect << " exponential=" << exp(-effect/localK); - // DEBUGLOG << " fec[" << stg << "][0]=" << fec[stg][0] - // << endl; - //} -#endif } } } @@ -686,21 +649,12 @@ void Population::reproduction(const float localK, const float envval, const int } // apply density dependence if (localK > 0.0) { - //#if GOBYMODEL - // ddeffect[1] = (float)ninds/localK; - //#else if (dem.repType == 1 || dem.repType == 2) { // sexual model // apply factor of 2 (as in manual, eqn. 6) fec[1][0] *= 2.0; } fec[1][0] /= (1.0f + fabs(dem.lambda - 1.0f) * pow(((float)ninds / localK), dem.bc)); - //#endif } -#if RSDEBUG - //DEBUGLOG << "Population::reproduction(): dem.lambda=" << dem.lambda << " ninds=" << ninds - // << " localK=" << localK << " dem.bc=" << dem.bc << " fec[1][0]=" << fec[1][0] - // << endl; -#endif } double propBreed; @@ -764,11 +718,6 @@ void Population::reproduction(const float localK, const float envval, const int case 2: // complex sexual model // count breeding females and males // add breeding males to list of potential fathers -#if RSDEBUG -//DEBUGLOG << "Population::reproduction(): case 1:" -// << " fec[1][0]=" << fec[1][0] << " fec[1][1]=" << fec[1][1] -// << endl; -#endif nfemales = nmales = 0; for (int i = 0; i < ninds; i++) { ind = inds[i]->getStats(); @@ -776,27 +725,14 @@ void Population::reproduction(const float localK, const float envval, const int if (ind.sex == 1 && fec[ind.stage][1] > 0.0) { fathers.push_back(inds[i]); nmales++; -#if RSDEBUG - //DEBUGLOG << "Population::reproduction(): i=" << i << " nmales=" << nmales - // << " inds[i]=" << inds[i] << endl; -#endif } } -#if RSDEBUG - //DEBUGLOG << "Population::reproduction(): breeding nfemales=" << nfemales - // << " breeding nmales=" << nmales << endl; -#endif if (nfemales > 0 && nmales > 0) { // population can breed if (dem.repType == 2) { // complex sexual model // calculate proportion of eligible females which breed propBreed = (2.0 * dem.harem * nmales) / (nfemales + dem.harem * nmales); if (propBreed > 1.0) propBreed = 1.0; -#if RSDEBUG - //DEBUGLOG << "Population::reproduction(): harem=" << dem.harem - // << " nfemales=" << nfemales << " nmales=" << nmales << " propBreed=" << propBreed - // << endl; -#endif } else propBreed = 1.0; for (int i = 0; i < ninds; i++) { @@ -821,20 +757,11 @@ void Population::reproduction(const float localK, const float envval, const int // NECESSARILY EQUAL THE EXPECTED NO. FROM EQN. 7 IN THE MANUAL... if (pRandom->Bernoulli(propBreed)) { expected = fec[stage][0]; // breeds -#if RSDEBUG - //DEBUGLOG << "Population::reproduction(): THIS LINE SHOULD NOT APPEAR FOR GOBY MODEL" - // << " expected=" << expected - // << endl; -#endif } else expected = 0.0; // fails to breed if (expected <= 0.0) njuvs = 0; else njuvs = pRandom->Poisson(expected); -#if RSDEBUG - //DEBUGLOG << "Population::reproduction():" - // << " i " << i << " ID=" << inds[i]->getId() << " stage=" << stage - // << " expected=" << expected << " njuvs=" << njuvs << endl; -#endif + if (njuvs > 0) { nj = (int)juvs.size(); @@ -844,7 +771,6 @@ void Population::reproduction(const float localK, const float envval, const int father = fathers[rrr]; pCell = pPatch->getRandomCell(); for (int j = 0; j < njuvs; j++) { - Individual* newJuv; #if RSDEBUG // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... @@ -881,17 +807,10 @@ void Population::reproduction(const float localK, const float envval, const int // Following reproduction of ALL species, add juveniles to the population prior to dispersal void Population::fledge(void) { -#if RSDEBUG - //DEBUGLOG << "Population::fledge(): this=" << this - // << " ninds=" << (int)inds.size() - // << " njuvs=" << (int)juvs.size() - // << endl; -#endif demogrParams dem = pSpecies->getDemogrParams(); if (dem.stageStruct) { // juveniles are added to the individuals vector inds.insert(inds.end(), juvs.begin(), juvs.end()); - // nInds += nJuvs; nJuvs = 0; } else { // all adults die and juveniles replace adults int ninds = (int)inds.size(); From 0acce45997650aa3c18d5807c317ee58bdf67df9 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 28 Mar 2024 16:37:02 +0000 Subject: [PATCH 074/332] make each neutral stat output independent --- Community.cpp | 17 ++++++++--------- Community.h | 2 +- Model.cpp | 4 ++-- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Community.cpp b/Community.cpp index 6716157..eeb0367 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1835,7 +1835,7 @@ void Community::writePairwiseFSTFile(Species* pSpecies, const int yr, const int // ---------------------------------------------------------------------------------------- -void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool perLocus, bool pairwise) { +void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool fstat, bool perLocus, bool pairwise) { const int nAlleles = (int)(pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second); const int nLoci = (int)pSpecies->getNPositionsForTrait(SNP); @@ -1852,25 +1852,24 @@ void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, pNeutralStatistics = make_unique(patchList, nLoci); pNeutralStatistics->updateAlleleTables(pSpecies, pLandscape, patchList); - pNeutralStatistics->calculateHo(patchList, nInds, nLoci, pSpecies, pLandscape); - pNeutralStatistics->setLociDiversityCounter(patchList, nInds, pSpecies, pLandscape); + + if (fstat) { + pNeutralStatistics->calculateHo(patchList, nInds, nLoci, pSpecies, pLandscape); + pNeutralStatistics->setLociDiversityCounter(patchList, nInds, pSpecies, pLandscape); + pNeutralStatistics->calculateFstatWC(patchList, nInds, nLoci, nAlleles, pSpecies, pLandscape); + writeWCFstatFile(rep, yr, gen); + } if (perLocus) { pNeutralStatistics->calculateFstatWC_MS(patchList, nInds, nLoci, nAlleles, pSpecies, pLandscape); pNeutralStatistics->calculateHo2(patchList, nInds, nLoci, pSpecies, pLandscape); writeWCPerLocusFstatFile(pSpecies, yr, gen, nAlleles, nLoci, patchList); } - else { - pNeutralStatistics->calculateFstatWC(patchList, nInds, nLoci, nAlleles, pSpecies, pLandscape); - } if (pairwise) { pNeutralStatistics->setFstMatrix(patchList, nInds, nLoci, pSpecies, pLandscape); writePairwiseFSTFile(pSpecies, yr, gen, nAlleles, nLoci, patchList); } - - // always write out the minimum stats - writeWCFstatFile(rep, yr, gen); } //--------------------------------------------------------------------------- diff --git a/Community.h b/Community.h index b4eb648..f559e60 100644 --- a/Community.h +++ b/Community.h @@ -209,7 +209,7 @@ class Community { void sampleIndividuals(Species* pSpecies); //control neutral stat output - void outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool perLocus, bool pairwise); + void outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool fstat, bool perLocus, bool pairwise); //file openers bool openWCFstatFile(Species* pSpecies, const int landNr); diff --git a/Model.cpp b/Model.cpp index d6cc617..2a6921f 100644 --- a/Model.cpp +++ b/Model.cpp @@ -468,9 +468,9 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outInds && yr >= sim.outStartInd && yr % sim.outIntInd == 0) pComm->outInds(rep, yr, gen, -1); // output Genetics - if ((sim.outputWCFstat || sim.outputPairwiseFst) && yr % sim.outputGeneticInterval == 0) { + if ((sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat) && yr % sim.outputGeneticInterval == 0) { if (pLandscape) pComm->sampleIndividuals(pSpecies); - pComm->outNeutralGenetics(pSpecies, rep, yr, gen, sim.outputPerLocusWCFstat, sim.outputPairwiseFst); + pComm->outNeutralGenetics(pSpecies, rep, yr, gen, sim.outputWCFstat, sim.outputPerLocusWCFstat, sim.outputPairwiseFst); } if (dem.stageStruct) { pComm->survival(1, 0, 1); From 77ae053069110e843643437e6bbb28c2fe2c1032 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 29 Mar 2024 15:13:58 +0000 Subject: [PATCH 075/332] improve readability of neutral data --- Community.cpp | 6 ++- GeneticLoad.cpp | 2 +- GeneticLoad.h | 2 +- Landscape.cpp | 11 ++-- Model.cpp | 2 +- NeutralStatsManager.cpp | 17 +++--- NeutralStatsManager.h | 50 +++++++---------- Population.cpp | 116 +++++++++------------------------------- Population.h | 4 +- QTLTrait.cpp | 2 +- QTLTrait.h | 4 +- SNPTrait.cpp | 2 +- SNPTrait.h | 2 +- TTrait.h | 2 +- 14 files changed, 75 insertions(+), 147 deletions(-) diff --git a/Community.cpp b/Community.cpp index eeb0367..fd35485 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1634,7 +1634,9 @@ void Community::sampleIndividuals(Species* pSpecies) { for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - pPop->sampleIndsWithoutReplacement(n, stages); + if (pPop != nullptr) { + pPop->sampleIndsWithoutReplacement(n, stages); + } } } @@ -1789,7 +1791,7 @@ void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const int popSize = pPop->sampleSize(); int het = 0; for (int a = 0; a < nAlleles; ++a) { - het += static_cast(pPop->getHetero(thisLocus, a)); // not sure why this returns a double + het += static_cast(pPop->getHeteroTally(thisLocus, a)); // not sure why this returns a double } outperlocusfstat << "\t" << het / (2.0 * popSize); } diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index 0f9e61c..dcf1811 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -404,7 +404,7 @@ int GeneticLoad::countHeterozygoteLoci() const { // ---------------------------------------------------------------------------------------- -float GeneticLoad::getSelectionCoefAtLoci(short whichChromosome, int position) const { +float GeneticLoad::getAlleleValueAtLocus(short whichChromosome, int position) const { auto it = genes.find(position); diff --git a/GeneticLoad.h b/GeneticLoad.h index 95d60ab..ed0c45c 100644 --- a/GeneticLoad.h +++ b/GeneticLoad.h @@ -54,7 +54,7 @@ class GeneticLoad : public TTrait { map>>& get_mutations() { return genes; } //returning reference, reciever must be const - virtual float getSelectionCoefAtLoci(short chromosome, int position) const override; + virtual float getAlleleValueAtLocus(short chromosome, int position) const override; virtual int countHeterozygoteLoci() const; diff --git a/Landscape.cpp b/Landscape.cpp index 0d5d75b..b2ef8ff 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -652,7 +652,8 @@ void Landscape::generatePatches(Species* pSpecies) } simParams sim = paramsSim->getSim(); - if (pSpecies->getNumberOfNeutralLoci() > 0 && (sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat)) { + if (pSpecies->getNumberOfNeutralLoci() > 0 && + (sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat)) { string cellsToSample = pSpecies->getNSampleCellsFst(); int n = (cellsToSample == "all") ? -9999 : stoi(cellsToSample); @@ -923,7 +924,6 @@ set Landscape::samplePatches(int n, bool all) { copy(sampledPatches.begin(), sampledPatches.end(), inserter(patchIds, patchIds.end())); return patchIds; - } void Landscape::resetPatchPopns(void) { @@ -1586,8 +1586,11 @@ void Landscape::recordPatchChanges(int landIx) { int Landscape::numPatchChanges(void) { return (int)patchchanges.size(); } patchChange Landscape::getPatchChange(int i) { - patchChange c; c.chgnum = 99999999; c.x = c.y = c.oldpatch = c.newpatch = -1; - if (i >= 0 && i < (int)patchchanges.size()) c = patchchanges[i]; + patchChange c; + c.chgnum = 99999999; + c.x = c.y = c.oldpatch = c.newpatch = -1; + if (i >= 0 && i < (int)patchchanges.size()) + c = patchchanges[i]; return c; } diff --git a/Model.cpp b/Model.cpp index 2a6921f..4ed2003 100644 --- a/Model.cpp +++ b/Model.cpp @@ -498,7 +498,7 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->ageIncrement(); // increment age of all individuals if (sim.outInds && yr >= sim.outStartInd && yr % sim.outIntInd == 0) pComm->outInds(rep, yr, -1, -1); // list any individuals dying having reached maximum age - pComm->survival(1, 0, 1); // delete any such individuals + pComm->survival(1, 0, 1); // delete any such individuals totalInds = pComm->totalInds(); if (totalInds <= 0) { yr++; break; } } diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 8b77aa0..d78109f 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -34,7 +34,7 @@ NeutralStatsManager::NeutralStatsManager(set const& patchList, const int nL } // ---------------------------------------------------------------------------------------- -// Set allele tables in NeutralData structs +// Set allele tables in SNPtable structs // ---------------------------------------------------------------------------------------- @@ -51,7 +51,10 @@ void NeutralStatsManager::updateAlleleTables(Species* pSpecies, Landscape* pLand for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); + if (patch == 0) throw runtime_error("Sampled patch does not exist."); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + if (pPop == 0) throw runtime_error("Sampled patch does not contain a population."); + pPop->updateAlleleTable(); populationSize += pPop->sampleSize(); @@ -61,10 +64,10 @@ void NeutralStatsManager::updateAlleleTables(Species* pSpecies, Landscape* pLand int patchAlleleCount = pPop->getAlleleCount(thisLocus, allele); if (globalAlleleTable.size() <= thisLocus) { //if first allele of new loci (should only happen in first calculation step) - NeutralData n = NeutralData(nAlleles, allele, patchAlleleCount); + SNPtable n = SNPtable(nAlleles, allele, patchAlleleCount); globalAlleleTable.push_back(n); } - else globalAlleleTable[thisLocus].incrementCountBy(patchAlleleCount, allele); + else globalAlleleTable[thisLocus].incrementTallyBy(patchAlleleCount, allele); } } } @@ -73,13 +76,13 @@ void NeutralStatsManager::updateAlleleTables(Species* pSpecies, Landscape* pLand std::for_each(globalAlleleTable.begin(), globalAlleleTable.end(), - [&](NeutralData &v) -> void { + [&](SNPtable &v) -> void { v.setFrequencies(populationSize); }); } // ---------------------------------------------------------------------------------------- -// Reset allele tables in NeutralData structs +// Reset allele tables in SNPtable structs // ---------------------------------------------------------------------------------------- void NeutralStatsManager::resetGlobalAlleleTable() { @@ -317,7 +320,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int s2 += var * pPop->sampleSize(); - h_bar += pPop->getHetero(thisLocus, allele); + h_bar += pPop->getHeteroTally(thisLocus, allele); }//end for pop @@ -430,7 +433,7 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i int popSize = pPop->sampleSize(); if (!popSize) continue; //skip empty patches - het = pPop->getHetero(l, a); + het = pPop->getHeteroTally(l, a); freq = pPop->getAlleleFrequency(l, a); diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index 8760781..74106e4 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -48,54 +48,40 @@ struct PatchMatrix }; -struct NeutralData { +struct SNPtable { private: - //int lociPosition; - //char allele; - vector counts; - vector freqs; - vector heteros; + vector alleleTallies; + vector alleleFrequencies; + vector alleleHeterozygoteTallies; public: //for community allele table, heteros not technically needed so don't reserve - NeutralData(int nAllele, int allele, int alleleCount) : counts(nAllele), freqs(nAllele) { - this->incrementCountBy(alleleCount, allele); + SNPtable(int nAllele, int allele, int alleleCount) : alleleTallies(nAllele), alleleFrequencies(nAllele) { + this->incrementTallyBy(alleleCount, allele); }; //for population allele tables - NeutralData(int nAllele) : counts(nAllele), freqs(nAllele), heteros(nAllele) {}; + SNPtable(int nAllele) : alleleTallies(nAllele), alleleFrequencies(nAllele), alleleHeterozygoteTallies(nAllele) {}; void setFrequencies(int populationSize) { - int i = 0; - for (auto count : counts) { - if (freqs.size() <= i) - freqs.push_back(((count != 0) ? count / static_cast(populationSize) : 0)); - else - freqs[i] = ((count != 0) ? count / static_cast(populationSize) : 0); - ++i; + for (int i = 0; i < alleleFrequencies.size(); i++) { + alleleFrequencies[i] = alleleTallies[i] / static_cast(populationSize); } }; void reset() { - fill(counts.begin(), counts.end(), 0); fill(freqs.begin(), freqs.end(), 0); - fill(heteros.begin(), heteros.end(), 0); + fill(alleleTallies.begin(), alleleTallies.end(), 0); fill(alleleFrequencies.begin(), alleleFrequencies.end(), 0); + fill(alleleHeterozygoteTallies.begin(), alleleHeterozygoteTallies.end(), 0); } - int getCount(int allele) { - return counts[allele]; - }; - double getFrequency(int allele) { return freqs[allele]; }; - - double getHetero(int allele) { return heteros[allele]; }; - - void incrementCount(int allele) { counts[allele]++; }; + int getTally(int whichAllele) { return alleleTallies[whichAllele]; }; + double getFrequency(int whichAllele) { return alleleFrequencies[whichAllele]; }; + int getHeteroTally(int whichAllele) { return alleleHeterozygoteTallies[whichAllele]; }; - void incrementCountBy(int count, int allele) { this->counts[allele] += count; } - - void incrementHeteroBy(int count, int allele) { - this->heteros[allele] += count; - } + void incrementTally(int whichAllele) { alleleTallies[whichAllele]++; }; + void incrementTallyBy(int count, int whichAllele) { this->alleleTallies[whichAllele] += count; } + void incrementHeteroTally(int whichAllele) { this->alleleHeterozygoteTallies[whichAllele]++; } }; @@ -116,7 +102,7 @@ class NeutralStatsManager { /**Pairwise Fst matrix.*/ PatchMatrix _fst_matrix; - vector globalAlleleTable; //don't have to be pointers, not shared or moved + vector globalAlleleTable; //don't have to be pointers, not shared or moved public: diff --git a/Population.cpp b/Population.cpp index ff5deba..a14f644 100644 --- a/Population.cpp +++ b/Population.cpp @@ -321,7 +321,7 @@ int Population::getNInds(void) { return (int)inds.size(); } // reset allele table // ---------------------------------------------------------------------------------------- void Population::resetAlleleTable() { - for (auto& entry : alleleTable) { + for (auto& entry : allSNPtables) { entry.reset(); } } @@ -336,13 +336,13 @@ void Population::updateAlleleTable() { const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; const auto& positions = pSpecies->getSpTrait(SNP)->getPositions(); - if (alleleTable.size() != 0) + if (allSNPtables.size() != 0) resetAlleleTable(); else { - alleleTable.reserve(nLoci); + allSNPtables.reserve(nLoci); for (int l = 0; l < nLoci; l++) { - alleleTable.push_back(NeutralData(nAlleles)); + allSNPtables.push_back(SNPtable(nAlleles)); } } @@ -350,45 +350,45 @@ void Population::updateAlleleTable() { const auto trait = individual->getTrait(SNP); - int lociCounter = 0; + int whichLocus = 0; for (auto position : positions) { - auto a = (int)trait->getSelectionCoefAtLoci(0, position); - auto b = (int)trait->getSelectionCoefAtLoci(1, position); + int alleleOnChromA = (int)trait->getAlleleValueAtLocus(0, position); + int alleleOnChromB = (int)trait->getAlleleValueAtLocus(1, position); - int isHetero = a != b; - alleleTable[lociCounter].incrementHeteroBy(isHetero, a); - alleleTable[lociCounter].incrementHeteroBy(isHetero, b); - - alleleTable[lociCounter].incrementCount(a); - alleleTable[lociCounter].incrementCount(b); + bool isHetero = alleleOnChromA != alleleOnChromB; + if (isHetero) { + allSNPtables[whichLocus].incrementHeteroTally(alleleOnChromA); + allSNPtables[whichLocus].incrementHeteroTally(alleleOnChromB); + } + allSNPtables[whichLocus].incrementTally(alleleOnChromA); + allSNPtables[whichLocus].incrementTally(alleleOnChromB); - lociCounter++; + whichLocus++; } - } if (sampledInds.size() > 0) { - std::for_each(alleleTable.begin(), - alleleTable.end(), - [&](NeutralData& v) -> void { - v.setFrequencies(static_cast(sampledInds.size()) * 2); - //v->divideHeteros(sampledInds.size()); //weir and cockerham doesn't need this division?? + std::for_each( + allSNPtables.begin(), + allSNPtables.end(), + [&](SNPtable& thisLocus) -> void { + thisLocus.setFrequencies(static_cast(sampledInds.size()) * 2); // /!\ assumes dipoidy? + //thisLocus->divideHeteros(sampledInds.size()); //weir and cockerham doesn't need this division?? }); } } double Population::getAlleleFrequency(int locus, int allele) { - return alleleTable[locus].getFrequency(allele); + return allSNPtables[locus].getFrequency(allele); } - int Population::getAlleleCount(int locus, int allele) { - return alleleTable[locus].getCount(allele); + return allSNPtables[locus].getTally(allele); } -double Population::getHetero(int locus, int allele) { - return alleleTable[locus].getHetero(allele); +int Population::getHeteroTally(int locus, int allele) { + return allSNPtables[locus].getHeteroTally(allele); } // ---------------------------------------------------------------------------------------- @@ -1778,13 +1778,6 @@ void Population::outPopulation(int rep, int yr, int gen, float eps, outPop << "\t" << eps << "\t" << envval << "\t" << k; } } -#if RSDEBUG - //DEBUGLOG << "Population::outPopulation(): this=" << this - // << " patchNum=" << pPatch->getPatchNum() - // << " totalPop()=" << totalPop() - // << " nStages=" << nStages << " nSexes=" << nSexes - // << endl; -#endif outPop << "\t" << pSpecies->getSpNum(); if (dem.stageStruct) { p = getStats(); @@ -1808,65 +1801,6 @@ void Population::outPopulation(int rep, int yr, int gen, float eps, } } outPop << endl; - - /* - #if RS_ABC - obsdata obs; - if (abcYear) { - int nobs = (int)pABCmaster->NObs(); - for (int i = 0; i < nobs; i++) { - obs = pABCmaster->getObsData(i); - #if RSDEBUG - //DEBUGLOG << "Population::outPopulation(): this=" << this << " i=" << i << " yr=" << yr - // << " obs.year=" << obs.year << " obs.type=" << obs.type << " obs.name=" << obs.name - // << " obs.x=" << obs.x << " obs.y=" << obs.y - // << endl; - #endif - if (obs.year == yr && obs.type == 2) { - if (obs.name == "NInds" || obs.name == "Occupied") { - bool match = false; - if (patchModel) { - if (obs.x == pPatch->getPatchNum()) { - match = true; - #if RSDEBUG - //DEBUGLOG << "Population::outPopulation(): i=" << i << " PROCESS Population NInds" - // << " obs.id=" << obs.id << " obs.value=" << obs.value << " obs.x=" << obs.x - // << " pPatch->PatchNum()=" << pPatch->getPatchNum() - // << " totalPop()=" << totalPop() << " p.nNonJuvs=" << p.nNonJuvs - // << endl; - #endif - } - } - else { - locn loc = pPatch->getCentroid(); - if (obs.x == loc.x && obs.y == loc.y) { - match = true; - #if RSDEBUG - DEBUGLOG << "Population::outPopulation(): i=" << i << " PROCESS Population NInds" - << " obs.id=" << obs.id << " obs.value=" << obs.value << " obs.x=" - << obs.x << " obs.y=" << obs.y << " loc.x=" << loc.x << " loc.y=" << loc.y - << " totalPop()=" << totalPop() << " p.nNonJuvs=" << p.nNonJuvs - << endl; - #endif - } - } - if (match) { - if (obs.name == "NInds") { - if (dem.stageStruct) - pABCmaster->AddNewPred(sim.simulation,obs.id,rep,obs.value,p.nNonJuvs,obs.weight); - else - pABCmaster->AddNewPred(sim.simulation,obs.id,rep,obs.value,totalPop(),obs.weight); - } - else { // obs.name == "Occupied" - pABCmaster->AddNewPred(sim.simulation,obs.id,rep,obs.value,p.breeding,obs.weight); - } - } - } - } - } - } - #endif // ABC - */ } //--------------------------------------------------------------------------- diff --git a/Population.h b/Population.h index 3fe81d4..6da4f1d 100644 --- a/Population.h +++ b/Population.h @@ -227,7 +227,7 @@ class Population { void updateAlleleTable(); double getAlleleFrequency(int locus, int allele); int getAlleleCount(int locus, int allele); - double getHetero(int locus, int allele); + int getHeteroTally(int locus, int allele); int countHeterozygoteLoci(); vector countLociHeterozyotes(); double computeHs(); @@ -244,7 +244,7 @@ class Population { // has been completed std::set sampledInds; - vector alleleTable; + vector allSNPtables; void resetAlleleTable(); }; diff --git a/QTLTrait.cpp b/QTLTrait.cpp index 1b38fee..383dffd 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -402,7 +402,7 @@ int QTLTrait::countHeterozygoteLoci() const { // get allele value at loci // ---------------------------------------------------------------------------------------- -float QTLTrait::getSelectionCoefAtLoci(short whichChromosome, int position) const { +float QTLTrait::getAlleleValueAtLocus(short whichChromosome, int position) const { auto it = genes.find(position); diff --git a/QTLTrait.h b/QTLTrait.h index f6e7545..00c7234 100644 --- a/QTLTrait.h +++ b/QTLTrait.h @@ -49,9 +49,9 @@ class QTLTrait : public TTrait { void inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) override; map>>& get_mutations() { return genes; } // returning reference, receiver must be const - // virtual float getSelectionCoefAtLoci(short chromosome, int i) const override { return (double)mutations[chromosome][i]->getSelectionCoef(); } + // virtual float getAlleleValueAtLocus(short chromosome, int i) const override { return (double)mutations[chromosome][i]->getSelectionCoef(); } - float getSelectionCoefAtLoci(short chromosome, int i) const override; + float getAlleleValueAtLocus(short chromosome, int i) const override; int countHeterozygoteLoci() const; bool isHeterozygoteAtLocus(int locus) const override; virtual ~QTLTrait() { } diff --git a/SNPTrait.cpp b/SNPTrait.cpp index 102d9cf..f418276 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -287,7 +287,7 @@ int SNPTrait::countHeterozygoteLoci() const { // ---------------------------------------------------------------------------------------- -float SNPTrait::getSelectionCoefAtLoci(short whichChromosome, int position) const { +float SNPTrait::getAlleleValueAtLocus(short whichChromosome, int position) const { auto it = genes.find(position); diff --git a/SNPTrait.h b/SNPTrait.h index c4d87b5..f06b4e5 100644 --- a/SNPTrait.h +++ b/SNPTrait.h @@ -54,7 +54,7 @@ class SNPTrait : public TTrait { map>& get_mutations() { return genes; } //returning reference, reciever must be const - virtual float getSelectionCoefAtLoci(short chromosome, int position) const override; + virtual float getAlleleValueAtLocus(short chromosome, int position) const override; virtual int countHeterozygoteLoci() const; diff --git a/TTrait.h b/TTrait.h index 71395c3..ff6f954 100644 --- a/TTrait.h +++ b/TTrait.h @@ -22,7 +22,7 @@ class TTrait { virtual int getNLoci() const = 0; virtual float getMutationRate() const = 0; virtual bool isInherited() const = 0; - virtual float getSelectionCoefAtLoci(short chromosome, int i) const = 0; + virtual float getAlleleValueAtLocus(short chromosome, int i) const = 0; virtual int countHeterozygoteLoci() const = 0; virtual bool isHeterozygoteAtLocus(int loci) const = 0; virtual float express() = 0; From 7213a183df639c0bad0b887ec9014d474bd78120 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 29 Mar 2024 15:18:21 +0000 Subject: [PATCH 076/332] rename SNPtables --- Community.cpp | 2 +- NeutralStatsManager.cpp | 36 ++++++++++++++++++------------------ NeutralStatsManager.h | 6 +++--- Population.cpp | 32 ++++++++++++++++---------------- Population.h | 6 +++--- 5 files changed, 41 insertions(+), 41 deletions(-) diff --git a/Community.cpp b/Community.cpp index fd35485..09c1d47 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1853,7 +1853,7 @@ void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, if (pNeutralStatistics == 0) pNeutralStatistics = make_unique(patchList, nLoci); - pNeutralStatistics->updateAlleleTables(pSpecies, pLandscape, patchList); + pNeutralStatistics->updateAllSNPTables(pSpecies, pLandscape, patchList); if (fstat) { pNeutralStatistics->calculateHo(patchList, nInds, nLoci, pSpecies, pLandscape); diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index d78109f..3ba9a73 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -30,7 +30,7 @@ NeutralStatsManager::NeutralStatsManager(set const& patchList, const int nLoci) { this->_fst_matrix = PatchMatrix(static_cast(patchList.size()), static_cast(patchList.size())); - globalAlleleTable.reserve(nLoci); //don't have to be pointers, not shared or moved + globalSNPtables.reserve(nLoci); //don't have to be pointers, not shared or moved } // ---------------------------------------------------------------------------------------- @@ -38,14 +38,14 @@ NeutralStatsManager::NeutralStatsManager(set const& patchList, const int nL // ---------------------------------------------------------------------------------------- -void NeutralStatsManager::updateAlleleTables(Species* pSpecies, Landscape* pLandscape, set const& patchList) { +void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLandscape, set const& patchList) { const int nLoci = pSpecies->getNPositionsForTrait(SNP); const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; const int chromosomes = (pSpecies->isDiploid() ? 2 : 1); - if (!globalAlleleTable.empty()) - resetGlobalAlleleTable(); + if (!globalSNPtables.empty()) + resetGlobalSNPtables(); int populationSize = 0; @@ -55,7 +55,7 @@ void NeutralStatsManager::updateAlleleTables(Species* pSpecies, Landscape* pLand const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop == 0) throw runtime_error("Sampled patch does not contain a population."); - pPop->updateAlleleTable(); + pPop->updatePopSNPtables(); populationSize += pPop->sampleSize(); for (int thisLocus = 0; thisLocus < nLoci; thisLocus++) { @@ -63,19 +63,19 @@ void NeutralStatsManager::updateAlleleTables(Species* pSpecies, Landscape* pLand int patchAlleleCount = pPop->getAlleleCount(thisLocus, allele); - if (globalAlleleTable.size() <= thisLocus) { //if first allele of new loci (should only happen in first calculation step) + if (globalSNPtables.size() <= thisLocus) { //if first allele of new loci (should only happen in first calculation step) SNPtable n = SNPtable(nAlleles, allele, patchAlleleCount); - globalAlleleTable.push_back(n); + globalSNPtables.push_back(n); } - else globalAlleleTable[thisLocus].incrementTallyBy(patchAlleleCount, allele); + else globalSNPtables[thisLocus].incrementTallyBy(patchAlleleCount, allele); } } } populationSize *= chromosomes; - std::for_each(globalAlleleTable.begin(), - globalAlleleTable.end(), + std::for_each(globalSNPtables.begin(), + globalSNPtables.end(), [&](SNPtable &v) -> void { v.setFrequencies(populationSize); }); @@ -85,8 +85,8 @@ void NeutralStatsManager::updateAlleleTables(Species* pSpecies, Landscape* pLand // Reset allele tables in SNPtable structs // ---------------------------------------------------------------------------------------- -void NeutralStatsManager::resetGlobalAlleleTable() { - for (auto& entry : globalAlleleTable) { +void NeutralStatsManager::resetGlobalSNPtables() { + for (auto& entry : globalSNPtables) { entry.reset(); } } @@ -163,7 +163,7 @@ void NeutralStatsManager::setLociDiversityCounter(set const& patchList, con //globally: for (i = 0; i < nLoci; ++i) for (j = 0; j < nAlleles; ++j) - totNbFixedAlleles += (globalAlleleTable[i].getFrequency(j) == 1); + totNbFixedAlleles += (globalSNPtables[i].getFrequency(j) == 1); } // ---------------------------------------------------------------------------------------- @@ -225,7 +225,7 @@ void NeutralStatsManager::calculateHt(Species* pSpecies, Landscape* pLandscape, for (int allele = 0; allele < nAlleles; ++allele) { - freq = globalAlleleTable[thisLocus].getFrequency(allele); + freq = globalSNPtables[thisLocus].getFrequency(allele); freq *= freq; //squared frequencies @@ -314,7 +314,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - var = pPop->getAlleleFrequency(thisLocus, allele) - globalAlleleTable[thisLocus].getFrequency(allele); //(p_liu - pbar_u)^2 + var = pPop->getAlleleFrequency(thisLocus, allele) - globalSNPtables[thisLocus].getFrequency(allele); //(p_liu - pbar_u)^2 var *= var; @@ -325,7 +325,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int }//end for pop s2 *= s2_denom; - p_bar = globalAlleleTable[thisLocus].getFrequency(allele); + p_bar = globalSNPtables[thisLocus].getFrequency(allele); h_bar *= inverse_n_total; x = p_bar * (1 - p_bar) - r * s2; @@ -437,7 +437,7 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i freq = pPop->getAlleleFrequency(l, a); - var = freq - globalAlleleTable[l].getFrequency(a); //(p_liu - pbar_u)^2 + var = freq - globalSNPtables[l].getFrequency(a); //(p_liu - pbar_u)^2 var *= var; @@ -602,7 +602,7 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd pq = p * (1 - p); - var = p - globalAlleleTable[l].getFrequency(u); //(p_liu - pbar_u)^2 + var = p - globalSNPtables[l].getFrequency(u); //(p_liu - pbar_u)^2 var *= var; diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index 74106e4..4cd14fb 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -102,15 +102,15 @@ class NeutralStatsManager { /**Pairwise Fst matrix.*/ PatchMatrix _fst_matrix; - vector globalAlleleTable; //don't have to be pointers, not shared or moved + vector globalSNPtables; //don't have to be pointers, not shared or moved public: NeutralStatsManager(set const& patchList, const int nLoci); - void updateAlleleTables(Species* pSpecies, Landscape* pLandscape, set const& patchList); + void updateAllSNPTables(Species* pSpecies, Landscape* pLandscape, set const& patchList); - void resetGlobalAlleleTable(); + void resetGlobalSNPtables(); void setLociDiversityCounter(set const& patchList, const int nInds, Species* pSpecies, Landscape* pLandscape); diff --git a/Population.cpp b/Population.cpp index a14f644..5099107 100644 --- a/Population.cpp +++ b/Population.cpp @@ -320,8 +320,8 @@ int Population::getNInds(void) { return (int)inds.size(); } // ---------------------------------------------------------------------------------------- // reset allele table // ---------------------------------------------------------------------------------------- -void Population::resetAlleleTable() { - for (auto& entry : allSNPtables) { +void Population::resetPopSNPtables() { + for (auto& entry : popSNPtables) { entry.reset(); } } @@ -330,19 +330,19 @@ void Population::resetAlleleTable() { // allele frequency in population of sampled individuals // ---------------------------------------------------------------------------------------- -void Population::updateAlleleTable() { +void Population::updatePopSNPtables() { const int nLoci = pSpecies->getNPositionsForTrait(SNP); const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; const auto& positions = pSpecies->getSpTrait(SNP)->getPositions(); - if (allSNPtables.size() != 0) - resetAlleleTable(); + if (popSNPtables.size() != 0) + resetPopSNPtables(); else { - allSNPtables.reserve(nLoci); + popSNPtables.reserve(nLoci); for (int l = 0; l < nLoci; l++) { - allSNPtables.push_back(SNPtable(nAlleles)); + popSNPtables.push_back(SNPtable(nAlleles)); } } @@ -358,11 +358,11 @@ void Population::updateAlleleTable() { bool isHetero = alleleOnChromA != alleleOnChromB; if (isHetero) { - allSNPtables[whichLocus].incrementHeteroTally(alleleOnChromA); - allSNPtables[whichLocus].incrementHeteroTally(alleleOnChromB); + popSNPtables[whichLocus].incrementHeteroTally(alleleOnChromA); + popSNPtables[whichLocus].incrementHeteroTally(alleleOnChromB); } - allSNPtables[whichLocus].incrementTally(alleleOnChromA); - allSNPtables[whichLocus].incrementTally(alleleOnChromB); + popSNPtables[whichLocus].incrementTally(alleleOnChromA); + popSNPtables[whichLocus].incrementTally(alleleOnChromB); whichLocus++; } @@ -370,8 +370,8 @@ void Population::updateAlleleTable() { if (sampledInds.size() > 0) { std::for_each( - allSNPtables.begin(), - allSNPtables.end(), + popSNPtables.begin(), + popSNPtables.end(), [&](SNPtable& thisLocus) -> void { thisLocus.setFrequencies(static_cast(sampledInds.size()) * 2); // /!\ assumes dipoidy? //thisLocus->divideHeteros(sampledInds.size()); //weir and cockerham doesn't need this division?? @@ -380,15 +380,15 @@ void Population::updateAlleleTable() { } double Population::getAlleleFrequency(int locus, int allele) { - return allSNPtables[locus].getFrequency(allele); + return popSNPtables[locus].getFrequency(allele); } int Population::getAlleleCount(int locus, int allele) { - return allSNPtables[locus].getTally(allele); + return popSNPtables[locus].getTally(allele); } int Population::getHeteroTally(int locus, int allele) { - return allSNPtables[locus].getHeteroTally(allele); + return popSNPtables[locus].getHeteroTally(allele); } // ---------------------------------------------------------------------------------------- diff --git a/Population.h b/Population.h index 6da4f1d..be81a29 100644 --- a/Population.h +++ b/Population.h @@ -224,7 +224,7 @@ class Population { void clean(void); // Remove zero pointers to dead or dispersed individuals - void updateAlleleTable(); + void updatePopSNPtables(); double getAlleleFrequency(int locus, int allele); int getAlleleCount(int locus, int allele); int getHeteroTally(int locus, int allele); @@ -244,8 +244,8 @@ class Population { // has been completed std::set sampledInds; - vector allSNPtables; - void resetAlleleTable(); + vector popSNPtables; + void resetPopSNPtables(); }; //--------------------------------------------------------------------------- From e3b2adc9e5c014771d8b2817c6894bba6712d149 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 29 Mar 2024 17:17:54 +0000 Subject: [PATCH 077/332] improve readability of some SNPcalculations --- Community.cpp | 9 ++- NeutralStatsManager.cpp | 118 ++++++++++++++++++++++------------------ NeutralStatsManager.h | 6 +- Population.cpp | 18 +++--- Population.h | 2 +- SNPTrait.cpp | 1 - 6 files changed, 84 insertions(+), 70 deletions(-) diff --git a/Community.cpp b/Community.cpp index 09c1d47..0f35156 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1846,12 +1846,17 @@ void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); + if (patch == 0) { + throw runtime_error("Sampled patch does not exist"); + } const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - nInds += pPop->sampleSize(); + if (pPop != 0) { // empty patches do not contribute + nInds += pPop->sampleSize(); + } } if (pNeutralStatistics == 0) - pNeutralStatistics = make_unique(patchList, nLoci); + pNeutralStatistics = make_unique(patchList.size(), nLoci); pNeutralStatistics->updateAllSNPTables(pSpecies, pLandscape, patchList); diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 3ba9a73..25b7a3d 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -28,8 +28,8 @@ // Cstor // ---------------------------------------------------------------------------------------- -NeutralStatsManager::NeutralStatsManager(set const& patchList, const int nLoci) { - this->_fst_matrix = PatchMatrix(static_cast(patchList.size()), static_cast(patchList.size())); +NeutralStatsManager::NeutralStatsManager(const int& nbSampledPatches, const int nLoci) { + this->_fst_matrix = PatchMatrix(nbSampledPatches, nbSampledPatches); globalSNPtables.reserve(nLoci); //don't have to be pointers, not shared or moved } @@ -42,7 +42,7 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand const int nLoci = pSpecies->getNPositionsForTrait(SNP); const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; - const int chromosomes = (pSpecies->isDiploid() ? 2 : 1); + const int ploidy = (pSpecies->isDiploid() ? 2 : 1); if (!globalSNPtables.empty()) resetGlobalSNPtables(); @@ -51,29 +51,31 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); - if (patch == 0) throw runtime_error("Sampled patch does not exist."); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - if (pPop == 0) throw runtime_error("Sampled patch does not contain a population."); + if (pPop != 0) { - pPop->updatePopSNPtables(); - populationSize += pPop->sampleSize(); + // Update this population's SNP counts tables + pPop->updatePopSNPtables(); + populationSize += pPop->sampleSize(); - for (int thisLocus = 0; thisLocus < nLoci; thisLocus++) { - for (int allele = 0; allele < nAlleles; allele++) { + // Update global SNP counts tables + for (int thisLocus = 0; thisLocus < nLoci; thisLocus++) { + for (int allele = 0; allele < nAlleles; allele++) { - int patchAlleleCount = pPop->getAlleleCount(thisLocus, allele); + int patchAlleleCount = pPop->getAlleleTally(thisLocus, allele); - if (globalSNPtables.size() <= thisLocus) { //if first allele of new loci (should only happen in first calculation step) - SNPtable n = SNPtable(nAlleles, allele, patchAlleleCount); - globalSNPtables.push_back(n); + if (globalSNPtables.size() <= thisLocus) { //if first allele of new loci (should only happen in first calculation step) + SNPtable newSNPtbl = SNPtable(nAlleles, allele, patchAlleleCount); + globalSNPtables.push_back(newSNPtbl); + } + else globalSNPtables[thisLocus].incrementTallyBy(patchAlleleCount, allele); } - else globalSNPtables[thisLocus].incrementTallyBy(patchAlleleCount, allele); } } } - populationSize *= chromosomes; - + // Update global frequency + populationSize *= ploidy; std::for_each(globalSNPtables.begin(), globalSNPtables.end(), [&](SNPtable &v) -> void { @@ -101,69 +103,75 @@ void NeutralStatsManager::setLociDiversityCounter(set const& patchList, con int i, j; const int nLoci = pSpecies->getNPositionsForTrait(SNP); const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; - const int chromosomes = (pSpecies->isDiploid() ? 2 : 1); - unsigned int nbpatch = 0; - double patch_mean, pop_mean = 0; + const int ploidy = (pSpecies->isDiploid() ? 2 : 1); + unsigned int nbPopulatedPatches = 0; + int nbAllelesInPatch = 0; + double meanAllelicDivInPatch = 0; + bool alleleExistsInPop = 0; - bool** pop_div; + bool** alleleExistsInCommTable; // number of alleles per locus, Patch and pop counters: - pop_div = new bool* [nLoci]; + alleleExistsInCommTable = new bool* [nLoci]; for (i = 0; i < nLoci; ++i) { - pop_div[i] = new bool[nAlleles]; + alleleExistsInCommTable[i] = new bool[nAlleles]; for (j = 0; j < nAlleles; ++j) - pop_div[i][j] = 0; + alleleExistsInCommTable[i][j] = 0; } for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + // if (pPop != 0) { } - nbpatch += (pPop->sampleSize() != 0); + nbPopulatedPatches += (pPop->sampleSize() != 0); // nbPopulatedPatches++ ? if (pPop->sampleSize() > 0) { - patch_mean = 0; + nbAllelesInPatch = 0; for (i = 0; i < nLoci; ++i) for (j = 0; j < nAlleles; ++j) { - patch_mean += (pPop->getAlleleCount(i, j) != 0); - pop_div[i][j] |= (pPop->getAlleleCount(i, j) != 0); // OR + alleleExistsInPop = pPop->getAlleleTally(i, j) != 0; + nbAllelesInPatch += alleleExistsInPop; + alleleExistsInCommTable[i][j] |= alleleExistsInPop; // OR operator } // add mean nb of alleles per locus for Patch k to the pop mean - pop_mean += patch_mean / nLoci; + meanAllelicDivInPatch += static_cast(nbAllelesInPatch) / nLoci; } } + meanNbAllelesPerLocusPerPatch = nbPopulatedPatches == 0 ? meanAllelicDivInPatch / nbPopulatedPatches : 0; - meanNbAllelesPerLocusPerPatch = (nbpatch ? pop_mean / nbpatch : nanf("NULL")); + // Compute mean allelic diversity per locus meanNbAllelesPerLocus = 0; - for (i = 0; i < nLoci; ++i) for (j = 0; j < nAlleles; ++j) - meanNbAllelesPerLocus += pop_div[i][j]; - + meanNbAllelesPerLocus += alleleExistsInCommTable[i][j]; meanNbAllelesPerLocus /= nLoci; - + // Clear table for (i = 0; i < nLoci; ++i) - delete[] pop_div[i]; - delete[] pop_div; + delete[] alleleExistsInCommTable[i]; + delete[] alleleExistsInCommTable; - //number of fixed loci, local and global counters: + // Compute number of fixed loci per patch + // mean number of loci that are fixed at pop level per pop meanNbFixedAllelesPerPatch = 0; - - for (int patchId : patchList) { - const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - for (i = 0; i < nLoci; ++i) - for (j = 0; j < nAlleles; ++j) - meanNbFixedAllelesPerPatch += (pPop->getAlleleFrequency(i, j) == 1); + if (nbPopulatedPatches > 0) { + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + if (pPop != 0) { + for (i = 0; i < nLoci; ++i) + for (j = 0; j < nAlleles; ++j) + meanNbFixedAllelesPerPatch += pPop->getAlleleFrequency(i, j) == 1; + } + } + meanNbFixedAllelesPerPatch /= nbPopulatedPatches; } - - meanNbFixedAllelesPerPatch /= nbpatch; - totNbFixedAlleles = 0; - - //globally: + + // Compute number of fixed loci + nbGloballyFixedAlleles = 0; for (i = 0; i < nLoci; ++i) for (j = 0; j < nAlleles; ++j) - totNbFixedAlleles += (globalSNPtables[i].getFrequency(j) == 1); + nbGloballyFixedAlleles += globalSNPtables[i].getFrequency(j) == 1; } // ---------------------------------------------------------------------------------------- @@ -171,16 +179,18 @@ void NeutralStatsManager::setLociDiversityCounter(set const& patchList, con // ---------------------------------------------------------------------------------------- void NeutralStatsManager::calculateHo(set const& patchList, const int nbInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape) { - double hetero = 0; - double nLoci = nbInds * nbrLoci; + int nbHetero = 0; + int nLoci = nbInds * nbrLoci; if (nLoci != 0) { for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - hetero += pPop->countHeterozygoteLoci(); + if (pPop != 0) { + nbHetero += pPop->countHeterozygoteLoci(); + } } - _ho = hetero / nLoci; + _ho = static_cast(nbHetero) / static_cast(nLoci); } else _ho = 0.0; } @@ -394,7 +404,7 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - cnt += pPop->getAlleleCount(l, a); + cnt += pPop->getAlleleTally(l, a); } alploc_table[l][a] = (cnt != 0); diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index 4cd14fb..e269ae3 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -92,7 +92,7 @@ class NeutralStatsManager { int _n_extantPopulations, _n_individuals; /**F-statistics*/ double _ho, _hs, _ht, _hsnei, _htnei, meanNbAllelesPerLocusPerPatch, meanNbAllelesPerLocus, - _fst, _fis, _fit, meanNbFixedAllelesPerPatch, totNbFixedAlleles; + _fst, _fis, _fit, meanNbFixedAllelesPerPatch, nbGloballyFixedAlleles; /**Weir & Hill (2002) F-stat estimates.*/ double _fst_WH; /**Weir & Cockerham (1984) F-stat estimates.*/ @@ -106,7 +106,7 @@ class NeutralStatsManager { public: - NeutralStatsManager(set const& patchList, const int nLoci); + NeutralStatsManager(const int& nbSampledPatches, const int nLoci); void updateAllSNPTables(Species* pSpecies, Landscape* pLandscape, set const& patchList); @@ -141,7 +141,7 @@ class NeutralStatsManager { double getMeanNbAllPerLocusPerPatch() const { return meanNbAllelesPerLocusPerPatch; } double getMeanNbAllPerLocus() const { return meanNbAllelesPerLocus; } double getMeanFixdAllelesPerPatch() const { return meanNbFixedAllelesPerPatch; } - double getTotalFixdAlleles() const { return totNbFixedAlleles; } + double getTotalFixdAlleles() const { return nbGloballyFixedAlleles; } double getPairwiseFst(int i, int j) { return _fst_matrix.get(i, j); } double get_fst_WC_loc(int i) const { return _fst_WC_loc[i]; } double get_fis_WC_loc(int i) const { return _fis_WC_loc[i]; } diff --git a/Population.cpp b/Population.cpp index 5099107..f84cdca 100644 --- a/Population.cpp +++ b/Population.cpp @@ -379,16 +379,16 @@ void Population::updatePopSNPtables() { } } -double Population::getAlleleFrequency(int locus, int allele) { - return popSNPtables[locus].getFrequency(allele); +double Population::getAlleleFrequency(int thisLocus, int whichAllele) { + return popSNPtables[thisLocus].getFrequency(whichAllele); } -int Population::getAlleleCount(int locus, int allele) { - return popSNPtables[locus].getTally(allele); +int Population::getAlleleTally(int thisLocus, int whichAllele) { + return popSNPtables[thisLocus].getTally(whichAllele); } -int Population::getHeteroTally(int locus, int allele) { - return popSNPtables[locus].getHeteroTally(allele); +int Population::getHeteroTally(int thisLocus, int whichAllele) { + return popSNPtables[thisLocus].getHeteroTally(whichAllele); } // ---------------------------------------------------------------------------------------- @@ -396,12 +396,12 @@ int Population::getHeteroTally(int locus, int allele) { // ---------------------------------------------------------------------------------------- int Population::countHeterozygoteLoci() { - int hetero = 0; + int nbHetero = 0; for (Individual* ind : sampledInds) { const auto trait = ind->getTrait(SNP); - hetero += trait->countHeterozygoteLoci(); + nbHetero += trait->countHeterozygoteLoci(); } - return hetero; + return nbHetero; } // ---------------------------------------------------------------------------------------- diff --git a/Population.h b/Population.h index be81a29..1d7b9de 100644 --- a/Population.h +++ b/Population.h @@ -226,7 +226,7 @@ class Population { void updatePopSNPtables(); double getAlleleFrequency(int locus, int allele); - int getAlleleCount(int locus, int allele); + int getAlleleTally(int locus, int allele); int getHeteroTally(int locus, int allele); int countHeterozygoteLoci(); vector countLociHeterozyotes(); diff --git a/SNPTrait.cpp b/SNPTrait.cpp index f418276..258950a 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -275,7 +275,6 @@ bool SNPTrait::isHeterozygoteAtLocus(int locus) const { int SNPTrait::countHeterozygoteLoci() const { int count = 0; - for (auto const& [locus, allelePair] : genes) { count += (allelePair[0] != allelePair[1]); } From c219f78c21070ec95328ac0bc1c049bb121aeaea Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 1 Apr 2024 21:28:35 +0100 Subject: [PATCH 078/332] progress debugging neutral stats - standing bug if all patches empty --- Community.cpp | 32 ++- Model.cpp | 1 - NeutralStatsManager.cpp | 486 +++++++++++++++++++--------------------- NeutralStatsManager.h | 79 +++---- Population.cpp | 27 ++- 5 files changed, 309 insertions(+), 316 deletions(-) diff --git a/Community.cpp b/Community.cpp index 0f35156..16455f4 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1634,7 +1634,7 @@ void Community::sampleIndividuals(Species* pSpecies) { for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - if (pPop != nullptr) { + if (pPop != 0) { pPop->sampleIndsWithoutReplacement(n, stages); } } @@ -1754,8 +1754,8 @@ bool Community::openPairwiseFSTFile(Species* pSpecies, Landscape* pLandscape, co void Community::writeWCFstatFile(int rep, int yr, int gen) { outwcfstat << rep << "\t" << yr << "\t" << gen << "\t"; - outwcfstat << pNeutralStatistics->getNExtantPatchs() - << "\t" << pNeutralStatistics->getNIndividuals() << "\t"; + outwcfstat << pNeutralStatistics->getNbPopulatedSampledPatches() + << "\t" << pNeutralStatistics->getTotalNbSampledInds() << "\t"; outwcfstat << pNeutralStatistics->getFstWC() << "\t" << pNeutralStatistics->getFisWC() << "\t" << pNeutralStatistics->getFitWC() << "\t"; @@ -1779,7 +1779,9 @@ void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const int thisLocus = 0; for (int position : positions) { - outperlocusfstat << yr << "\t" << gen << "\t" << position << "\t"; + outperlocusfstat << yr << "\t" + << gen << "\t" + << position << "\t"; outperlocusfstat << pNeutralStatistics->get_fst_WC_loc(thisLocus) << "\t" << pNeutralStatistics->get_fis_WC_loc(thisLocus) << "\t" << pNeutralStatistics->get_fit_WC_loc(thisLocus) << "\t" @@ -1788,12 +1790,24 @@ void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - int popSize = pPop->sampleSize(); + int popSize = 0; int het = 0; - for (int a = 0; a < nAlleles; ++a) { - het += static_cast(pPop->getHeteroTally(thisLocus, a)); // not sure why this returns a double + if (pPop != 0) { + popSize = pPop->sampleSize(); + if (popSize == 0) { + outperlocusfstat << "\t" << "NA"; + } + else { + for (int a = 0; a < nAlleles; ++a) { + het += static_cast(pPop->getHeteroTally(thisLocus, a)); + } + outperlocusfstat << "\t" + << het / (2.0 * popSize); + } + } + else { + outperlocusfstat << "\t" << "NA"; } - outperlocusfstat << "\t" << het / (2.0 * popSize); } ++thisLocus; outperlocusfstat << endl; @@ -1806,7 +1820,7 @@ void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const // ---------------------------------------------------------------------------------------- void Community::writePairwiseFSTFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList) { - //within patch fst (diagonal of matrix) + // within patch fst (diagonal of matrix) int i = 0; for (int patchId : patchList) { outpairwisefst << yr << "\t" << gen << "\t"; diff --git a/Model.cpp b/Model.cpp index 4ed2003..5d9772d 100644 --- a/Model.cpp +++ b/Model.cpp @@ -457,7 +457,6 @@ int RunModel(Landscape* pLandscape, int seqsim) } if (sstruct.survival == 2) { // annually pComm->survival(0, 1, 0); // development only of all stages - // pComm->survival(0,1,0); // development only of all stages } } else { // non-structured population diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 25b7a3d..6f0af3e 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -29,7 +29,7 @@ // ---------------------------------------------------------------------------------------- NeutralStatsManager::NeutralStatsManager(const int& nbSampledPatches, const int nLoci) { - this->_fst_matrix = PatchMatrix(nbSampledPatches, nbSampledPatches); + this->pairwiseFstMatrix = PatchMatrix(nbSampledPatches, nbSampledPatches); globalSNPtables.reserve(nLoci); //don't have to be pointers, not shared or moved } @@ -64,7 +64,7 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand int patchAlleleCount = pPop->getAlleleTally(thisLocus, allele); - if (globalSNPtables.size() <= thisLocus) { //if first allele of new loci (should only happen in first calculation step) + if (globalSNPtables.size() <= thisLocus) { // if first allele of new loci (should only happen in first calculation step) SNPtable newSNPtbl = SNPtable(nAlleles, allele, patchAlleleCount); globalSNPtables.push_back(newSNPtbl); } @@ -123,19 +123,19 @@ void NeutralStatsManager::setLociDiversityCounter(set const& patchList, con for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - // if (pPop != 0) { } - - nbPopulatedPatches += (pPop->sampleSize() != 0); // nbPopulatedPatches++ ? - if (pPop->sampleSize() > 0) { - nbAllelesInPatch = 0; - for (i = 0; i < nLoci; ++i) - for (j = 0; j < nAlleles; ++j) { - alleleExistsInPop = pPop->getAlleleTally(i, j) != 0; - nbAllelesInPatch += alleleExistsInPop; - alleleExistsInCommTable[i][j] |= alleleExistsInPop; // OR operator - } - // add mean nb of alleles per locus for Patch k to the pop mean - meanAllelicDivInPatch += static_cast(nbAllelesInPatch) / nLoci; + if (pPop != 0) { + if (pPop->sampleSize() > 0) { + nbPopulatedPatches++; + nbAllelesInPatch = 0; + for (i = 0; i < nLoci; ++i) + for (j = 0; j < nAlleles; ++j) { + alleleExistsInPop = pPop->getAlleleTally(i, j) != 0; + nbAllelesInPatch += alleleExistsInPop; + alleleExistsInCommTable[i][j] |= alleleExistsInPop; // OR operator + } + // add mean nb of alleles per locus for Patch k to the pop mean + meanAllelicDivInPatch += static_cast(nbAllelesInPatch) / nLoci; + } } } meanNbAllelesPerLocusPerPatch = nbPopulatedPatches == 0 ? meanAllelicDivInPatch / nbPopulatedPatches : 0; @@ -260,11 +260,12 @@ void NeutralStatsManager::calculateHo2(set const& patchList, const int nbIn for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - if (pPop->sampleSize() > 0) { - const vector heteroPatch = pPop->countLociHeterozyotes(); - - transform(hetero.begin(), hetero.end(), heteroPatch.begin(), - hetero.begin(), plus()); + if (pPop != 0) { + if (pPop->sampleSize() > 0) { + const vector heteroPatch = pPop->countLociHeterozyotes(); + transform(hetero.begin(), hetero.end(), heteroPatch.begin(), + hetero.begin(), plus()); + } } } @@ -272,7 +273,7 @@ void NeutralStatsManager::calculateHo2(set const& patchList, const int nbIn for (double h : hetero) { h /= nbInds; } - ho_loc = hetero; + perLocusHo = hetero; } @@ -281,77 +282,75 @@ void NeutralStatsManager::calculateHo2(set const& patchList, const int nbIn // ---------------------------------------------------------------------------------------- -void NeutralStatsManager::calculateFstatWC(set const& patchList, const int nInds, const int nLoci, const int nAlleles, Species* pSpecies, Landscape* pLandscape) { +void NeutralStatsManager::calculateFstatWC(set const& patchList, const int nbSampledIndsInComm, const int nLoci, const int nAlleles, Species* pSpecies, Landscape* pLandscape) { - double inverse_n_total; + double inverseNtotal; double sum_weights = 0; - double n_bar, n_c, inverse_n_bar; - unsigned int extantPs = 0; + double nBar, nC, inverseNbar; + unsigned int nbPopulatedPatches = 0; for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - int patchSize = pPop->sampleSize(); - if (patchSize) { - extantPs++; - sum_weights += (patchSize * patchSize / static_cast(nInds)); + if (pPop != 0) { + int nbSampledIndsinPop = pPop->sampleSize(); + if (nbSampledIndsinPop > 0) { + nbPopulatedPatches++; + sum_weights += nbSampledIndsinPop * nbSampledIndsinPop / static_cast(nbSampledIndsInComm); + } } } - _n_extantPopulations = extantPs; - _n_individuals = nInds; + nbExtantPops = nbPopulatedPatches; + totalNbSampledInds = nbSampledIndsInComm; // r * nBar - n_bar = nInds / static_cast(extantPs); - n_c = (nInds - sum_weights) / (extantPs - 1); - inverse_n_bar = 1.0 / (n_bar - 1); - inverse_n_total = 1.0 / nInds; + nBar = nbSampledIndsInComm / static_cast(nbPopulatedPatches); // average sample size + nC = (nbSampledIndsInComm - sum_weights) / (nbPopulatedPatches - 1); + inverseNbar = 1.0 / (nBar - 1); + inverseNtotal = 1.0 / nbSampledIndsInComm; double var; - double s2, p_bar, h_bar; - double s2_denom = 1.0 / ((extantPs - 1) * n_bar), - r = (double)(extantPs - 1) / extantPs, - h_bar_factor = (2 * n_bar - 1) / (4 * n_bar); - - double a = 0, b = 0, c = 0, x; + double s2, pBar, hBar; + double s2Denom = 1.0 / ((nbPopulatedPatches - 1) * nBar); + double rTerm = static_cast(nbPopulatedPatches - 1) / nbPopulatedPatches; + double hBarFactor = (2 * nBar - 1) / (4 * nBar); + double a = 0, b = 0, c = 0, intermediateTerm; for (int thisLocus = 0; thisLocus < nLoci; ++thisLocus) { for (int allele = 0; allele < nAlleles; ++allele) { - s2 = p_bar = h_bar = 0; + s2 = hBar = 0; + pBar = globalSNPtables[thisLocus].getFrequency(allele); for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + if (pPop != 0) { + var = pPop->getAlleleFrequency(thisLocus, allele) - pBar; + var *= var; + s2 += var * pPop->sampleSize(); + hBar += pPop->getHeteroTally(thisLocus, allele); + } + } //end for pop - var = pPop->getAlleleFrequency(thisLocus, allele) - globalSNPtables[thisLocus].getFrequency(allele); //(p_liu - pbar_u)^2 - - var *= var; - - s2 += var * pPop->sampleSize(); - - h_bar += pPop->getHeteroTally(thisLocus, allele); - - }//end for pop - - s2 *= s2_denom; - p_bar = globalSNPtables[thisLocus].getFrequency(allele); - h_bar *= inverse_n_total; + s2 *= s2Denom; + hBar *= inverseNtotal; - x = p_bar * (1 - p_bar) - r * s2; - a += s2 - inverse_n_bar * (x - 0.25 * h_bar); - b += x - h_bar_factor * h_bar; - c += h_bar; + intermediateTerm = pBar * (1 - pBar) - rTerm * s2; + a += s2 - inverseNbar * (intermediateTerm - 0.25 * hBar); + b += intermediateTerm - hBarFactor * hBar; + c += hBar; } // end for allele } // end for locus - a *= n_bar / n_c; - b *= n_bar / (n_bar - 1); + a *= nBar / nC; + b *= nBar / (nBar - 1); c *= 0.5; - _fst_WC = a / (a + b + c); - _fit_WC = (a + b) / (a + b + c); - _fis_WC = b / (b + c); + FstWeirCockerham = a / (a + b + c); // theta hat in eq. 1 in WC 1984 + FitWeirCockerham = (a + b) / (a + b + c); // F hat + FisWeirCockerham = b / (b + c); // f hat } @@ -359,191 +358,159 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int // Fstat Weir & Cockerham using Mean square approach. Similar to implementation in Hierfstat // ---------------------------------------------------------------------------------------- -void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const int nInds, const int nLoci, const int nAlleles, Species* pSpecies, Landscape* pLandscape) { +void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const int nInds, const int nLoci, const int maxNbAllelesPerLocus, Species* pSpecies, Landscape* pLandscape) { - double sum_weights = 0; + double sumWeights = 0; double nc; - unsigned int extantPs = 0; + unsigned int nbExtantPops = 0; for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - int patchSize = pPop->sampleSize(); - if (patchSize) { - extantPs++; - sum_weights += (patchSize * patchSize / static_cast(nInds)); + if (pPop != 0) { + int patchSize = pPop->sampleSize(); + if (patchSize > 0) { + nbExtantPops++; + sumWeights += (patchSize * patchSize / static_cast(nInds)); + } } - } - nc = (nInds - sum_weights) / (extantPs - 1); - - unsigned int npl = extantPs; //all loci typed in all patches - - //p = _alleleFreqTable - //pb = _globalAlleleFreq - - vector alploc(nLoci); - - unsigned int** alploc_table = new unsigned int* [nLoci]; + nc = (nInds - sumWeights) / (nbExtantPops - 1); + vector nbAllelesEachLocus(nLoci); + bool** alleleExistsTable = new bool* [nLoci]; for (int i = 0; i < nLoci; ++i) - alploc_table[i] = new unsigned int[nAlleles]; - - int tot_num_allele = 0; - - for (int l = 0; l < nLoci; ++l) { - - alploc[l] = 0; - - for (int cnt, a = 0; a < nAlleles; ++a) { - - cnt = 0; + alleleExistsTable[i] = new bool[maxNbAllelesPerLocus]; + int nbAllelesInComm = 0; + for (int locus = 0; locus < nLoci; ++locus) { + nbAllelesEachLocus[locus] = 0; + for (int allele = 0; allele < maxNbAllelesPerLocus; ++allele) { + int count = 0; for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - - cnt += pPop->getAlleleTally(l, a); - + if (pPop != 0) count += pPop->getAlleleTally(locus, allele); } - alploc_table[l][a] = (cnt != 0); - alploc[l] += (cnt != 0); + alleleExistsTable[locus][allele] = count != 0; + nbAllelesEachLocus[locus] += count != 0; } - - tot_num_allele += alploc[l]; + nbAllelesInComm += nbAllelesEachLocus[locus]; } - //n, and nal are given by pop_sizes, same num ind typed at all loci in each patch -//nc is the same for each locus -//nt is given by tot_size, same tot num of ind typed for all loci - -//SSG: het/2 for each allele - vector SSG(tot_num_allele); - vector SSP(tot_num_allele); - vector SSi(tot_num_allele); - - int all_cntr = 0; + // n, and nal are given by pop_sizes, same num ind typed at all loci in each patch + // nc is the same for each locus + // nt is given by tot_size, same tot num of ind typed for all loci - double het, freq, var; + //SSG: het/2 for each allele + vector SSG(nbAllelesInComm); + vector SSP(nbAllelesInComm); + vector SSi(nbAllelesInComm); - for (int l = 0; l < nLoci; ++l) { + int totalAlleleCounter = 0; + double het, pi, var, pBar; + int popSize; - for (int a = 0; a < nAlleles && all_cntr < tot_num_allele; ++a) { + for (int locus = 0; locus < nLoci; ++locus) { + for (int allele = 0; allele < maxNbAllelesPerLocus && totalAlleleCounter < nbAllelesInComm; ++allele) { - if (alploc_table[l][a] == 0) continue; //do not consider alleles not present in the pop - - SSG[all_cntr] = 0; - SSi[all_cntr] = 0; - SSP[all_cntr] = 0; + if (alleleExistsTable[locus][allele] == false) continue; //do not consider alleles not present in the pop + SSG[totalAlleleCounter] = 0; + SSi[totalAlleleCounter] = 0; + SSP[totalAlleleCounter] = 0; for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - int popSize = pPop->sampleSize(); - if (!popSize) continue; //skip empty patches - - het = pPop->getHeteroTally(l, a); - - freq = pPop->getAlleleFrequency(l, a); - - var = freq - globalSNPtables[l].getFrequency(a); //(p_liu - pbar_u)^2 - + if (pPop == 0) popSize = 0; + else popSize = pPop->sampleSize(); + if (popSize == 0) continue; // skip empty patches + + het = pPop->getHeteroTally(locus, allele); // ni * h_i + pi = pPop->getAlleleFrequency(locus, allele); + pBar = globalSNPtables[locus].getFrequency(allele); + var = pi - pBar; //(p_liu - pbar_u)^2 var *= var; - SSG[all_cntr] += het; - - SSi[all_cntr] += 2 * popSize * freq * (1 - freq) - het / 2; - - SSP[all_cntr] += 2 * popSize * var; + SSG[totalAlleleCounter] += het; // numerator MSG + SSi[totalAlleleCounter] += 2 * popSize * pi * (1 - pi) - het / 2; // numerator + SSP[totalAlleleCounter] += 2 * popSize * var; // numerator MSP } - all_cntr++; + totalAlleleCounter++; } } - if (all_cntr != tot_num_allele) - cout << endl << ("Error:: allele counter and total number of alleles differ in WC mean squared Fstat calculation \n"); + if (totalAlleleCounter != nbAllelesInComm) + throw runtime_error("Error:: allele counter and total number of alleles differ in WC mean squared Fstat calculation \n"); //these shouldn't have to be dynamically allocated manually, if using a vector from stl then would do allocation for you - - vector MSG(tot_num_allele); - vector MSP(tot_num_allele); - vector MSI(tot_num_allele); - vector sigw(tot_num_allele); - vector siga(tot_num_allele); - vector sigb(tot_num_allele); - - // double *FST_pal = new double[tot_num_allele]; - // double *FIS_pal = new double[tot_num_allele]; + vector MSG(nbAllelesInComm); + vector MSP(nbAllelesInComm); + vector MSI(nbAllelesInComm); + vector sigw(nbAllelesInComm); + vector siga(nbAllelesInComm); + vector sigb(nbAllelesInComm); double SIGA = 0, SIGB = 0, SIGW = 0; - - //per locus stats, resize should only happen in first timestep of calculation: - if (_fst_WC_loc.size() == 0) - _fst_WC_loc.resize(nLoci); - if (_fis_WC_loc.size() == 0) - _fis_WC_loc.resize(nLoci); - if (_fit_WC_loc.size() == 0) - _fit_WC_loc.resize(nLoci); + + // per locus stats, resize should only happen in first timestep of calculation: + if (perLocusFstWeirCockerham.size() == 0) + perLocusFstWeirCockerham.resize(nLoci); + if (perLocusFisWeirCockerham.size() == 0) + perLocusFisWeirCockerham.resize(nLoci); + if (perLocusFitWeirCockerham.size() == 0) + perLocusFitWeirCockerham.resize(nLoci); - if (tot_num_allele != nLoci) { - for (int i = 0; i < tot_num_allele; ++i) { + if (nbAllelesInComm != nLoci) { // more than one allele per locus + for (int i = 0; i < nbAllelesInComm; ++i) { MSG[i] = SSG[i] / (2 * nInds); - sigw[i] = MSG[i]; //wasted! - - MSP[i] = SSP[i] / (npl - 1); - - MSI[i] = SSi[i] / (nInds - npl); - - sigb[i] = 0.5 * (MSI[i] - MSG[i]); + MSP[i] = SSP[i] / (nbExtantPops - 1); + MSI[i] = SSi[i] / (nInds - nbExtantPops); siga[i] = (MSP[i] - MSI[i]) / (2 * nc); - - // FST_pal[i] = siga[i]/(siga[i]+sigb[i]+sigw[i]); - // FIS_pal[i] = sigb[i]/(sigb[i]+sigw[i]); + sigb[i] = 0.5 * (MSI[i] - MSG[i]); + sigw[i] = MSG[i]; SIGA += siga[i]; SIGB += sigb[i]; SIGW += sigw[i]; } - double lsiga, lsigb, lsigw; - // cout<<" computing sigma per locus\n"; - - for (int allcntr = 0, i = 0; i < nLoci; ++i) { - - lsiga = lsigb = lsigw = 0; - - for (int l = 0; l < alploc[i]; ++l) { - lsiga += siga[allcntr]; - lsigb += sigb[allcntr]; - lsigw += sigw[allcntr]; - allcntr++; + double locusSIGA, locusSIGB, locusSIGW; + int alleleCounter; + for (int locus = 0; locus < nLoci; ++locus) { + alleleCounter = 0; + locusSIGA = locusSIGB = locusSIGW = 0; + + for (int allele = 0; allele < nbAllelesEachLocus[locus]; ++allele) { + locusSIGA += siga[alleleCounter]; + locusSIGB += sigb[alleleCounter]; + locusSIGW += sigw[alleleCounter]; + alleleCounter++; } - - _fst_WC_loc[i] = lsiga / (lsiga + lsigb + lsigw); - _fis_WC_loc[i] = lsigb / (lsigb + lsigw); - _fit_WC_loc[i] = (lsiga + lsigb) / (lsiga + lsigb + lsigw); - + perLocusFstWeirCockerham[locus] = locusSIGA / (locusSIGA + locusSIGB + locusSIGW); + perLocusFisWeirCockerham[locus] = locusSIGB / (locusSIGB + locusSIGW); + perLocusFitWeirCockerham[locus] = (locusSIGA + locusSIGB) / (locusSIGA + locusSIGB + locusSIGW); } // Total F-stats - _fst_WC = SIGA / (SIGA + SIGB + SIGW); - _fit_WC = (SIGA + SIGB) / (SIGA + SIGB + SIGW); - _fis_WC = SIGB / (SIGB + SIGW); - + FstWeirCockerham = SIGA / (SIGA + SIGB + SIGW); + FitWeirCockerham = (SIGA + SIGB) / (SIGA + SIGB + SIGW); + FisWeirCockerham = SIGB / (SIGB + SIGW); } - else { //then there is no variation at any locus, only 1 allele (wildtype) at each locus so don't calculate to avoid division by zero issues - // Total F-stats - _fst_WC = 0; - _fit_WC = 0; - _fis_WC = 0; + else { // no variation: only 1 allele (wildtype) at each locus + // so don't calculate to avoid division by zero + FstWeirCockerham = 0; + FitWeirCockerham = 0; + FisWeirCockerham = 0; } + // Deallocate matrix for (int i = 0; i < nLoci; ++i) - delete[]alploc_table[i]; - delete[]alploc_table; + delete[]alleleExistsTable[i]; + delete[]alleleExistsTable; } @@ -560,118 +527,125 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd vector patchVect; - copy(patchList.begin(), patchList.end(), std::back_inserter(patchVect)); //needs to be in vector to iterate over, copy preserves order + // Needs to be in vector to iterate over, copy preserves order + copy(patchList.begin(), patchList.end(), std::back_inserter(patchVect)); int nPatches = static_cast(patchList.size()); - //initialise - - if (_fst_matrix.length() != nPatches * nPatches) - _fst_matrix = PatchMatrix(nPatches, nPatches); + // Initialise + if (pairwiseFstMatrix.getNbCells() != nPatches * nPatches) + pairwiseFstMatrix = PatchMatrix(nPatches, nPatches); - //reset table - _fst_matrix.assign(nanf("NULL")); + // Reset table + pairwiseFstMatrix.assign(nanf("NULL")); //init - double* pop_weights = new double[nPatches]; - double* pop_sizes = new double[nPatches]; - double** numerator = new double* [nPatches]; - for (int i = 0; i < nPatches; i++) numerator[i] = new double[nPatches]; - double tot_size; - double numerator_W = 0; + vector popWeights(nPatches); + vector popSizes(nPatches); + double** numeratorPairwiseFst = new double* [nPatches]; + for (int i = 0; i < nPatches; i++) numeratorPairwiseFst[i] = new double[nPatches]; + double totSize; + double numeratorWeightedFst = 0; double denominator = 0; - double sum_weights = 0; + double sumWeights = 0; - tot_size = nInds * 2; //diploid + totSize = nInds * 2; // diploid + // Calculate weight (n_ic) terms for (int i = 0; i < nPatches; ++i) { - const auto patch = pLandscape->findPatch(patchVect[i]); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - pop_sizes[i] = pPop->sampleSize() * 2; - pop_weights[i] = pop_sizes[i] - (pop_sizes[i] * pop_sizes[i] / tot_size); //n_ic in Weir & Hill 2002 - sum_weights += pop_weights[i]; + if (pPop != 0) { + popSizes[i] = pPop->sampleSize() * 2; + } // else popSizes[i] remain default init value 0, safe + popWeights[i] = popSizes[i] - (popSizes[i] * popSizes[i] / totSize); // n_ic in Weir & Hill 2002 + sumWeights += popWeights[i]; + + // Fill the pairwise Fst matrix with default value 0 for (int j = 0; j < nPatches; j++) - numerator[i][j] = 0; + numeratorPairwiseFst[i][j] = 0; } - double p, pq, var, num; - + // Calculate Fst numerators and denominators + double p, pq, pBar, sqDist, num; for (int i = 0; i < nPatches; ++i) { - - if (!pop_sizes[i]) continue; - + if (popSizes[i] == 0) continue; const auto patch = pLandscape->findPatch(patchVect[i]); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); for (int l = 0; l < nLoci; ++l) { - for (int u = 0; u < nAlleles; ++u) { - p = pPop->getAlleleFrequency(l, u); //p_liu - pq = p * (1 - p); + pBar = globalSNPtables[l].getFrequency(u); + sqDist = p - pBar; //(p_liu - pbar_u)^2 + sqDist *= sqDist; - var = p - globalSNPtables[l].getFrequency(u); //(p_liu - pbar_u)^2 - - var *= var; - - num = pq * pop_sizes[i] / (pop_sizes[i] - 1); - - numerator[i][i] += num; - - numerator_W += num * pop_sizes[i]; //see equ. 9, Weir & Hill 2002 - - denominator += pop_sizes[i] * var + pop_weights[i] * pq; //common denominator + num = pq * popSizes[i] / (popSizes[i] - 1); + numeratorPairwiseFst[i][i] += num; + numeratorWeightedFst += num * popSizes[i]; // see equ. 9, Weir & Hill 2002 + denominator += popSizes[i] * sqDist + popWeights[i] * pq; //common denominator } // end for allele - }// end for locus - }//end for pop + } // end for locus + } // end for pop + // Diagonals + double pairwiseFst; for (int i = 0; i < nPatches; ++i) { - if (!pop_sizes[i]) continue; - if(denominator != 0) - _fst_matrix.set(i, i, 1 - (numerator[i][i] * sum_weights / denominator)); - else - _fst_matrix.set(i, i, 0.0); + if (popSizes[i] == 0) continue; + else if (denominator != 0) + { + pairwiseFst = 1 - (numeratorPairwiseFst[i][i] * sumWeights / denominator); + pairwiseFstMatrix.set(i, i, pairwiseFst); + } + else pairwiseFstMatrix.set(i, i, 0.0); } - _fst_WH = 1 - ((numerator_W * sum_weights) / (denominator * tot_size)); //equ. 9 Weir & Hill 2002 - //pairwise Fst: + // Add allele frequencies to numerators double pi, pj; for (int l = 0; l < nLoci; ++l) for (int u = 0; u < nAlleles; ++u) for (int i = 0; i < nPatches - 1; ++i) { - if (!pop_sizes[i]) continue; - + if (popSizes[i] == 0) continue; const auto patch = pLandscape->findPatch(patchVect[i]); const auto pPopI = (Population*)patch->getPopn((intptr)pSpecies); for (int j = i + 1; j < nPatches; ++j) { - if (!pop_sizes[j]) continue; + if (popSizes[j] == 0) continue; const auto patch = pLandscape->findPatch(patchVect[j]); const auto pPopJ = (Population*)patch->getPopn((intptr)pSpecies); pi = pPopI->getAlleleFrequency(l, u); pj = pPopJ->getAlleleFrequency(l, u); - numerator[i][j] += pi * (1 - pj) + pj * (1 - pi); //equ. 7 of Weir & Hill 2002 + numeratorPairwiseFst[i][j] += pi * (1 - pj) + pj * (1 - pi); // equ. 7 of Weir & Hill 2002 } } + // Final estimates of pairwise Fst (beta_ii' in eq. 7 in WC 2002) for (int i = 0; i < nPatches - 1; ++i) { - if (!pop_sizes[i]) continue; + if (popSizes[i] == 0) continue; // Fst for this pair remains NULL for (int j = i + 1; j < nPatches; ++j) { - if (!pop_sizes[j]) continue; - if (denominator != 0) - _fst_matrix.set(i, j, 1 - ((numerator[i][j] * sum_weights) / (2 * denominator))); - else - _fst_matrix.set(i, j, 0.0); + if (popSizes[j] == 0) continue; + else if (denominator != 0) { + pairwiseFst = 1 - (numeratorPairwiseFst[i][j] * sumWeights) / (2 * denominator); + pairwiseFstMatrix.set(i, j, pairwiseFst); + } + else pairwiseFstMatrix.set(i, j, 0.0); } - } - delete[] pop_weights; - delete[] pop_sizes; - for (int i = 0; i < nPatches; i++) delete[] numerator[i]; - delete[] numerator; + } + + // Estimator of global Fst weighted by sample sizes (beta_W in eq. 9 in WH 2002) + if (denominator != 0) { + weightedFstWeirHill = 1 - (numeratorWeightedFst * sumWeights) / (denominator * totSize); // beta_w in Eq. 9 in WH 2002 + } + else { + weightedFstWeirHill = 0.0; + } + + // Deallocate pairwise Fst matrix + for (int i = 0; i < nPatches; i++) delete[] numeratorPairwiseFst[i]; + delete[] numeratorPairwiseFst; } diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index e269ae3..dfb12ed 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -10,37 +10,37 @@ using namespace std; struct PatchMatrix { private: - unsigned int _rows, _cols, _length; - vector _val; + unsigned int rows, cols, nbCells; + vector value; public: - PatchMatrix(int rows = 0, int cols = 0) : _rows(0), _cols(0), _length(0), _val(0) { - _length = rows * cols; - _val.resize(_length); - _rows = rows; _cols = cols; + PatchMatrix(int rows = 0, int cols = 0) : rows(0), cols(0), nbCells(0), value(0) { + nbCells = rows * cols; + value.resize(nbCells); + rows = rows; cols = cols; }; /**Assigns a value to all element of the matrix.*/ void assign(double val) { - for (unsigned int i = 0; i < _length; ++i) _val[i] = val; + for (unsigned int i = 0; i < nbCells; ++i) value[i] = val; } - int length() { return _length; }; + int getNbCells() { return nbCells; }; /**Sets element at row i and column j to value val**/ void set(unsigned int i, unsigned int j, double val) { - if (i * j < _length) - _val[i * _cols + j] = val; + if (i * j < nbCells) + value[i * cols + j] = val; else cout << endl << ("Error: PatchMatrix::set() out of range!\n"); } double get(unsigned int i, unsigned int j) { - if (!((i + 1) * (j + 1) > _length)) - return _val[i * _cols + j]; + if (!((i + 1) * (j + 1) > nbCells)) + return value[i * cols + j]; else cout << endl << ("Error: PatchMatrix::get() out of range!\n"); return 0; @@ -89,19 +89,19 @@ struct SNPtable { class NeutralStatsManager { private: - int _n_extantPopulations, _n_individuals; - /**F-statistics*/ + int nbExtantPops, totalNbSampledInds; + /** F-statistics */ double _ho, _hs, _ht, _hsnei, _htnei, meanNbAllelesPerLocusPerPatch, meanNbAllelesPerLocus, _fst, _fis, _fit, meanNbFixedAllelesPerPatch, nbGloballyFixedAlleles; - /**Weir & Hill (2002) F-stat estimates.*/ - double _fst_WH; - /**Weir & Cockerham (1984) F-stat estimates.*/ - double _fst_WC, _fis_WC, _fit_WC; - /**Per-locus F-stats (Weir&Cockerham).*/ - vector _fst_WC_loc, _fis_WC_loc, _fit_WC_loc, ho_loc; //no need for pointers because shouldn't be copied or moved, resized - - /**Pairwise Fst matrix.*/ - PatchMatrix _fst_matrix; + /** Weir & Hill (2002) F-stat estimates. */ + double weightedFstWeirHill; + /** Weir & Cockerham (1984) F-stat estimates. */ + double FstWeirCockerham, FisWeirCockerham, FitWeirCockerham; + /** Per-locus F-stats (Weir&Cockerham). */ + vector perLocusFstWeirCockerham, perLocusFisWeirCockerham, perLocusFitWeirCockerham, perLocusHo; //no need for pointers because shouldn't be copied or moved, resized + + /** Pairwise Fst matrix. */ + PatchMatrix pairwiseFstMatrix; vector globalSNPtables; //don't have to be pointers, not shared or moved public: @@ -109,21 +109,16 @@ class NeutralStatsManager { NeutralStatsManager(const int& nbSampledPatches, const int nLoci); void updateAllSNPTables(Species* pSpecies, Landscape* pLandscape, set const& patchList); - void resetGlobalSNPtables(); - void setLociDiversityCounter(set const& patchList, const int nInds, Species* pSpecies, Landscape* pLandscape); - - void calculateHo(set const& patchList, const int nbInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape); + void setFstMatrix(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape); + void calculateHo(set const& patchList, const int totalNbSampledInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape); void calculateHs(set const& patchList, const int nbrLoci, Species* pSpecies, Landscape* pLandscape); void calculateHt(Species* pSpecies, Landscape* pLandscape, const int nLoci, const int nAlleles); - void calculateHo2(set const& patchList, const int nbInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape); - + void calculateHo2(set const& patchList, const int totalNbSampledInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape); void calculateFstatWC(set const& patchList, const int nInds, const int nLoci, const int nAlleles, Species* pSpecies, Landscape* pLandscape); void calculateFstatWC_MS(set const& patchList, const int nInds, const int nLoci, const int nAlleles, Species* pSpecies, Landscape* pLandscape); - void setFstMatrix(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape); - double getHsnei() const { return _hsnei; } double getHtnei() const { return _htnei; } double getHo() const { return _ho; } @@ -132,21 +127,21 @@ class NeutralStatsManager { double getFst() const { return _fst; } double getFis() const { return _fis; } double getFit() const { return _fit; } - double getFstWC() const { return _fst_WC; } - double getFisWC() const { return _fis_WC; } - double getFitWC() const { return _fit_WC; } - int getNExtantPatchs() const { return _n_extantPopulations; } - int getNIndividuals() const { return _n_individuals; } - double getWeightedFst() { return _fst_WH; } + double getFstWC() const { return FstWeirCockerham; } + double getFisWC() const { return FisWeirCockerham; } + double getFitWC() const { return FitWeirCockerham; } + int getNbPopulatedSampledPatches() const { return nbExtantPops; } + int getTotalNbSampledInds() const { return totalNbSampledInds; } + double getWeightedFst() { return weightedFstWeirHill; } double getMeanNbAllPerLocusPerPatch() const { return meanNbAllelesPerLocusPerPatch; } double getMeanNbAllPerLocus() const { return meanNbAllelesPerLocus; } double getMeanFixdAllelesPerPatch() const { return meanNbFixedAllelesPerPatch; } double getTotalFixdAlleles() const { return nbGloballyFixedAlleles; } - double getPairwiseFst(int i, int j) { return _fst_matrix.get(i, j); } - double get_fst_WC_loc(int i) const { return _fst_WC_loc[i]; } - double get_fis_WC_loc(int i) const { return _fis_WC_loc[i]; } - double get_fit_WC_loc(int i) const { return _fit_WC_loc[i]; } - double get_ho_loc(int i) const { return ho_loc[i]; } + double getPairwiseFst(int i, int j) { return pairwiseFstMatrix.get(i, j); } + double get_fst_WC_loc(int i) const { return perLocusFstWeirCockerham[i]; } + double get_fis_WC_loc(int i) const { return perLocusFisWeirCockerham[i]; } + double get_fit_WC_loc(int i) const { return perLocusFitWeirCockerham[i]; } + double get_ho_loc(int i) const { return perLocusHo[i]; } }; #endif diff --git a/Population.cpp b/Population.cpp index f84cdca..d7c8fa8 100644 --- a/Population.cpp +++ b/Population.cpp @@ -838,19 +838,30 @@ void Population::sampleIndsWithoutReplacement(string n, const set& sampleSt auto rng = pRandom->getRNG(); set stagedInds; + // Stage individuals in eligible stages for (int stage : sampleStages) { auto sInds = getIndividualsInStage(stage); stagedInds.insert(sInds.begin(), sInds.end()); } - if (n == "all" || stagedInds.size() < stoi(n)) + if (n == "all") { // Sample all individuals in selected stages sampledInds = stagedInds; + } else { - vector out; - // Sample n individuals across selected stages - sample(stagedInds.begin(), stagedInds.end(), std::back_inserter(out), stoi(n), rng); - std::copy(out.begin(), out.end(), std::inserter(sampledInds, sampledInds.end())); + int nbToSample = stoi(n); + if (stagedInds.size() <= nbToSample) { + // Sample all individuals in selected stages + sampledInds = stagedInds; + } + else { + vector tempSampledInds; + // Sample n individuals across selected stages + sample(stagedInds.begin(), stagedInds.end(), std::back_inserter(tempSampledInds), nbToSample, rng); + // Copy from vector to set + std::copy(tempSampledInds.begin(), tempSampledInds.end(), std::inserter(sampledInds, sampledInds.end())); + assert(sampledInds.size() == nbToSample); + } } } @@ -859,12 +870,12 @@ int Population::sampleSize() const { } set Population::getIndividualsInStage(int stage) { - set filteredInds; + set indsInStage; for (auto ind : inds) { if (ind->getStats().stage == stage) - filteredInds.insert(ind); + indsInStage.insert(ind); } - return filteredInds; + return indsInStage; } // Determine which individuals will disperse From 0322059e25593c47716bfe3408c1def30b4d4c27 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 2 Apr 2024 15:26:43 +0100 Subject: [PATCH 079/332] debug case where all sampled patches empty --- NeutralStatsManager.cpp | 559 +++++++++++++++++++++------------------- NeutralStatsManager.h | 6 +- 2 files changed, 297 insertions(+), 268 deletions(-) diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 6f0af3e..f17b9dd 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -30,55 +30,57 @@ NeutralStatsManager::NeutralStatsManager(const int& nbSampledPatches, const int nLoci) { this->pairwiseFstMatrix = PatchMatrix(nbSampledPatches, nbSampledPatches); - globalSNPtables.reserve(nLoci); //don't have to be pointers, not shared or moved + commSNPTables.reserve(nLoci); //don't have to be pointers, not shared or moved } // ---------------------------------------------------------------------------------------- // Set allele tables in SNPtable structs // ---------------------------------------------------------------------------------------- - void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLandscape, set const& patchList) { const int nLoci = pSpecies->getNPositionsForTrait(SNP); const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; const int ploidy = (pSpecies->isDiploid() ? 2 : 1); - if (!globalSNPtables.empty()) - resetGlobalSNPtables(); + if (!commSNPTables.empty()) + resetCommSNPtables(); int populationSize = 0; + int patchAlleleCount; for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop != 0) { - // Update this population's SNP counts tables pPop->updatePopSNPtables(); populationSize += pPop->sampleSize(); + } + // Update global SNP counts tables + for (int thisLocus = 0; thisLocus < nLoci; thisLocus++) { + for (int allele = 0; allele < nAlleles; allele++) { - // Update global SNP counts tables - for (int thisLocus = 0; thisLocus < nLoci; thisLocus++) { - for (int allele = 0; allele < nAlleles; allele++) { - - int patchAlleleCount = pPop->getAlleleTally(thisLocus, allele); - - if (globalSNPtables.size() <= thisLocus) { // if first allele of new loci (should only happen in first calculation step) - SNPtable newSNPtbl = SNPtable(nAlleles, allele, patchAlleleCount); - globalSNPtables.push_back(newSNPtbl); - } - else globalSNPtables[thisLocus].incrementTallyBy(patchAlleleCount, allele); + if (pPop != 0) { + patchAlleleCount = pPop->getAlleleTally(thisLocus, allele); + } + else { + patchAlleleCount = 0; + } + if (commSNPTables.size() <= thisLocus) { // if first allele of new loci (should only happen in first calculation step) + SNPtable newSNPtbl = SNPtable(nAlleles, allele, patchAlleleCount); + commSNPTables.push_back(newSNPtbl); } + else commSNPTables[thisLocus].incrementTallyBy(patchAlleleCount, allele); } } } // Update global frequency populationSize *= ploidy; - std::for_each(globalSNPtables.begin(), - globalSNPtables.end(), - [&](SNPtable &v) -> void { + std::for_each(commSNPTables.begin(), + commSNPTables.end(), + [&](SNPtable& v) -> void { v.setFrequencies(populationSize); }); } @@ -87,8 +89,8 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand // Reset allele tables in SNPtable structs // ---------------------------------------------------------------------------------------- -void NeutralStatsManager::resetGlobalSNPtables() { - for (auto& entry : globalSNPtables) { +void NeutralStatsManager::resetCommSNPtables() { + for (auto& entry : commSNPTables) { entry.reset(); } } @@ -123,7 +125,7 @@ void NeutralStatsManager::setLociDiversityCounter(set const& patchList, con for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - if (pPop != 0) { + if (pPop != 0) { if (pPop->sampleSize() > 0) { nbPopulatedPatches++; nbAllelesInPatch = 0; @@ -138,7 +140,7 @@ void NeutralStatsManager::setLociDiversityCounter(set const& patchList, con } } } - meanNbAllelesPerLocusPerPatch = nbPopulatedPatches == 0 ? meanAllelicDivInPatch / nbPopulatedPatches : 0; + meanNbAllelesPerLocusPerPatch = nbPopulatedPatches > 0 ? meanAllelicDivInPatch / nbPopulatedPatches : 0; // Compute mean allelic diversity per locus meanNbAllelesPerLocus = 0; @@ -166,12 +168,12 @@ void NeutralStatsManager::setLociDiversityCounter(set const& patchList, con } meanNbFixedAllelesPerPatch /= nbPopulatedPatches; } - + // Compute number of fixed loci nbGloballyFixedAlleles = 0; for (i = 0; i < nLoci; ++i) for (j = 0; j < nAlleles; ++j) - nbGloballyFixedAlleles += globalSNPtables[i].getFrequency(j) == 1; + nbGloballyFixedAlleles += commSNPTables[i].getFrequency(j) == 1; } // ---------------------------------------------------------------------------------------- @@ -235,7 +237,7 @@ void NeutralStatsManager::calculateHt(Species* pSpecies, Landscape* pLandscape, for (int allele = 0; allele < nAlleles; ++allele) { - freq = globalSNPtables[thisLocus].getFrequency(allele); + freq = commSNPTables[thisLocus].getFrequency(allele); freq *= freq; //squared frequencies @@ -254,7 +256,7 @@ void NeutralStatsManager::calculateHt(Species* pSpecies, Landscape* pLandscape, void NeutralStatsManager::calculateHo2(set const& patchList, const int nbInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape) { - vector hetero(nbrLoci, 0); + vector hetero(nbrLoci, 0); double nLoci = nbInds * nbrLoci; for (int patchId : patchList) { @@ -285,7 +287,7 @@ void NeutralStatsManager::calculateHo2(set const& patchList, const int nbIn void NeutralStatsManager::calculateFstatWC(set const& patchList, const int nbSampledIndsInComm, const int nLoci, const int nAlleles, Species* pSpecies, Landscape* pLandscape) { double inverseNtotal; - double sum_weights = 0; + double sumWeights = 0; double nBar, nC, inverseNbar; unsigned int nbPopulatedPatches = 0; @@ -296,7 +298,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int int nbSampledIndsinPop = pPop->sampleSize(); if (nbSampledIndsinPop > 0) { nbPopulatedPatches++; - sum_weights += nbSampledIndsinPop * nbSampledIndsinPop / static_cast(nbSampledIndsInComm); + sumWeights += static_cast(nbSampledIndsinPop * nbSampledIndsinPop) / nbSampledIndsInComm; } } } @@ -304,53 +306,62 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int nbExtantPops = nbPopulatedPatches; totalNbSampledInds = nbSampledIndsInComm; // r * nBar - nBar = nbSampledIndsInComm / static_cast(nbPopulatedPatches); // average sample size - nC = (nbSampledIndsInComm - sum_weights) / (nbPopulatedPatches - 1); - inverseNbar = 1.0 / (nBar - 1); - inverseNtotal = 1.0 / nbSampledIndsInComm; - - double var; - double s2, pBar, hBar; - double s2Denom = 1.0 / ((nbPopulatedPatches - 1) * nBar); - double rTerm = static_cast(nbPopulatedPatches - 1) / nbPopulatedPatches; - double hBarFactor = (2 * nBar - 1) / (4 * nBar); - double a = 0, b = 0, c = 0, intermediateTerm; - - for (int thisLocus = 0; thisLocus < nLoci; ++thisLocus) { - - for (int allele = 0; allele < nAlleles; ++allele) { - - s2 = hBar = 0; - pBar = globalSNPtables[thisLocus].getFrequency(allele); - - for (int patchId : patchList) { - const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - if (pPop != 0) { - var = pPop->getAlleleFrequency(thisLocus, allele) - pBar; - var *= var; - s2 += var * pPop->sampleSize(); - hBar += pPop->getHeteroTally(thisLocus, allele); - } - } //end for pop + if (nbPopulatedPatches > 1) { + + // Calculate F stats + nBar = static_cast(nbSampledIndsInComm) / nbPopulatedPatches; // average sample size, cannot be less than 1 + nC = (nbSampledIndsInComm - sumWeights) / nbPopulatedPatches - 1; + double nBarMinusOne = (nBar == 1.0) ? 1.0 : nBar - 1.0; // avoid / 0 if exactly 1 ind per pop + inverseNbar = 1.0 / nBarMinusOne; + inverseNtotal = 1.0 / nbSampledIndsInComm; + + double var; + double s2, pBar, hBar; + double s2Denom = 1.0 / ((nbPopulatedPatches - 1) * nBar); + double rTerm = static_cast(nbPopulatedPatches - 1) / nbPopulatedPatches; + double hBarFactor = (2 * nBarMinusOne) / (4 * nBar); + double a = 0, b = 0, c = 0, intermediateTerm; + + for (int thisLocus = 0; thisLocus < nLoci; ++thisLocus) { + for (int allele = 0; allele < nAlleles; ++allele) { + + s2 = hBar = 0; + pBar = commSNPTables[thisLocus].getFrequency(allele); + + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + if (pPop != 0) { + var = pPop->getAlleleFrequency(thisLocus, allele) - pBar; + var *= var; + s2 += var * pPop->sampleSize(); + hBar += pPop->getHeteroTally(thisLocus, allele); + } + } //end for pop - s2 *= s2Denom; - hBar *= inverseNtotal; + s2 *= s2Denom; + hBar *= inverseNtotal; - intermediateTerm = pBar * (1 - pBar) - rTerm * s2; - a += s2 - inverseNbar * (intermediateTerm - 0.25 * hBar); - b += intermediateTerm - hBarFactor * hBar; - c += hBar; - } // end for allele - } // end for locus + intermediateTerm = pBar * (1 - pBar) - rTerm * s2; + a += s2 - inverseNbar * (intermediateTerm - 0.25 * hBar); + b += intermediateTerm - hBarFactor * hBar; + c += hBar; + } // end for allele + } // end for locus - a *= nBar / nC; - b *= nBar / (nBar - 1); - c *= 0.5; + a *= nBar / nC; + b *= nBar / nBarMinusOne; + c *= 0.5; - FstWeirCockerham = a / (a + b + c); // theta hat in eq. 1 in WC 1984 - FitWeirCockerham = (a + b) / (a + b + c); // F hat - FisWeirCockerham = b / (b + c); // f hat + FstWeirCockerham = a / (a + b + c); // theta hat in eq. 1 in WC 1984 + FitWeirCockerham = (a + b) / (a + b + c); // F hat + FisWeirCockerham = b / (b + c); // f hat + } + else { // zero or one sampled pops, cannot compute F stats + FstWeirCockerham = 0.0; + FitWeirCockerham = 0.0; + FisWeirCockerham = 0.0; + } } @@ -361,7 +372,6 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const int nInds, const int nLoci, const int maxNbAllelesPerLocus, Species* pSpecies, Landscape* pLandscape) { double sumWeights = 0; - double nc; unsigned int nbExtantPops = 0; for (int patchId : patchList) { @@ -371,89 +381,11 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i int patchSize = pPop->sampleSize(); if (patchSize > 0) { nbExtantPops++; - sumWeights += (patchSize * patchSize / static_cast(nInds)); - } - } - } - - nc = (nInds - sumWeights) / (nbExtantPops - 1); - - vector nbAllelesEachLocus(nLoci); - bool** alleleExistsTable = new bool* [nLoci]; - for (int i = 0; i < nLoci; ++i) - alleleExistsTable[i] = new bool[maxNbAllelesPerLocus]; - - int nbAllelesInComm = 0; - for (int locus = 0; locus < nLoci; ++locus) { - nbAllelesEachLocus[locus] = 0; - for (int allele = 0; allele < maxNbAllelesPerLocus; ++allele) { - int count = 0; - for (int patchId : patchList) { - const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - if (pPop != 0) count += pPop->getAlleleTally(locus, allele); - } - alleleExistsTable[locus][allele] = count != 0; - nbAllelesEachLocus[locus] += count != 0; - } - nbAllelesInComm += nbAllelesEachLocus[locus]; - } - - // n, and nal are given by pop_sizes, same num ind typed at all loci in each patch - // nc is the same for each locus - // nt is given by tot_size, same tot num of ind typed for all loci - - //SSG: het/2 for each allele - vector SSG(nbAllelesInComm); - vector SSP(nbAllelesInComm); - vector SSi(nbAllelesInComm); - - int totalAlleleCounter = 0; - double het, pi, var, pBar; - int popSize; - - for (int locus = 0; locus < nLoci; ++locus) { - for (int allele = 0; allele < maxNbAllelesPerLocus && totalAlleleCounter < nbAllelesInComm; ++allele) { - - if (alleleExistsTable[locus][allele] == false) continue; //do not consider alleles not present in the pop - SSG[totalAlleleCounter] = 0; - SSi[totalAlleleCounter] = 0; - SSP[totalAlleleCounter] = 0; - - for (int patchId : patchList) { - const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - if (pPop == 0) popSize = 0; - else popSize = pPop->sampleSize(); - if (popSize == 0) continue; // skip empty patches - - het = pPop->getHeteroTally(locus, allele); // ni * h_i - pi = pPop->getAlleleFrequency(locus, allele); - pBar = globalSNPtables[locus].getFrequency(allele); - var = pi - pBar; //(p_liu - pbar_u)^2 - var *= var; - - SSG[totalAlleleCounter] += het; // numerator MSG - SSi[totalAlleleCounter] += 2 * popSize * pi * (1 - pi) - het / 2; // numerator - SSP[totalAlleleCounter] += 2 * popSize * var; // numerator MSP + sumWeights += static_cast(patchSize * patchSize) / nInds; } - totalAlleleCounter++; } } - if (totalAlleleCounter != nbAllelesInComm) - throw runtime_error("Error:: allele counter and total number of alleles differ in WC mean squared Fstat calculation \n"); - - //these shouldn't have to be dynamically allocated manually, if using a vector from stl then would do allocation for you - vector MSG(nbAllelesInComm); - vector MSP(nbAllelesInComm); - vector MSI(nbAllelesInComm); - vector sigw(nbAllelesInComm); - vector siga(nbAllelesInComm); - vector sigb(nbAllelesInComm); - - double SIGA = 0, SIGB = 0, SIGW = 0; - // per locus stats, resize should only happen in first timestep of calculation: if (perLocusFstWeirCockerham.size() == 0) perLocusFstWeirCockerham.resize(nLoci); @@ -461,56 +393,146 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i perLocusFisWeirCockerham.resize(nLoci); if (perLocusFitWeirCockerham.size() == 0) perLocusFitWeirCockerham.resize(nLoci); - - if (nbAllelesInComm != nLoci) { // more than one allele per locus - for (int i = 0; i < nbAllelesInComm; ++i) { - MSG[i] = SSG[i] / (2 * nInds); - MSP[i] = SSP[i] / (nbExtantPops - 1); - MSI[i] = SSi[i] / (nInds - nbExtantPops); + if (nbExtantPops > 1) { + vector nbAllelesEachLocus(nLoci); + bool** alleleExistsMatrix = new bool* [nLoci]; + for (int i = 0; i < nLoci; ++i) + alleleExistsMatrix[i] = new bool[maxNbAllelesPerLocus]; - siga[i] = (MSP[i] - MSI[i]) / (2 * nc); - sigb[i] = 0.5 * (MSI[i] - MSG[i]); - sigw[i] = MSG[i]; - - SIGA += siga[i]; - SIGB += sigb[i]; - SIGW += sigw[i]; + int nbAllelesInComm = 0; + for (int locus = 0; locus < nLoci; ++locus) { + nbAllelesEachLocus[locus] = 0; + for (int allele = 0; allele < maxNbAllelesPerLocus; ++allele) { + int count = 0; + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + if (pPop != 0) count += pPop->getAlleleTally(locus, allele); + } + alleleExistsMatrix[locus][allele] = count != 0; + nbAllelesEachLocus[locus] += count != 0; + } + nbAllelesInComm += nbAllelesEachLocus[locus]; } - double locusSIGA, locusSIGB, locusSIGW; - int alleleCounter; + // n, and nal are given by pop_sizes, same num ind typed at all loci in each patch + // nc is the same for each locus + // nt is given by tot_size, same tot num of ind typed for all loci + + //SSG: het/2 for each allele + vector SSG(nbAllelesInComm); + vector SSP(nbAllelesInComm); + vector SSi(nbAllelesInComm); + + int totalAlleleCounter = 0; + double het, pi, var, pBar; + int popSize; + for (int locus = 0; locus < nLoci; ++locus) { - alleleCounter = 0; - locusSIGA = locusSIGB = locusSIGW = 0; - - for (int allele = 0; allele < nbAllelesEachLocus[locus]; ++allele) { - locusSIGA += siga[alleleCounter]; - locusSIGB += sigb[alleleCounter]; - locusSIGW += sigw[alleleCounter]; - alleleCounter++; + for (int allele = 0; allele < maxNbAllelesPerLocus && totalAlleleCounter < nbAllelesInComm; ++allele) { + + if (alleleExistsMatrix[locus][allele] == false) continue; //do not consider alleles not present in the pop + SSG[totalAlleleCounter] = 0; + SSi[totalAlleleCounter] = 0; + SSP[totalAlleleCounter] = 0; + + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + if (pPop == 0) popSize = 0; + else popSize = pPop->sampleSize(); + if (popSize == 0) continue; // skip empty patches + + het = pPop->getHeteroTally(locus, allele); // ni * h_i + pi = pPop->getAlleleFrequency(locus, allele); + pBar = commSNPTables[locus].getFrequency(allele); + var = pi - pBar; //(p_liu - pbar_u)^2 + var *= var; + + SSG[totalAlleleCounter] += het; // numerator MSG + SSi[totalAlleleCounter] += 2 * popSize * pi * (1 - pi) - het / 2; // numerator + SSP[totalAlleleCounter] += 2 * popSize * var; // numerator MSP + } + totalAlleleCounter++; + } + } + + if (totalAlleleCounter != nbAllelesInComm) + throw runtime_error("Error:: allele counter and total number of alleles differ in WC mean squared Fstat calculation \n"); + + vector MSG(nbAllelesInComm); + vector MSP(nbAllelesInComm); + vector MSI(nbAllelesInComm); + vector sigw(nbAllelesInComm); + vector siga(nbAllelesInComm); + vector sigb(nbAllelesInComm); + + double SIGA = 0, SIGB = 0, SIGW = 0; + + if (nbAllelesInComm != nLoci) { // more than one allele per locus + double nc = (nInds - sumWeights) / (nbExtantPops - 1); + int MSiDenom = nInds == nbExtantPops ? 1 : nInds - nbExtantPops; // avoid /0 if exactly 1 ind per pop + + for (int i = 0; i < nbAllelesInComm; ++i) { + + MSG[i] = SSG[i] / (2 * nInds); + MSP[i] = SSP[i] / (nbExtantPops - 1); + MSI[i] = SSi[i] / MSiDenom; + + siga[i] = (MSP[i] - MSI[i]) / (2 * nc); + sigb[i] = 0.5 * (MSI[i] - MSG[i]); + sigw[i] = MSG[i]; + + SIGA += siga[i]; + SIGB += sigb[i]; + SIGW += sigw[i]; + } + + double locusSIGA, locusSIGB, locusSIGW; + int alleleCounter; + for (int locus = 0; locus < nLoci; ++locus) { + alleleCounter = 0; + locusSIGA = locusSIGB = locusSIGW = 0; + + for (int allele = 0; allele < nbAllelesEachLocus[locus]; ++allele) { + locusSIGA += siga[alleleCounter]; + locusSIGB += sigb[alleleCounter]; + locusSIGW += sigw[alleleCounter]; + alleleCounter++; + } + perLocusFstWeirCockerham[locus] = locusSIGA / (locusSIGA + locusSIGB + locusSIGW); + perLocusFisWeirCockerham[locus] = locusSIGB / (locusSIGB + locusSIGW); + perLocusFitWeirCockerham[locus] = (locusSIGA + locusSIGB) / (locusSIGA + locusSIGB + locusSIGW); } - perLocusFstWeirCockerham[locus] = locusSIGA / (locusSIGA + locusSIGB + locusSIGW); - perLocusFisWeirCockerham[locus] = locusSIGB / (locusSIGB + locusSIGW); - perLocusFitWeirCockerham[locus] = (locusSIGA + locusSIGB) / (locusSIGA + locusSIGB + locusSIGW); + + // Total F-stats + FstWeirCockerham = SIGA / (SIGA + SIGB + SIGW); + FitWeirCockerham = (SIGA + SIGB) / (SIGA + SIGB + SIGW); + FisWeirCockerham = SIGB / (SIGB + SIGW); + } + else { // no variation: only 1 allele (wildtype) at each locus + // so don't calculate to avoid division by zero + FstWeirCockerham = 0; + FitWeirCockerham = 0; + FisWeirCockerham = 0; } - // Total F-stats - FstWeirCockerham = SIGA / (SIGA + SIGB + SIGW); - FitWeirCockerham = (SIGA + SIGB) / (SIGA + SIGB + SIGW); - FisWeirCockerham = SIGB / (SIGB + SIGW); + // Deallocate matrix + for (int i = 0; i < nLoci; ++i) + delete[]alleleExistsMatrix[i]; + delete[]alleleExistsMatrix; } - else { // no variation: only 1 allele (wildtype) at each locus - // so don't calculate to avoid division by zero + else { // zero or one sampled pops, cannot calculate Fst + for (int locus = 0; locus < nLoci; ++locus) { + perLocusFstWeirCockerham[locus] = 0.0; + perLocusFisWeirCockerham[locus] = 0.0; + perLocusFitWeirCockerham[locus] = 0.0; + } FstWeirCockerham = 0; FitWeirCockerham = 0; FisWeirCockerham = 0; - } - - // Deallocate matrix - for (int i = 0; i < nLoci; ++i) - delete[]alleleExistsTable[i]; - delete[]alleleExistsTable; + } } @@ -525,19 +547,19 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; - vector patchVect; - // Needs to be in vector to iterate over, copy preserves order - copy(patchList.begin(), patchList.end(), std::back_inserter(patchVect)); + vector patchVect; + copy(patchList.begin(), patchList.end(), std::back_inserter(patchVect)); int nPatches = static_cast(patchList.size()); + int nbPopulatedPatches = 0; // Initialise - if (pairwiseFstMatrix.getNbCells() != nPatches * nPatches) + if (pairwiseFstMatrix.getNbCells() != nPatches * nPatches) pairwiseFstMatrix = PatchMatrix(nPatches, nPatches); // Reset table - pairwiseFstMatrix.assign(nanf("NULL")); + pairwiseFstMatrix.assign(0.0); // or nanf("NULL")? //init vector popWeights(nPatches); @@ -556,96 +578,103 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd const auto patch = pLandscape->findPatch(patchVect[i]); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop != 0) { - popSizes[i] = pPop->sampleSize() * 2; + popSizes[i] = pPop->sampleSize() * 2.0; } // else popSizes[i] remain default init value 0, safe popWeights[i] = popSizes[i] - (popSizes[i] * popSizes[i] / totSize); // n_ic in Weir & Hill 2002 sumWeights += popWeights[i]; + if (popSizes[i] > 0) nbPopulatedPatches++; // Fill the pairwise Fst matrix with default value 0 for (int j = 0; j < nPatches; j++) numeratorPairwiseFst[i][j] = 0; } - // Calculate Fst numerators and denominators - double p, pq, pBar, sqDist, num; - for (int i = 0; i < nPatches; ++i) { - if (popSizes[i] == 0) continue; - const auto patch = pLandscape->findPatch(patchVect[i]); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - - for (int l = 0; l < nLoci; ++l) { - for (int u = 0; u < nAlleles; ++u) { - p = pPop->getAlleleFrequency(l, u); //p_liu - pq = p * (1 - p); - pBar = globalSNPtables[l].getFrequency(u); - sqDist = p - pBar; //(p_liu - pbar_u)^2 - sqDist *= sqDist; - - num = pq * popSizes[i] / (popSizes[i] - 1); - numeratorPairwiseFst[i][i] += num; - numeratorWeightedFst += num * popSizes[i]; // see equ. 9, Weir & Hill 2002 - denominator += popSizes[i] * sqDist + popWeights[i] * pq; //common denominator - - } // end for allele - } // end for locus - } // end for pop + if (nbPopulatedPatches > 1) { + // Calculate Fst numerators and denominators + double p, pq, pBar, sqDist, num; + for (int i = 0; i < nPatches; ++i) { + if (popSizes[i] == 0) continue; + const auto patch = pLandscape->findPatch(patchVect[i]); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - // Diagonals - double pairwiseFst; - for (int i = 0; i < nPatches; ++i) { - if (popSizes[i] == 0) continue; - else if (denominator != 0) - { - pairwiseFst = 1 - (numeratorPairwiseFst[i][i] * sumWeights / denominator); - pairwiseFstMatrix.set(i, i, pairwiseFst); + for (int l = 0; l < nLoci; ++l) { + for (int u = 0; u < nAlleles; ++u) { + p = pPop->getAlleleFrequency(l, u); //p_liu + pq = p * (1 - p); + pBar = commSNPTables[l].getFrequency(u); + sqDist = p - pBar; //(p_liu - pbar_u)^2 + sqDist *= sqDist; + + num = pq * popSizes[i] / (popSizes[i] - 1); + numeratorPairwiseFst[i][i] += num; + numeratorWeightedFst += num * popSizes[i]; // see equ. 9, Weir & Hill 2002 + denominator += popSizes[i] * sqDist + popWeights[i] * pq; //common denominator + + } // end for allele + } // end for locus + } // end for pop + + // Diagonals + double pairwiseFst; + for (int i = 0; i < nPatches; ++i) { + if (popSizes[i] == 0) continue; + else if (denominator != 0) + { + pairwiseFst = 1 - (numeratorPairwiseFst[i][i] * sumWeights / denominator); + pairwiseFstMatrix.set(i, i, pairwiseFst); + } + // else remain 0 } - else pairwiseFstMatrix.set(i, i, 0.0); - } - // Add allele frequencies to numerators - double pi, pj; - for (int l = 0; l < nLoci; ++l) - for (int u = 0; u < nAlleles; ++u) - for (int i = 0; i < nPatches - 1; ++i) { - if (popSizes[i] == 0) continue; - const auto patch = pLandscape->findPatch(patchVect[i]); - const auto pPopI = (Population*)patch->getPopn((intptr)pSpecies); - - for (int j = i + 1; j < nPatches; ++j) { - if (popSizes[j] == 0) continue; - const auto patch = pLandscape->findPatch(patchVect[j]); - const auto pPopJ = (Population*)patch->getPopn((intptr)pSpecies); - - pi = pPopI->getAlleleFrequency(l, u); - pj = pPopJ->getAlleleFrequency(l, u); - numeratorPairwiseFst[i][j] += pi * (1 - pj) + pj * (1 - pi); // equ. 7 of Weir & Hill 2002 + // Add allele frequencies to numerators + double pi, pj; + for (int l = 0; l < nLoci; ++l) + for (int u = 0; u < nAlleles; ++u) + for (int i = 0; i < nPatches - 1; ++i) { + if (popSizes[i] == 0) continue; + const auto patch = pLandscape->findPatch(patchVect[i]); + const auto pPopI = (Population*)patch->getPopn((intptr)pSpecies); + + for (int j = i + 1; j < nPatches; ++j) { + if (popSizes[j] == 0) continue; + const auto patch = pLandscape->findPatch(patchVect[j]); + const auto pPopJ = (Population*)patch->getPopn((intptr)pSpecies); + + pi = pPopI->getAlleleFrequency(l, u); + pj = pPopJ->getAlleleFrequency(l, u); + numeratorPairwiseFst[i][j] += pi * (1 - pj) + pj * (1 - pi); // equ. 7 of Weir & Hill 2002 + } } - } - // Final estimates of pairwise Fst (beta_ii' in eq. 7 in WC 2002) - for (int i = 0; i < nPatches - 1; ++i) { - if (popSizes[i] == 0) continue; // Fst for this pair remains NULL - for (int j = i + 1; j < nPatches; ++j) { - if (popSizes[j] == 0) continue; - else if (denominator != 0) { - pairwiseFst = 1 - (numeratorPairwiseFst[i][j] * sumWeights) / (2 * denominator); - pairwiseFstMatrix.set(i, j, pairwiseFst); + // Final estimates of pairwise Fst (beta_ii' in eq. 7 in WC 2002) + for (int i = 0; i < nPatches - 1; ++i) { + if (popSizes[i] == 0) continue; // Fst for this pair remains NULL + for (int j = i + 1; j < nPatches; ++j) { + if (popSizes[j] == 0) continue; + else if (denominator != 0) { + pairwiseFst = 1 - (numeratorPairwiseFst[i][j] * sumWeights) / (2 * denominator); + pairwiseFstMatrix.set(i, j, pairwiseFst); + } + // else remain 0 } - else pairwiseFstMatrix.set(i, j, 0.0); } - } - // Estimator of global Fst weighted by sample sizes (beta_W in eq. 9 in WH 2002) - if (denominator != 0) { - weightedFstWeirHill = 1 - (numeratorWeightedFst * sumWeights) / (denominator * totSize); // beta_w in Eq. 9 in WH 2002 + // Estimator of global Fst weighted by sample sizes (beta_W in eq. 9 in WH 2002) + if (denominator != 0) { + weightedFstWeirHill = 1 - (numeratorWeightedFst * sumWeights) / (denominator * totSize); // beta_w in Eq. 9 in WH 2002 + } + else { + weightedFstWeirHill = 0.0; + } + + // Deallocate pairwise Fst matrix + for (int i = 0; i < nPatches; i++) delete[] numeratorPairwiseFst[i]; + delete[] numeratorPairwiseFst; } - else { + else { // zero or one pop, cannot calculate Fst + // pairwiseFstMatrix keeps default values (0) weightedFstWeirHill = 0.0; } - - // Deallocate pairwise Fst matrix - for (int i = 0; i < nPatches; i++) delete[] numeratorPairwiseFst[i]; - delete[] numeratorPairwiseFst; } diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index dfb12ed..e95eac1 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -66,7 +66,7 @@ struct SNPtable { void setFrequencies(int populationSize) { for (int i = 0; i < alleleFrequencies.size(); i++) { - alleleFrequencies[i] = alleleTallies[i] / static_cast(populationSize); + alleleFrequencies[i] = populationSize > 0 ? alleleTallies[i] / static_cast(populationSize) : 0.0; } }; @@ -102,14 +102,14 @@ class NeutralStatsManager { /** Pairwise Fst matrix. */ PatchMatrix pairwiseFstMatrix; - vector globalSNPtables; //don't have to be pointers, not shared or moved + vector commSNPTables; //don't have to be pointers, not shared or moved public: NeutralStatsManager(const int& nbSampledPatches, const int nLoci); void updateAllSNPTables(Species* pSpecies, Landscape* pLandscape, set const& patchList); - void resetGlobalSNPtables(); + void resetCommSNPtables(); void setLociDiversityCounter(set const& patchList, const int nInds, Species* pSpecies, Landscape* pLandscape); void setFstMatrix(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape); void calculateHo(set const& patchList, const int totalNbSampledInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape); From dea36e6dcc30fac9ead6a0304748cfac1c4a2ec3 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 4 Apr 2024 16:54:13 +0100 Subject: [PATCH 080/332] fix patch sampling --- Community.cpp | 3 ++ Landscape.cpp | 66 +++++++++++++---------------------------- Landscape.h | 11 ++----- Model.cpp | 15 +++++++++- NeutralStatsManager.cpp | 15 ++++++---- NeutralStatsManager.h | 5 ---- Parameters.cpp | 4 ++- Parameters.h | 13 +++----- Patch.cpp | 5 ++++ Patch.h | 1 + Population.h | 3 -- Species.cpp | 8 ++--- Species.h | 8 ++--- SubCommunity.h | 4 --- 14 files changed, 70 insertions(+), 91 deletions(-) diff --git a/Community.cpp b/Community.cpp index 16455f4..bbb69ef 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1633,6 +1633,9 @@ void Community::sampleIndividuals(Species* pSpecies) { for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); + if (patch == 0) { + throw runtime_error("Sampled patch doesn't exist!"); + } auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop != 0) { pPop->sampleIndsWithoutReplacement(n, stages); diff --git a/Landscape.cpp b/Landscape.cpp index b2ef8ff..47c66b9 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -650,17 +650,6 @@ void Landscape::generatePatches(Species* pSpecies) } } } - - simParams sim = paramsSim->getSim(); - if (pSpecies->getNumberOfNeutralLoci() > 0 && - (sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat)) { - - string cellsToSample = pSpecies->getNSampleCellsFst(); - int n = (cellsToSample == "all") ? -9999 : stoi(cellsToSample); - auto patchesToSample = samplePatches(n, (cellsToSample == "all")); - - pSpecies->setSamplePatchList(patchesToSample); - } } //--------------------------------------------------------------------------- @@ -763,18 +752,6 @@ void Landscape::allocatePatches(Species* pSpecies) break; } // end of switch (rasterType) - - simParams sim = paramsSim->getSim(); - if (pSpecies->getNumberOfNeutralLoci() > 0 && (sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat)) { - - string cellsToSample = pSpecies->getNSampleCellsFst(); - int n = (cellsToSample == "all") ? -9999 : stoi(cellsToSample); - - auto patchesToSample = samplePatches(n, (cellsToSample == "all")); - - pSpecies->setSamplePatchList(patchesToSample); - - } } Patch* Landscape::newPatch(int num) @@ -862,18 +839,6 @@ void Landscape::addCellToPatch(Cell* pCell, Patch* pPatch, int hab) { pPatch->addCell(pCell, loc.x, loc.y); } -std::vector Landscape::getTruePatchNums() const { - // Need access to patchnums in Batch interface to set up random sampled patches - // when patchnums member is not yet initialised. - // Bad solution, would be better to rm patchnums and use this in all instances - // but might break existing assumptions in current code. - vector patchNums; - for (auto p : patches) { - patchNums.push_back(p->getPatchNum()); - } - return patchNums; -} - patchData Landscape::getPatchData(int ix) { patchData ppp; ppp.pPatch = patches[ix]; ppp.patchNum = patches[ix]->getPatchNum(); @@ -903,26 +868,35 @@ Patch* Landscape::findPatch(int num) { return 0; } -set Landscape::samplePatches(int n, bool all) { - vector sampledPatches; - vector allPatches; +set Landscape::samplePatches(const string& samplingOption, int nbToSample, Species* pSpecies) { - int npatches = (int)patches.size(); - for (int i = 0; i < npatches; i++) - allPatches.push_back(patches[i]->getPatchNum()); + vector sampledPatches; + vector occupiedPatches; + // Get list of viable patches + for (auto p : patches) { + // p->getPopn(); + if (p->speciesIsPresent(pSpecies)) + occupiedPatches.push_back(p->getPatchNum()); + } - if (!all) { + if (samplingOption == "all") { + sampledPatches = occupiedPatches; + } + else if (samplingOption == "random") { + if (nbToSample > occupiedPatches.size()) + nbToSample = occupiedPatches.size(); auto rng = pRandom->getRNG(); - sample(allPatches.begin(), allPatches.end(), std::back_inserter(sampledPatches), - n, rng); + sample(occupiedPatches.begin(), occupiedPatches.end(), std::back_inserter(sampledPatches), + nbToSample, rng); + } + else { + throw logic_error("Sampling option should be random or all when sampling patches."); } - else sampledPatches = allPatches; set patchIds; copy(sampledPatches.begin(), sampledPatches.end(), inserter(patchIds, patchIds.end())); - return patchIds; } diff --git a/Landscape.h b/Landscape.h index 10b703b..c042470 100644 --- a/Landscape.h +++ b/Landscape.h @@ -291,7 +291,7 @@ class Landscape { Patch* findPatch( int // Patch id no. ); - set samplePatches(int n, bool all); + set samplePatches(const string& samplingOption, int nbToSample, Species* pSpecies); int checkTotalCover(void); void resetPatchPopns(void); void updateCarryingCapacity( @@ -451,9 +451,8 @@ class Landscape { string // cost file name (may be NULL) ); void listPatches(void); - int readCosts( - string // costs file name - ); + int readCosts(string); // costs file name + // the following four functions are implemented for the GUI version only // in the batch version, they are defined, but empty void setLandMap(void); @@ -462,10 +461,6 @@ class Landscape { int, // landscape index number (always 0 if landscape is not dynamic) int // landscape no. ); - void drawGradient(void); // Draw environmental gradient map - void drawGlobalStoch( // Draw environmental stochasticity time-series - int // no. of years - ); void resetVisits(void); void outVisits(int, int); // save SMS path visits map to raster text file diff --git a/Model.cpp b/Model.cpp index 5d9772d..87d61d5 100644 --- a/Model.cpp +++ b/Model.cpp @@ -468,7 +468,20 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->outInds(rep, yr, gen, -1); // output Genetics if ((sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat) && yr % sim.outputGeneticInterval == 0) { - if (pLandscape) pComm->sampleIndividuals(pSpecies); + + simParams sim = paramsSim->getSim(); + if (sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat) { + + if (sim.patchSamplingOption != "list") { + // then patches must be re-sampled every gen + int nbToSample = pSpecies->getNbPatchesToSample(); + auto patchesToSample = pLandscape->samplePatches(sim.patchSamplingOption, nbToSample, pSpecies); + pSpecies->setSamplePatchList(patchesToSample); + } + // otherwise always use the user-specified list (even if patches are empty) + } + + pComm->sampleIndividuals(pSpecies); pComm->outNeutralGenetics(pSpecies, rep, yr, gen, sim.outputWCFstat, sim.outputPerLocusWCFstat, sim.outputPairwiseFst); } if (dem.stageStruct) { diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index f17b9dd..b54b5c9 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -43,8 +43,15 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; const int ploidy = (pSpecies->isDiploid() ? 2 : 1); - if (!commSNPTables.empty()) + if (!commSNPTables.empty()) { resetCommSNPtables(); + } + else { // populate the tables with default values + for (int thisLocus = 0; thisLocus < nLoci; thisLocus++) { + SNPtable newSNPtbl = SNPtable(nAlleles); + commSNPTables.push_back(newSNPtbl); + } + } int populationSize = 0; int patchAlleleCount; @@ -67,11 +74,7 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand else { patchAlleleCount = 0; } - if (commSNPTables.size() <= thisLocus) { // if first allele of new loci (should only happen in first calculation step) - SNPtable newSNPtbl = SNPtable(nAlleles, allele, patchAlleleCount); - commSNPTables.push_back(newSNPtbl); - } - else commSNPTables[thisLocus].incrementTallyBy(patchAlleleCount, allele); + commSNPTables[thisLocus].incrementTallyBy(patchAlleleCount, allele); } } } diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index e95eac1..98b75ef 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -56,11 +56,6 @@ struct SNPtable { vector alleleHeterozygoteTallies; public: - //for community allele table, heteros not technically needed so don't reserve - SNPtable(int nAllele, int allele, int alleleCount) : alleleTallies(nAllele), alleleFrequencies(nAllele) { - this->incrementTallyBy(alleleCount, allele); - }; - //for population allele tables SNPtable(int nAllele) : alleleTallies(nAllele), alleleFrequencies(nAllele), alleleHeterozygoteTallies(nAllele) {}; diff --git a/Parameters.cpp b/Parameters.cpp index 5821779..bf7bf42 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -286,7 +286,8 @@ void paramSim::setSim(simParams s) { fixReplicateSeed = s.fixReplicateSeed; } -void paramSim::setGeneticSim(bool outputWCFstat, bool outputPerLocusWCFstat, bool outputPairwiseFst, int outputGeneticInterval) { +void paramSim::setGeneticSim(string patchSamplingOption, bool outputWCFstat, bool outputPerLocusWCFstat, bool outputPairwiseFst, int outputGeneticInterval) { + this->patchSamplingOption = patchSamplingOption; this->outputWCFstat = outputWCFstat; this->outputPerLocusWCFstat = outputPerLocusWCFstat; this->outputPairwiseFst = outputPairwiseFst; @@ -323,6 +324,7 @@ simParams paramSim::getSim(void) { s.CreatePopFile = CreatePopFile; #endif s.drawLoaded = drawLoaded; + s.patchSamplingOption = patchSamplingOption; s.outputWCFstat = outputWCFstat; s.outputPerLocusWCFstat = outputPerLocusWCFstat; s.outputPairwiseFst = outputPairwiseFst; diff --git a/Parameters.h b/Parameters.h index 36ff4ba..e6f63e1 100644 --- a/Parameters.h +++ b/Parameters.h @@ -344,9 +344,8 @@ struct simParams { int outStartPaths; int outIntPaths; bool outPaths; bool ReturnPopRaster; bool CreatePopFile; #endif - int fionaOptions; - int storeIndsYr; bool fixReplicateSeed; + string patchSamplingOption; bool outputWCFstat, outputPerLocusWCFstat, outputPairwiseFst; int outputGeneticInterval; }; @@ -363,7 +362,7 @@ class paramSim { paramSim(void); ~paramSim(void); void setSim(simParams); - void setGeneticSim(bool outputWCFstat, bool outputPerLocusWCFstat, bool outputPairwiseFst, int outputGeneticInterval); + void setGeneticSim(string patchSamplingOption, bool outputWCFstat, bool outputPerLocusWCFstat, bool outputPairwiseFst, int outputGeneticInterval); simParams getSim(void); int getSimNum(void); void setViews(simView); @@ -380,8 +379,6 @@ class paramSim { int simulation; // simulation no. int reps; // no. of replicates int years; // no. of years - // int outStartRange; // output start year for range file - // int outStartOcc; // output start year for occupancy file int outStartPop; // output start year for population file int outStartInd; // output start year for individuals file int outStartTraitCell; // output start year for traits by cell file @@ -398,8 +395,7 @@ class paramSim { int traitInt; // output interval for evolving traits maps int slowFactor; // to reduce speed of movement paths on screen bool batchMode; // - bool absorbing; // landscape boundary and no-data regions are - // absorbing boundaries + bool absorbing; // landscape boundary and no-data regions are absorbing boundaries bool outRange; // produce output range file? bool outOccup; // produce output occupancy file? bool outPop; // produce output population file? @@ -428,9 +424,8 @@ class paramSim { bool viewGraph; // view population/occupancy graph on screen? string dir; // full name of working directory - int fionaOptions; - int storeIndsYr; bool fixReplicateSeed; + string patchSamplingOption; bool outputWCFstat; bool outputPerLocusWCFstat; bool outputPairwiseFst; diff --git a/Patch.cpp b/Patch.cpp index 499dbc5..8504a57 100644 --- a/Patch.cpp +++ b/Patch.cpp @@ -354,6 +354,11 @@ int Patch::getPossSettlers(Species* pSpecies, int sex) { else return 0; } +bool Patch::speciesIsPresent(Species* pSpecies) { + const auto pPop = this->getPopn((intptr)pSpecies); + return pPop != 0; +} + //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- diff --git a/Patch.h b/Patch.h index 4b6c871..445dd02 100644 --- a/Patch.h +++ b/Patch.h @@ -141,6 +141,7 @@ class Patch { bool // TRUE if there is a gradient in carrying capacity across the Landscape ); float getK(void); + bool speciesIsPresent(Species* sp); private: int patchSeqNum;// sequential patch number - patch 0 is reserved for the inter-patch matrix diff --git a/Population.h b/Population.h index 1d7b9de..d20cf06 100644 --- a/Population.h +++ b/Population.h @@ -148,9 +148,6 @@ class Population { disperser extractSettler( int // index no. to the Individual in the inds vector ); - void addEmigTraitsForInd(int ix, emigTraits&); - void addSettleTraitsForInd(int, settleTraits&); - void addTransferDataForInd(int ix, trfrData* avgTrfrData); void recruit( // Add a specified individual to the population Individual* // pointer to Individual ); diff --git a/Species.cpp b/Species.cpp index ec463bc..b01f33c 100644 --- a/Species.cpp +++ b/Species.cpp @@ -383,7 +383,7 @@ void Species::resetGeneticParameters() { numberOfAdaptiveTraits = 0; genomeSize = -9999; recombinationRate = -9999; - nSampleCellsFst = ""; + nPatchesToSample = 0; nIndsToSample = ""; chromosomeEnds.clear(); samplePatchList.clear(); @@ -760,18 +760,18 @@ void Species::setSettTraits(const short stg, const short sex, const settleTraits } void Species::setGeneticParameters(const std::set& chromosomeEnds, const int genomeSize, const float recombinationRate, - const std::set& samplePatchList, const string nIndsToSample, const std::set& stagesToSampleFrom, string nSampleCellsFst) + const std::set& samplePatchList, const string nIndsToSample, const std::set& stagesToSampleFrom, int nPatchesToSampleFrom) { this->genomeSize = genomeSize; this->chromosomeEnds = chromosomeEnds; this->recombinationRate = recombinationRate; this->samplePatchList = samplePatchList; - this->nSampleCellsFst = nSampleCellsFst; + this->nPatchesToSample = nPatchesToSampleFrom; this->nIndsToSample = nIndsToSample; this->stagesToSampleFrom = stagesToSampleFrom; } -//only called for cell based landscape +// only called for cell based landscape void Species::setSamplePatchList(const set& samplePatchList) { this->samplePatchList = samplePatchList; } diff --git a/Species.h b/Species.h index c26a788..485db45 100644 --- a/Species.h +++ b/Species.h @@ -298,8 +298,8 @@ class Species { return stagesToSampleFrom; } - string getNSampleCellsFst() { - return nSampleCellsFst; + int getNbPatchesToSample() { + return nPatchesToSample; } // Genetic functions @@ -432,7 +432,7 @@ class Species { float getRecombinationRate() const; std::set getChromosomeEnds() const; void setGeneticParameters(const std::set& chromosomeEnds, const int genomeSize, const float recombinationRate, - const std::set& samplePatchList, const string nIndsToSample, const std::set& stagesToSampleFrom, string nSampleCellsFst); + const std::set& samplePatchList, const string nIndsToSample, const std::set& stagesToSampleFrom, int nPatchesToSampleFrom); void setSamplePatchList(const std::set& samplePatchList); private: @@ -495,7 +495,7 @@ class Species { int numberOfAdaptiveTraits; float recombinationRate; std::set samplePatchList; - string nSampleCellsFst; //for cell based landscape + int nPatchesToSample; //for cell based landscape std::set stagesToSampleFrom; string nIndsToSample; //could be integer or 'all', all means in in selected patches not necessarily all in population diff --git a/SubCommunity.h b/SubCommunity.h index 0bf9ba5..05baa23 100644 --- a/SubCommunity.h +++ b/SubCommunity.h @@ -132,10 +132,6 @@ class SubCommunity { ); void ageIncrement(void); - int addEmigrationAndSettlementTraitValues(emigTraits& avgEmTraits, settleTraits& avgSettleTraits); - - void addTransferDataForInd(trfrData* avgTrfrData); - // Find the population of a given species in a given patch Population* findPop(Species*, Patch*); From a8a579befdb954f5a6e006e76f0b4bcc1617cb03 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 5 Apr 2024 14:22:26 +0100 Subject: [PATCH 081/332] clean up neutral stats --- Community.cpp | 8 ++++---- Landscape.h | 1 - NeutralStatsManager.cpp | 4 ++-- Population.cpp | 9 ++++----- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Community.cpp b/Community.cpp index bbb69ef..942a54c 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1628,17 +1628,17 @@ Rcpp::IntegerMatrix Community::addYearToPopList(int rep, int yr) { // TODO: def void Community::sampleIndividuals(Species* pSpecies) { const set patchList = pSpecies->getSamplePatches(); - string n = pSpecies->getNIndsToSample(); - const set stages = pSpecies->getStagesToSample(); + string nbIndsToSample = pSpecies->getNIndsToSample(); + const set stagesToSampleFrom = pSpecies->getStagesToSample(); for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); if (patch == 0) { - throw runtime_error("Sampled patch doesn't exist!"); + throw runtime_error("Sampled patch doesn't exist."); } auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop != 0) { - pPop->sampleIndsWithoutReplacement(n, stages); + pPop->sampleIndsWithoutReplacement(nbIndsToSample, stagesToSampleFrom); } } } diff --git a/Landscape.h b/Landscape.h index c042470..e03b23b 100644 --- a/Landscape.h +++ b/Landscape.h @@ -235,7 +235,6 @@ class Landscape { void setCellArray(void); void addPatchNum(int); std::vector getPatchNums() const { return patchnums; } - std::vector getTruePatchNums() const; void generatePatches(Species*); // create an artificial landscape void allocatePatches(Species*); // create patches for a cell-based landscape Patch* newPatch( diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index b54b5c9..3c70ced 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -338,12 +338,12 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int var = pPop->getAlleleFrequency(thisLocus, allele) - pBar; var *= var; s2 += var * pPop->sampleSize(); - hBar += pPop->getHeteroTally(thisLocus, allele); + hBar += pPop->getHeteroTally(thisLocus, allele); // n_i * h_i } } //end for pop s2 *= s2Denom; - hBar *= inverseNtotal; + hBar *= inverseNtotal; // / (r * n_bar) intermediateTerm = pBar * (1 - pBar) - rTerm * s2; a += s2 - inverseNbar * (intermediateTerm - 0.25 * hBar); diff --git a/Population.cpp b/Population.cpp index d7c8fa8..07bf177 100644 --- a/Population.cpp +++ b/Population.cpp @@ -374,7 +374,6 @@ void Population::updatePopSNPtables() { popSNPtables.end(), [&](SNPtable& thisLocus) -> void { thisLocus.setFrequencies(static_cast(sampledInds.size()) * 2); // /!\ assumes dipoidy? - //thisLocus->divideHeteros(sampledInds.size()); //weir and cockerham doesn't need this division?? }); } } @@ -832,7 +831,7 @@ Individual* Population::sampleInd() const { return inds[index]; } -void Population::sampleIndsWithoutReplacement(string n, const set& sampleStages) { +void Population::sampleIndsWithoutReplacement(string strNbToSample, const set& sampleStages) { sampledInds.clear(); auto rng = pRandom->getRNG(); @@ -844,12 +843,12 @@ void Population::sampleIndsWithoutReplacement(string n, const set& sampleSt stagedInds.insert(sInds.begin(), sInds.end()); } - if (n == "all") { + if (strNbToSample == "all") { // Sample all individuals in selected stages sampledInds = stagedInds; } - else { - int nbToSample = stoi(n); + else { // random + int nbToSample = stoi(strNbToSample); if (stagedInds.size() <= nbToSample) { // Sample all individuals in selected stages sampledInds = stagedInds; From b5c5ba564b09efea541059fc38bd9ae2f61c1a55 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 5 Apr 2024 16:32:31 +0100 Subject: [PATCH 082/332] progress with fixing ploidy in neutral stats --- GeneticLoad.cpp | 2 +- GeneticLoad.h | 2 +- Model.cpp | 2 -- NeutralStatsManager.cpp | 18 +++++++++--------- NeutralStatsManager.h | 2 +- Population.cpp | 21 ++++++++++++--------- QTLTrait.cpp | 2 +- QTLTrait.h | 2 +- SNPTrait.cpp | 2 +- SNPTrait.h | 10 +++------- 10 files changed, 30 insertions(+), 33 deletions(-) diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index dcf1811..ae5d9df 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -291,7 +291,7 @@ void GeneticLoad::inherit(TTrait* parentTrait, set const& recomPos { auto parentCast = dynamic_cast (parentTrait); //horrible - const auto& parent_seq = parentCast->get_mutations(); + const auto& parent_seq = parentCast->getGenes(); if (parent_seq.size() > 0) //else nothing to inherit (this->*_inherit_func_ptr) (whichChromosome, parent_seq, recomPositions, startingChromosome); } diff --git a/GeneticLoad.h b/GeneticLoad.h index ed0c45c..817f22d 100644 --- a/GeneticLoad.h +++ b/GeneticLoad.h @@ -52,7 +52,7 @@ class GeneticLoad : public TTrait { bool isInherited() const override { return pSpeciesTrait->isInherited(); } - map>>& get_mutations() { return genes; } //returning reference, reciever must be const + map>>& getGenes() { return genes; } //returning reference, reciever must be const virtual float getAlleleValueAtLocus(short chromosome, int position) const override; diff --git a/Model.cpp b/Model.cpp index 87d61d5..9f51e94 100644 --- a/Model.cpp +++ b/Model.cpp @@ -471,7 +471,6 @@ int RunModel(Landscape* pLandscape, int seqsim) simParams sim = paramsSim->getSim(); if (sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat) { - if (sim.patchSamplingOption != "list") { // then patches must be re-sampled every gen int nbToSample = pSpecies->getNbPatchesToSample(); @@ -480,7 +479,6 @@ int RunModel(Landscape* pLandscape, int seqsim) } // otherwise always use the user-specified list (even if patches are empty) } - pComm->sampleIndividuals(pSpecies); pComm->outNeutralGenetics(pSpecies, rep, yr, gen, sim.outputWCFstat, sim.outputPerLocusWCFstat, sim.outputPairwiseFst); } diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 3c70ced..9a6cc75 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -41,7 +41,7 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand const int nLoci = pSpecies->getNPositionsForTrait(SNP); const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; - const int ploidy = (pSpecies->isDiploid() ? 2 : 1); + const int ploidy = pSpecies->isDiploid() ? 2 : 1; if (!commSNPTables.empty()) { resetCommSNPtables(); @@ -53,7 +53,7 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand } } - int populationSize = 0; + int nbSampledInds = 0; int patchAlleleCount; for (int patchId : patchList) { @@ -62,7 +62,7 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand if (pPop != 0) { // Update this population's SNP counts tables pPop->updatePopSNPtables(); - populationSize += pPop->sampleSize(); + nbSampledInds += pPop->sampleSize(); } // Update global SNP counts tables for (int thisLocus = 0; thisLocus < nLoci; thisLocus++) { @@ -80,11 +80,10 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand } // Update global frequency - populationSize *= ploidy; std::for_each(commSNPTables.begin(), commSNPTables.end(), [&](SNPtable& v) -> void { - v.setFrequencies(populationSize); + v.setFrequencies(nbSampledInds * ploidy); }); } @@ -108,7 +107,7 @@ void NeutralStatsManager::setLociDiversityCounter(set const& patchList, con int i, j; const int nLoci = pSpecies->getNPositionsForTrait(SNP); const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; - const int ploidy = (pSpecies->isDiploid() ? 2 : 1); + const int ploidy = pSpecies->isDiploid() ? 2 : 1; unsigned int nbPopulatedPatches = 0; int nbAllelesInPatch = 0; double meanAllelicDivInPatch = 0; @@ -195,7 +194,7 @@ void NeutralStatsManager::calculateHo(set const& patchList, const int nbInd nbHetero += pPop->countHeterozygoteLoci(); } } - _ho = static_cast(nbHetero) / static_cast(nLoci); + _ho = static_cast(nbHetero) / nLoci; } else _ho = 0.0; } @@ -549,6 +548,7 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape) { const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; + const int ploidy = pSpecies->isDiploid() ? 2 : 1; // Needs to be in vector to iterate over, copy preserves order vector patchVect; @@ -574,14 +574,14 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd double denominator = 0; double sumWeights = 0; - totSize = nInds * 2; // diploid + totSize = nInds * ploidy; // diploid // Calculate weight (n_ic) terms for (int i = 0; i < nPatches; ++i) { const auto patch = pLandscape->findPatch(patchVect[i]); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop != 0) { - popSizes[i] = pPop->sampleSize() * 2.0; + popSizes[i] = pPop->sampleSize() * ploidy; } // else popSizes[i] remain default init value 0, safe popWeights[i] = popSizes[i] - (popSizes[i] * popSizes[i] / totSize); // n_ic in Weir & Hill 2002 sumWeights += popWeights[i]; diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index 98b75ef..1078b5e 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -61,7 +61,7 @@ struct SNPtable { void setFrequencies(int populationSize) { for (int i = 0; i < alleleFrequencies.size(); i++) { - alleleFrequencies[i] = populationSize > 0 ? alleleTallies[i] / static_cast(populationSize) : 0.0; + alleleFrequencies[i] = populationSize > 0 ? static_cast(alleleTallies[i]) / populationSize : 0.0; } }; diff --git a/Population.cpp b/Population.cpp index 07bf177..bf4468c 100644 --- a/Population.cpp +++ b/Population.cpp @@ -335,6 +335,7 @@ void Population::updatePopSNPtables() { const int nLoci = pSpecies->getNPositionsForTrait(SNP); const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; const auto& positions = pSpecies->getSpTrait(SNP)->getPositions(); + const int ploidy = pSpecies->isDiploid() ? 2 : 1; if (popSNPtables.size() != 0) resetPopSNPtables(); @@ -354,16 +355,18 @@ void Population::updatePopSNPtables() { for (auto position : positions) { int alleleOnChromA = (int)trait->getAlleleValueAtLocus(0, position); - int alleleOnChromB = (int)trait->getAlleleValueAtLocus(1, position); - - bool isHetero = alleleOnChromA != alleleOnChromB; - if (isHetero) { - popSNPtables[whichLocus].incrementHeteroTally(alleleOnChromA); - popSNPtables[whichLocus].incrementHeteroTally(alleleOnChromB); - } popSNPtables[whichLocus].incrementTally(alleleOnChromA); - popSNPtables[whichLocus].incrementTally(alleleOnChromB); + if (ploidy == 2) { + int alleleOnChromB = (int)trait->getAlleleValueAtLocus(1, position); + popSNPtables[whichLocus].incrementTally(alleleOnChromB); + + bool isHetero = alleleOnChromA != alleleOnChromB; + if (isHetero) { + popSNPtables[whichLocus].incrementHeteroTally(alleleOnChromA); + popSNPtables[whichLocus].incrementHeteroTally(alleleOnChromB); + } + } whichLocus++; } } @@ -373,7 +376,7 @@ void Population::updatePopSNPtables() { popSNPtables.begin(), popSNPtables.end(), [&](SNPtable& thisLocus) -> void { - thisLocus.setFrequencies(static_cast(sampledInds.size()) * 2); // /!\ assumes dipoidy? + thisLocus.setFrequencies(static_cast(sampledInds.size()) * ploidy); // /!\ assumes dipoidy? }); } } diff --git a/QTLTrait.cpp b/QTLTrait.cpp index 383dffd..8a1be32 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -200,7 +200,7 @@ void QTLTrait::inherit(TTrait* parentTrait, set const& recomPositi { auto parentCast = dynamic_cast (parentTrait); //horrible - const auto& parent_seq = parentCast->get_mutations(); + const auto& parent_seq = parentCast->getGenes(); if (parent_seq.size() > 0) //else nothing to inherit, should always be something to inherit with QTL (this->*_inherit_func_ptr) (whichChromosome, parent_seq, recomPositions, startingChromosome); } diff --git a/QTLTrait.h b/QTLTrait.h index 00c7234..62c08db 100644 --- a/QTLTrait.h +++ b/QTLTrait.h @@ -47,7 +47,7 @@ class QTLTrait : public TTrait { void mutate() override { (this->*_mutate_func_ptr) (); } float express() override { return (this->*_express_func_ptr) (); } void inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) override; - map>>& get_mutations() { return genes; } // returning reference, receiver must be const + map>>& getGenes() { return genes; } // returning reference, receiver must be const // virtual float getAlleleValueAtLocus(short chromosome, int i) const override { return (double)mutations[chromosome][i]->getSelectionCoef(); } diff --git a/SNPTrait.cpp b/SNPTrait.cpp index 258950a..ebde22a 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -182,7 +182,7 @@ void SNPTrait::inherit(TTrait* parent, set const& recomPositions, { auto parentCast = dynamic_cast (parent); //horrible - const auto& parent_seq = parentCast->get_mutations(); + const auto& parent_seq = parentCast->getGenes(); if (parent_seq.size() > 0) //else nothing to inherit (this->*_inherit_func_ptr) (chromosome, parent_seq, recomPositions, startingChromosome); } diff --git a/SNPTrait.h b/SNPTrait.h index f06b4e5..740224c 100644 --- a/SNPTrait.h +++ b/SNPTrait.h @@ -36,23 +36,20 @@ class SNPTrait : public TTrait { public: //this one for species held trait table, e.g. prototype table, sets static members SNPTrait(SpeciesTrait* P); - //this one for individuals, static members are not reset SNPTrait(const SNPTrait& T); + virtual ~SNPTrait() { } + virtual unique_ptr clone() const override { return std::make_unique(*this); } virtual void inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) override; - virtual void mutate() override { (this->*_mutate_func_ptr) (); } virtual int getNLoci() const override { return pProtoTrait->getPositionsSize(); } - float getMutationRate() const override { return pProtoTrait->getMutationRate(); } - bool isInherited() const override { return pProtoTrait->isInherited(); } - - map>& get_mutations() { return genes; } //returning reference, reciever must be const + map>& getGenes() { return genes; } //returning reference, reciever must be const virtual float getAlleleValueAtLocus(short chromosome, int position) const override; @@ -62,6 +59,5 @@ class SNPTrait : public TTrait { virtual float express() { return -9999; } - virtual ~SNPTrait() { } }; #endif \ No newline at end of file From bd5a24bc3f8f418592603be55a293ed5945bd773 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 9 Apr 2024 11:44:42 +0100 Subject: [PATCH 083/332] cleanup --- Individual.cpp | 14 -------------- Individual.h | 2 -- SNPTrait.cpp | 13 ++++++------- Species.cpp | 13 +------------ Species.h | 5 +---- 5 files changed, 8 insertions(+), 39 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 0eb9758..bcf93dc 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -55,7 +55,6 @@ Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short rep path = new pathData; path->year = 0; path->total = 0; path->out = 0; path->pSettPatch = 0; path->settleStatus = 0; - // path->leftNatalPatch = false; if (moveType == 1) { // SMS // set up location data for SMS pTrfrData = make_unique(loc, loc); @@ -73,18 +72,10 @@ Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short rep path = 0; pTrfrData = make_unique(0.0, 0.0, 0.0); } - //pEmigTraits = make_unique(nullptr); - //pSettleTraits = make_unique(nullptr); } Individual::~Individual(void) { if (path != 0) delete path; - //if (crw != 0) delete crw; - //if (smsData != 0) delete smsData; - //if (emigtraits != 0) delete emigtraits; - //if (kerntraits != 0) delete kerntraits; - //if (setttraits != 0) delete setttraits; - } @@ -113,11 +104,6 @@ TTrait* Individual::getTrait(TraitType trait) const { else return p->second.get(); } -//map> Individual::getTraitTable(void) const -//{ -// return traitTable; -//} - set Individual::getTraitTypes() { auto kv = std::views::keys(this->spTraitTable); set< TraitType > keys{ kv.begin(), kv.end() }; diff --git a/Individual.h b/Individual.h index b60a2f3..4f20482 100644 --- a/Individual.h +++ b/Individual.h @@ -255,8 +255,6 @@ class Individual { set getTraitTypes(); - //map> getTraitTable(void) const; - void inherit(Species* pSpecies, const Individual* mother, const Individual* father); void inherit(Species* pSpecies, const Individual* mother); // haploid diff --git a/SNPTrait.cpp b/SNPTrait.cpp index ebde22a..4e5d037 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -100,22 +100,21 @@ void SNPTrait::mutate_KAM() for (int p = 0; p < ploidy; p++) { unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); + if (NbMut > positionsSize) NbMut = positionsSize; if (NbMut > 0) { vector mutationPositions; sample(positions.begin(), positions.end(), std::back_inserter(mutationPositions), - NbMut, rng); + NbMut, rng); // without replacement for (int m : mutationPositions) { - mut = (unsigned char)pRandom->IRandom(0, maxD - 1); //draw new mutation, could draw wildtype - auto it = genes.find(m); //find if position in map already has mutations there - - if (it == genes.end()) { // not found so create new entry in map with wildtype as char default + mut = (unsigned char)pRandom->IRandom(0, maxD - 1); // draw new mutation, could draw wildtype + auto it = genes.find(m); // find if position in map already has mutations there + if (it == genes.end()) { // not found so create new entry in map with wildtype as char default vector allelePair(2, wildType); - allelePair[p] = mut; //put new mutation value in - + allelePair[p] = mut; //put new mutation value in genes.insert(make_pair(m, allelePair)); } else { //position found, already mutations there diff --git a/Species.cpp b/Species.cpp index b01f33c..6288724 100644 --- a/Species.cpp +++ b/Species.cpp @@ -379,7 +379,6 @@ bool Species::areMutationsOn(void) { void Species::resetGeneticParameters() { mutationsOn = true; - numberOfNeutralLoci = -9999; numberOfAdaptiveTraits = 0; genomeSize = -9999; recombinationRate = -9999; @@ -393,16 +392,6 @@ bool Species::isDiploid() const { return diploid; } -void Species::setNumberOfNeutralLoci(int nN) -{ - numberOfNeutralLoci = nN; -} - -int Species::getNumberOfNeutralLoci() const -{ - return numberOfNeutralLoci; -} - int Species::incrementAdaptiveTraits() { numberOfAdaptiveTraits++; @@ -417,7 +406,7 @@ int Species::getNumberOfAdaptiveTraits() const void Species::addTrait(TraitType traitType, const SpeciesTrait& trait) { TraitType traitT = traitType; - //hack to deal with multiple genetic load traits, could be handled better + // hack to deal with multiple genetic load traits, could be handled better if (traitType == GENETIC_LOAD) { int n = incrementAdaptiveTraits(); diff --git a/Species.h b/Species.h index 485db45..09e0c20 100644 --- a/Species.h +++ b/Species.h @@ -306,8 +306,6 @@ class Species { void resetGeneticParameters(); bool areMutationsOn(void); bool isDiploid() const; - void setNumberOfNeutralLoci(int); - int getNumberOfNeutralLoci() const; int incrementAdaptiveTraits(); int getNumberOfAdaptiveTraits() const; @@ -491,7 +489,6 @@ class Species { int genomeSize; bool diploid; bool mutationsOn; - int numberOfNeutralLoci = 0; int numberOfAdaptiveTraits; float recombinationRate; std::set samplePatchList; @@ -566,7 +563,7 @@ class Species { int minSteps; // minimum no. of steps int maxSteps; // maximum total no. of steps int maxStepsYr[maxNbStages][maxNbSexes]; // maximum no. of steps in any one dispersal period - float s0[maxNbStages][maxNbSexes]; // maximum settlement probability + float s0[maxNbStages][maxNbSexes]; // maximum settlement probability float alphaS[maxNbStages][maxNbSexes]; // slope of the settlement reaction norm to density float betaS[maxNbStages][maxNbSexes]; // inflection point of the settlement reaction norm to density From 820e87597c5da9d8e234da95049ef03d6c9368b5 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 11 Apr 2024 16:12:31 +0100 Subject: [PATCH 084/332] relax ploidy assumption in neutral stats --- NeutralStatsManager.cpp | 29 ++++++++++++++++------------- NeutralStatsManager.h | 4 ++-- Population.cpp | 2 +- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 9a6cc75..fcf978c 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -259,7 +259,6 @@ void NeutralStatsManager::calculateHt(Species* pSpecies, Landscape* pLandscape, void NeutralStatsManager::calculateHo2(set const& patchList, const int nbInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape) { vector hetero(nbrLoci, 0); - double nLoci = nbInds * nbrLoci; for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); @@ -292,15 +291,17 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int double sumWeights = 0; double nBar, nC, inverseNbar; unsigned int nbPopulatedPatches = 0; + const int ploidy = pSpecies->isDiploid() ? 2 : 1; + const int totalSampleSize = nbSampledIndsInComm * ploidy; for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop != 0) { - int nbSampledIndsinPop = pPop->sampleSize(); - if (nbSampledIndsinPop > 0) { + int sampleSize = pPop->sampleSize() * ploidy; + if (sampleSize > 0) { nbPopulatedPatches++; - sumWeights += static_cast(nbSampledIndsinPop * nbSampledIndsinPop) / nbSampledIndsInComm; + sumWeights += static_cast(sampleSize * sampleSize) / totalSampleSize; } } } @@ -311,8 +312,8 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int if (nbPopulatedPatches > 1) { // Calculate F stats - nBar = static_cast(nbSampledIndsInComm) / nbPopulatedPatches; // average sample size, cannot be less than 1 - nC = (nbSampledIndsInComm - sumWeights) / nbPopulatedPatches - 1; + nBar = static_cast(totalSampleSize) / nbPopulatedPatches; // average sample size, cannot be less than 1 + nC = (totalSampleSize - sumWeights) / nbPopulatedPatches - 1; double nBarMinusOne = (nBar == 1.0) ? 1.0 : nBar - 1.0; // avoid / 0 if exactly 1 ind per pop inverseNbar = 1.0 / nBarMinusOne; inverseNtotal = 1.0 / nbSampledIndsInComm; @@ -322,8 +323,8 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int double s2Denom = 1.0 / ((nbPopulatedPatches - 1) * nBar); double rTerm = static_cast(nbPopulatedPatches - 1) / nbPopulatedPatches; double hBarFactor = (2 * nBarMinusOne) / (4 * nBar); - double a = 0, b = 0, c = 0, intermediateTerm; + double a = 0, b = 0, c = 0, intermediateTerm; for (int thisLocus = 0; thisLocus < nLoci; ++thisLocus) { for (int allele = 0; allele < nAlleles; ++allele) { @@ -336,7 +337,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int if (pPop != 0) { var = pPop->getAlleleFrequency(thisLocus, allele) - pBar; var *= var; - s2 += var * pPop->sampleSize(); + s2 += var * pPop->sampleSize() * ploidy; hBar += pPop->getHeteroTally(thisLocus, allele); // n_i * h_i } } //end for pop @@ -375,15 +376,17 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i double sumWeights = 0; unsigned int nbExtantPops = 0; + const int ploidy = pSpecies->isDiploid() ? 2 : 1; + const int totSampleSize = nInds * ploidy; for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop != 0) { - int patchSize = pPop->sampleSize(); - if (patchSize > 0) { + int ni = pPop->sampleSize() * ploidy; + if (ni > 0) { nbExtantPops++; - sumWeights += static_cast(patchSize * patchSize) / nInds; + sumWeights += static_cast(ni * ni) / totSampleSize; } } } @@ -473,7 +476,7 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i double SIGA = 0, SIGB = 0, SIGW = 0; if (nbAllelesInComm != nLoci) { // more than one allele per locus - double nc = (nInds - sumWeights) / (nbExtantPops - 1); + double nc = (totSampleSize - sumWeights) / (nbExtantPops - 1); int MSiDenom = nInds == nbExtantPops ? 1 : nInds - nbExtantPops; // avoid /0 if exactly 1 ind per pop for (int i = 0; i < nbAllelesInComm; ++i) { @@ -574,7 +577,7 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd double denominator = 0; double sumWeights = 0; - totSize = nInds * ploidy; // diploid + totSize = nInds * ploidy; // Calculate weight (n_ic) terms for (int i = 0; i < nPatches; ++i) { diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index 1078b5e..09f4dad 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -59,9 +59,9 @@ struct SNPtable { //for population allele tables SNPtable(int nAllele) : alleleTallies(nAllele), alleleFrequencies(nAllele), alleleHeterozygoteTallies(nAllele) {}; - void setFrequencies(int populationSize) { + void setFrequencies(int sampleSize) { for (int i = 0; i < alleleFrequencies.size(); i++) { - alleleFrequencies[i] = populationSize > 0 ? static_cast(alleleTallies[i]) / populationSize : 0.0; + alleleFrequencies[i] = sampleSize > 0 ? static_cast(alleleTallies[i]) / sampleSize : 0.0; } }; diff --git a/Population.cpp b/Population.cpp index bf4468c..1a77a90 100644 --- a/Population.cpp +++ b/Population.cpp @@ -376,7 +376,7 @@ void Population::updatePopSNPtables() { popSNPtables.begin(), popSNPtables.end(), [&](SNPtable& thisLocus) -> void { - thisLocus.setFrequencies(static_cast(sampledInds.size()) * ploidy); // /!\ assumes dipoidy? + thisLocus.setFrequencies(static_cast(sampledInds.size()) * ploidy); }); } } From 92525ae976bbd4c45a8a0c86f200c051fc8f576f Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 11 Apr 2024 17:34:45 +0100 Subject: [PATCH 085/332] refactoring SNP variables and types --- GeneticLoad.cpp | 18 ++++++------- Parameters.h | 11 +------- QTLTrait.cpp | 22 ++++++++-------- SNPTrait.cpp | 67 ++++++++++++++++++++++++------------------------ SNPTrait.h | 3 ++- SpeciesTrait.cpp | 6 ++--- SpeciesTrait.h | 18 ++++++------- 7 files changed, 69 insertions(+), 76 deletions(-) diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index ae5d9df..a3fa3ee 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -16,7 +16,7 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &GeneticLoad::inheritHaploid : &GeneticLoad::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); - map mutationParameters = pSpeciesTrait->getMutationParameters(); + map mutationParameters = pSpeciesTrait->getMutationParameters(); switch (mutationDistribution) { case UNIFORM: @@ -35,7 +35,7 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) if (mutationParameters.count(MEAN) != 1) cout << endl << ("Error:: genetic load mutation distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); - if (mutationParameters.count(SDEV) != 1) + if (mutationParameters.count(SD) != 1) cout << endl << ("Error:: genetic load mutation distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); break; @@ -65,7 +65,7 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) } DistributionType dominanceDistribution = pSpeciesTrait->getDominanceDistribution(); - map dominanceParameters = pSpeciesTrait->getDominanceParameters(); + map dominanceParameters = pSpeciesTrait->getDominanceParameters(); switch (dominanceDistribution) { case UNIFORM: @@ -84,7 +84,7 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) if (dominanceParameters.count(MEAN) != 1) cout << endl << ("Error:: genetic load dominance distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); - if (dominanceParameters.count(SDEV) != 1) + if (dominanceParameters.count(SD) != 1) cout << endl << ("Error:: genetic load dominance distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); break; @@ -119,7 +119,7 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) } DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); - map initialParameters = pSpeciesTrait->getInitialParameters(); + map initialParameters = pSpeciesTrait->getInitialParameters(); } @@ -180,7 +180,7 @@ void GeneticLoad::mutate() float GeneticLoad::drawDominance(float selCoef) { DistributionType dominanceDistribution = pSpeciesTrait->getDominanceDistribution(); - map dominanceParameters = pSpeciesTrait->getDominanceParameters(); + map dominanceParameters = pSpeciesTrait->getDominanceParameters(); float h = 1.0; //default dominance is 1 @@ -195,7 +195,7 @@ float GeneticLoad::drawDominance(float selCoef) { case NORMAL: { const float mean = dominanceParameters.find(MEAN)->second; - const float sd = dominanceParameters.find(SDEV)->second; + const float sd = dominanceParameters.find(SD)->second; h = static_cast(pRandom->Normal(mean, sd)); break; } @@ -238,7 +238,7 @@ float GeneticLoad::drawDominance(float selCoef) { float GeneticLoad::drawSelectionCoef() { DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); - map mutationParameters = pSpeciesTrait->getMutationParameters(); + map mutationParameters = pSpeciesTrait->getMutationParameters(); float s = 0.0; //default selection coefficient is 0 @@ -254,7 +254,7 @@ float GeneticLoad::drawSelectionCoef() { case NORMAL: { const float mean = mutationParameters.find(MEAN)->second; - const float sd = mutationParameters.find(SDEV)->second; + const float sd = mutationParameters.find(SD)->second; s = static_cast(pRandom->Normal(mean, sd)); break; diff --git a/Parameters.h b/Parameters.h index e6f63e1..fe55111 100644 --- a/Parameters.h +++ b/Parameters.h @@ -139,17 +139,8 @@ enum TraitType { INVALID_TRAIT // error }; -typedef std::string parameter_t; - -constexpr auto MEAN = "mean"; -constexpr auto SDEV = "sd"; -constexpr auto MIN = "min"; -constexpr auto MAX = "max"; -constexpr auto SHAPE = "shape"; -constexpr auto SCALE = "scale"; - +enum GenParamType { MEAN, SD, MIN, MAX, SHAPE, SCALE, INVALID }; enum DistributionType { UNIFORM, NORMAL, GAMMA, NEGEXP, SCALED, KAM, SSM, NONE }; - enum ExpressionType { AVERAGE, ADDITIVE, NOTEXPR, MULTIPLICATIVE }; /** Param's types **/ diff --git a/QTLTrait.cpp b/QTLTrait.cpp index 8a1be32..7bf5299 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -15,7 +15,7 @@ QTLTrait::QTLTrait(SpeciesTrait* P) _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &QTLTrait::inheritHaploid : &QTLTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); - map mutationParameters = pSpeciesTrait->getMutationParameters(); + map mutationParameters = pSpeciesTrait->getMutationParameters(); switch (mutationDistribution) { case UNIFORM: @@ -34,7 +34,7 @@ QTLTrait::QTLTrait(SpeciesTrait* P) if (mutationParameters.count(MEAN) != 1) cout << endl << ("Error:: qtl mutation distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); - if (mutationParameters.count(SDEV) != 1) + if (mutationParameters.count(SD) != 1) cout << endl << ("Error::qtl mutation distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); _mutate_func_ptr = &QTLTrait::mutateNormal; @@ -50,7 +50,7 @@ QTLTrait::QTLTrait(SpeciesTrait* P) } DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); - map initialParameters = pSpeciesTrait->getInitialParameters(); + map initialParameters = pSpeciesTrait->getInitialParameters(); switch (initialDistribution) { case UNIFORM: @@ -72,11 +72,11 @@ QTLTrait::QTLTrait(SpeciesTrait* P) if (initialParameters.count(MEAN) != 1) cout << endl << ("Error:: initial normal qtl distribution parameter must contain mean value (e.g. mean= ) \n"); - if (initialParameters.count(SDEV) != 1) + if (initialParameters.count(SD) != 1) cout << endl << ("Error:: initial normal qtl distribution parameter must contain sdev value (e.g. sdev= ) \n"); float mean = initialParameters.find(MEAN)->second; - float sd = initialParameters.find(SDEV)->second; + float sd = initialParameters.find(SD)->second; initialiseNormal(mean, sd); break; @@ -130,7 +130,7 @@ void QTLTrait::mutateUniform() auto rng = pRandom->getRNG(); - map mutationParameters = pSpeciesTrait->getMutationParameters(); + map mutationParameters = pSpeciesTrait->getMutationParameters(); float maxD = mutationParameters.find(MAX)->second; float minD = mutationParameters.find(MIN)->second; @@ -168,9 +168,9 @@ void QTLTrait::mutateNormal() auto rng = pRandom->getRNG(); - const map mutationParameters = pSpeciesTrait->getMutationParameters(); + const map mutationParameters = pSpeciesTrait->getMutationParameters(); const float mean = mutationParameters.find(MEAN)->second; - const float sd = mutationParameters.find(SDEV)->second; + const float sd = mutationParameters.find(SD)->second; for (int p = 0; p < ploidy; p++) { @@ -253,7 +253,7 @@ void QTLTrait::inheritHaploid(sex_t chromosome, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); - map initialParameters = pSpeciesTrait->getInitialParameters(); + map initialParameters = pSpeciesTrait->getInitialParameters(); switch (initialDistribution) { case UNIFORM: @@ -276,11 +276,11 @@ void QTLTrait::inheritInitialParameters(sex_t whichChromosome, mapsecond; - float sd = initialParameters.find(SDEV)->second; + float sd = initialParameters.find(SD)->second; initialiseNormal(mean, sd); diff --git a/SNPTrait.cpp b/SNPTrait.cpp index 4e5d037..caf009c 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -8,7 +8,7 @@ SNPTrait::SNPTrait(SpeciesTrait* P) pProtoTrait = P; DistributionType mutationDistribution = pProtoTrait->getMutationDistribution(); - map mutationParameters = pProtoTrait->getMutationParameters(); + map mutationParameters = pProtoTrait->getMutationParameters(); _inherit_func_ptr = (pProtoTrait->getPloidy() == 1) ? &SNPTrait::inheritHaploid : &SNPTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance @@ -27,11 +27,11 @@ SNPTrait::SNPTrait(SpeciesTrait* P) if (wildType == -999) wildType = (int)mutationParameters.find(MAX)->second - 1; - if (wildType > maxSNPAlleles - 1) - cout << endl << "Error:: max number of alleles cannot exceed " << maxSNPAlleles << ".\n"; + if (wildType > SNPvalUpperBound) + cout << endl << "Error:: max number of alleles cannot exceed " << SNPvalUpperBound << ".\n"; DistributionType initialDistribution = pProtoTrait->getInitialDistribution(); - map initialParameters = pProtoTrait->getInitialParameters(); + map initialParameters = pProtoTrait->getInitialParameters(); if (mutationDistribution == SSM && initialDistribution != UNIFORM) cout << endl << ("Error:: If using SSM mutation model must initialise genome with alleles (microsats) \n"); @@ -40,15 +40,14 @@ SNPTrait::SNPTrait(SpeciesTrait* P) case UNIFORM: { if (initialParameters.count(MAX) != 1) - cout << endl << "Error:: initial SNP/Microsat distribution parameter must contain one max value if set to UNIFORM (e.g. max= ), max cannot exceed " << maxSNPAlleles << "\n"; + cout << endl << "Error:: initial SNP/Microsat distribution parameter must contain one max value if set to UNIFORM (e.g. max= ), max cannot exceed " << SNPvalUpperBound << "\n"; - float maxD = initialParameters.find(MAX)->second; - if (maxD > maxSNPAlleles) { - cout << endl << "Warning:: initial SNP/Microsat distribution parameter max cannot exceed " << maxSNPAlleles << ", resetting to " << maxSNPAlleles << "\n"; - - maxD = maxSNPAlleles; //reserve 255 for wildtype + float maxSNPval = initialParameters.find(MAX)->second; + if (maxSNPval > SNPvalUpperBound) { + cout << endl << "Warning:: initial SNP/Microsat distribution parameter max cannot exceed " << SNPvalUpperBound << ", resetting to " << SNPvalUpperBound << "\n"; + maxSNPval = SNPvalUpperBound; //reserve 255 for wildtype } - initialiseFull(maxD); + initialiseFull(maxSNPval); break; } @@ -90,14 +89,14 @@ void SNPTrait::mutate_KAM() auto rng = pRandom->getRNG(); unsigned char mut; - map mutationParameters = pProtoTrait->getMutationParameters(); + map mutationParameters = pProtoTrait->getMutationParameters(); - int maxD = (int)mutationParameters.find(MAX)->second; + int maxSNPval = (int)mutationParameters.find(MAX)->second; - if (maxD > maxSNPAlleles) maxD = maxSNPAlleles; //reserve max value -1 for wildtype + if (maxSNPval > SNPvalUpperBound) maxSNPval = SNPvalUpperBound; //reserve max value for wildtype - for (int p = 0; p < ploidy; p++) { + for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); if (NbMut > positionsSize) NbMut = positionsSize; @@ -109,22 +108,22 @@ void SNPTrait::mutate_KAM() for (int m : mutationPositions) { - mut = (unsigned char)pRandom->IRandom(0, maxD - 1); // draw new mutation, could draw wildtype + mut = (unsigned char)pRandom->IRandom(0, maxSNPval); // draw new mutation, could draw wildtype auto it = genes.find(m); // find if position in map already has mutations there if (it == genes.end()) { // not found so create new entry in map with wildtype as char default vector allelePair(2, wildType); - allelePair[p] = mut; //put new mutation value in + allelePair[whichChromosome] = mut; //put new mutation value in genes.insert(make_pair(m, allelePair)); } else { //position found, already mutations there - auto currentChar = it->second[p]; //current mutation + auto currentChar = it->second[whichChromosome]; //current mutation do { - mut = (unsigned char)pRandom->IRandom(0, maxD - 1); //make sure new value differs from old , could be a problem here with infinite loops + mut = (unsigned char)pRandom->IRandom(0, maxSNPval); //make sure new value differs from old , could be a problem here with infinite loops } while (mut == currentChar); - it->second[p] = mut; //overwrite with new value + it->second[whichChromosome] = mut; //overwrite with new value } } } @@ -143,12 +142,12 @@ void SNPTrait::mutate_SSM() const float mutationRate = pProtoTrait->getMutationRate(); auto rng = pRandom->getRNG(); - map mutationParameters = pProtoTrait->getMutationParameters(); + map mutationParameters = pProtoTrait->getMutationParameters(); - int maxD = (int)mutationParameters.find(MAX)->second; - if (maxD > maxSNPAlleles) maxD = maxSNPAlleles; //reserved max value for wildtype + int maxSNPval = (int)mutationParameters.find(MAX)->second; + if (maxSNPval > SNPvalUpperBound) maxSNPval = SNPvalUpperBound; //reserved max value for wildtype - for (int p = 0; p < ploidy; p++) { + for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); @@ -160,14 +159,16 @@ void SNPTrait::mutate_SSM() for (int m : mutationPositions) { int mutateForward = pRandom->Bernoulli(0.5); auto it = genes.find(m); - auto currentAllele = it->second[p];//current - //alleles values are from 0 to maxD - 1 - if (mutateForward && currentAllele < maxD - 1) - it->second[p] += 1; //one step to the right - else if (currentAllele > 0) // !direction || all==_allele_num - it->second[p] -= 1; //one step to the left - else //!direction && all == 0 - it->second[p] += 1; + if (it == genes.end()) + throw runtime_error(""); + + auto currentAllele = it->second[whichChromosome]; + if (mutateForward == 1 && currentAllele < maxSNPval) + it->second[whichChromosome] += 1; // shift one char to the right + else if (currentAllele > 0) + it->second[whichChromosome] -= 1; // shift one char to the left + else // current allele is 0 and mutate backwards + it->second[whichChromosome] += 1; } } } @@ -244,7 +245,7 @@ void SNPTrait::initialiseFull(int maxAlleleVal) vector allelePair; for (int i = 0; i < ploidy; i++) { - auto alleleVal = (unsigned char)pRandom->IRandom(0, maxAlleleVal - 1); // allele values span 0 - max (255 ceiling) inclusive, max == wildtype + auto alleleVal = (unsigned char)pRandom->IRandom(0, maxAlleleVal); // allele values span 0 - max (255 ceiling) inclusive, max == wildtype allelePair.emplace_back(alleleVal); } genes.insert(make_pair(position, allelePair)); diff --git a/SNPTrait.h b/SNPTrait.h index 740224c..59e7b7d 100644 --- a/SNPTrait.h +++ b/SNPTrait.h @@ -15,7 +15,8 @@ class SNPTrait : public TTrait { private: inline static int wildType = -999; - const int maxSNPAlleles = UCHAR_MAX + 1; // allele is char, can take value 0-255 + const int SNPvalUpperBound = UCHAR_MAX; // i.e. 256 + // allele is char, can take value 0-255 SpeciesTrait* pProtoTrait; diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index dd1a45b..08588c1 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -5,10 +5,10 @@ SpeciesTrait::SpeciesTrait( const TraitType& traitType, const sex_t& sx, const set& pos, const ExpressionType& expr, - const DistributionType& initDist, const map initParams, - const DistributionType& dominanceDist, const map dominanceParams, + const DistributionType& initDist, const map initParams, + const DistributionType& dominanceDist, const map dominanceParams, bool isInherited, const float& mutRate, - const DistributionType& mutationDist, const map mutationParams, + const DistributionType& mutationDist, const map mutationParams, Species* pSpecies) : sex{sx}, positions{pos}, diff --git a/SpeciesTrait.h b/SpeciesTrait.h index 2880686..14356e2 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -20,12 +20,12 @@ class SpeciesTrait { set positions; ExpressionType expressionType; DistributionType initialDistribution; - map initialParameters; + map initialParameters; DistributionType dominanceDistribution; - map dominanceParameters; + map dominanceParameters; bool inherited; DistributionType mutationDistribution; - map mutationParameters; + map mutationParameters; public: @@ -35,13 +35,13 @@ class SpeciesTrait { const set& pos, const ExpressionType& expr, const DistributionType& initDist, - const map initParams, + const map initParams, const DistributionType& dominanceDist, - const map dominanceParams, + const map dominanceParams, bool isInherited, const float& mutationRate, const DistributionType& mutationDist, - const map mutationParams, + const map mutationParams, Species* pSpecies ); @@ -53,11 +53,11 @@ class SpeciesTrait { int getPositionsSize() const { return static_cast(positions.size()); } bool isInherited() const { return inherited; } DistributionType getMutationDistribution() const { return mutationDistribution; }; - map getMutationParameters() const { return mutationParameters; }; + map getMutationParameters() const { return mutationParameters; }; DistributionType getDominanceDistribution() const { return dominanceDistribution; }; - map getDominanceParameters() const { return dominanceParameters; }; + map getDominanceParameters() const { return dominanceParameters; }; DistributionType getInitialDistribution() const { return initialDistribution; }; - map getInitialParameters() const { return initialParameters; }; + map getInitialParameters() const { return initialParameters; }; ExpressionType getExpressionType() const { return expressionType; }; }; #endif \ No newline at end of file From 1263801c675699e6f7edc43f4fbbfe0afd009f49 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 11 Apr 2024 17:41:26 +0100 Subject: [PATCH 086/332] snp mutations don't add new loci --- SNPTrait.cpp | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/SNPTrait.cpp b/SNPTrait.cpp index caf009c..92f4b08 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -109,22 +109,17 @@ void SNPTrait::mutate_KAM() for (int m : mutationPositions) { mut = (unsigned char)pRandom->IRandom(0, maxSNPval); // draw new mutation, could draw wildtype - auto it = genes.find(m); // find if position in map already has mutations there - if (it == genes.end()) { // not found so create new entry in map with wildtype as char default - vector allelePair(2, wildType); - allelePair[whichChromosome] = mut; //put new mutation value in - genes.insert(make_pair(m, allelePair)); - } - else { //position found, already mutations there + auto it = genes.find(m); + if (it == genes.end()) + throw runtime_error("Locus selected for mutation doesn't exist."); - auto currentChar = it->second[whichChromosome]; //current mutation - do { - mut = (unsigned char)pRandom->IRandom(0, maxSNPval); //make sure new value differs from old , could be a problem here with infinite loops - } while (mut == currentChar); + auto currentChar = it->second[whichChromosome]; //current mutation + do { + mut = (unsigned char)pRandom->IRandom(0, maxSNPval); //make sure new value differs from old , could be a problem here with infinite loops + } while (mut == currentChar); - it->second[whichChromosome] = mut; //overwrite with new value - } + it->second[whichChromosome] = mut; //overwrite with new value } } } @@ -160,7 +155,7 @@ void SNPTrait::mutate_SSM() int mutateForward = pRandom->Bernoulli(0.5); auto it = genes.find(m); if (it == genes.end()) - throw runtime_error(""); + throw runtime_error("Locus selected for mutation doesn't exist."); auto currentAllele = it->second[whichChromosome]; if (mutateForward == 1 && currentAllele < maxSNPval) From d8b4c97049e43bc1e919016ea0e3d8fc80792274 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 11 Apr 2024 18:00:20 +0100 Subject: [PATCH 087/332] more refactoring for clarification --- Community.cpp | 2 +- GeneticLoad.cpp | 4 ++-- Population.cpp | 4 ++-- QTLTrait.cpp | 16 ++++++++-------- SNPTrait.cpp | 45 ++++++++++++++++++++++----------------------- SNPTrait.h | 8 ++++---- SpeciesTrait.cpp | 2 +- SpeciesTrait.h | 6 +++--- 8 files changed, 43 insertions(+), 44 deletions(-) diff --git a/Community.cpp b/Community.cpp index 942a54c..74c9355 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1777,7 +1777,7 @@ void Community::writeWCFstatFile(int rep, int yr, int gen) { void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList) { - const set positions = pSpecies->getSpTrait(SNP)->getPositions(); + const set positions = pSpecies->getSpTrait(SNP)->getGenePositions(); int thisLocus = 0; for (int position : positions) { diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index a3fa3ee..3a88e7f 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -136,7 +136,7 @@ GeneticLoad::GeneticLoad(const GeneticLoad& T) : pSpeciesTrait(T.pSpeciesTrait), void GeneticLoad::mutate() { const int positionsSize = pSpeciesTrait->getPositionsSize(); - const auto& positions = pSpeciesTrait->getPositions(); + const auto& genePositions = pSpeciesTrait->getGenePositions(); const short ploidy = pSpeciesTrait->getPloidy(); const float mutationRate = pSpeciesTrait->getMutationRate(); @@ -150,7 +150,7 @@ void GeneticLoad::mutate() if (NbMut > 0) { vector mutationPositions; // Draw which positions mutate - sample(positions.begin(), positions.end(), std::back_inserter(mutationPositions), + sample(genePositions.begin(), genePositions.end(), std::back_inserter(mutationPositions), NbMut, rng); for (int m : mutationPositions) { diff --git a/Population.cpp b/Population.cpp index 1a77a90..ee9d172 100644 --- a/Population.cpp +++ b/Population.cpp @@ -334,7 +334,7 @@ void Population::updatePopSNPtables() { const int nLoci = pSpecies->getNPositionsForTrait(SNP); const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; - const auto& positions = pSpecies->getSpTrait(SNP)->getPositions(); + const auto& positions = pSpecies->getSpTrait(SNP)->getGenePositions(); const int ploidy = pSpecies->isDiploid() ? 2 : 1; if (popSNPtables.size() != 0) @@ -411,7 +411,7 @@ int Population::countHeterozygoteLoci() { // ---------------------------------------------------------------------------------------- vector Population::countLociHeterozyotes() { - const auto& positions = pSpecies->getSpTrait(SNP)->getPositions(); + const auto& positions = pSpecies->getSpTrait(SNP)->getGenePositions(); vector hetero(positions.size(), 0); for (Individual* ind : sampledInds) { diff --git a/QTLTrait.cpp b/QTLTrait.cpp index 7bf5299..a1dcff0 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -124,7 +124,7 @@ QTLTrait::QTLTrait(const QTLTrait& T) : pSpeciesTrait(T.pSpeciesTrait), _mutate_ void QTLTrait::mutateUniform() { const int positionsSize = pSpeciesTrait->getPositionsSize(); - const auto& positions = pSpeciesTrait->getPositions(); + const auto& genePositions = pSpeciesTrait->getGenePositions(); const short ploidy = pSpeciesTrait->getPloidy(); const float mutationRate = pSpeciesTrait->getMutationRate(); @@ -140,7 +140,7 @@ void QTLTrait::mutateUniform() if (NbMut > 0) { vector mutationPositions; - sample(positions.begin(), positions.end(), std::back_inserter(mutationPositions), + sample(genePositions.begin(), genePositions.end(), std::back_inserter(mutationPositions), NbMut, rng); for (int m : mutationPositions) { @@ -161,7 +161,7 @@ void QTLTrait::mutateNormal() { const int positionsSize = pSpeciesTrait->getPositionsSize(); - const auto& positions = pSpeciesTrait->getPositions(); + const auto& genePositions = pSpeciesTrait->getGenePositions(); const short ploidy = pSpeciesTrait->getPloidy(); const float mutationRate = pSpeciesTrait->getMutationRate(); @@ -178,7 +178,7 @@ void QTLTrait::mutateNormal() if (NbMut > 0) { vector mutationPositions; - sample(positions.begin(), positions.end(), std::back_inserter(mutationPositions), + sample(genePositions.begin(), genePositions.end(), std::back_inserter(mutationPositions), NbMut, rng); for (int m : mutationPositions) { @@ -303,10 +303,10 @@ void QTLTrait::inheritInitialParameters(sex_t whichChromosome, map positions = pSpeciesTrait->getPositions(); + const set genePositions = pSpeciesTrait->getGenePositions(); short ploidy = pSpeciesTrait->getPloidy(); - for (auto position : positions) { + for (auto position : genePositions) { vector> newAllelePair; for (int i = 0; i < ploidy; i++) { float alleleVal = pRandom->Normal(mean, sd); @@ -318,10 +318,10 @@ void QTLTrait::initialiseNormal(float mean, float sd) { void QTLTrait::initialiseUniform(float min, float max) { - const set positions = pSpeciesTrait->getPositions(); + const set genePositions = pSpeciesTrait->getGenePositions(); short ploidy = pSpeciesTrait->getPloidy(); - for (auto position : positions) { + for (auto position : genePositions) { vector> newAllelePair; for (int i = 0; i < ploidy; i++) { float alleleVal = pRandom->FRandom(min, max); diff --git a/SNPTrait.cpp b/SNPTrait.cpp index 92f4b08..8b9da27 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -5,12 +5,12 @@ // ---------------------------------------------------------------------------------------- SNPTrait::SNPTrait(SpeciesTrait* P) { - pProtoTrait = P; + pSpeciesTrait = P; - DistributionType mutationDistribution = pProtoTrait->getMutationDistribution(); - map mutationParameters = pProtoTrait->getMutationParameters(); + DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); + map mutationParameters = pSpeciesTrait->getMutationParameters(); - _inherit_func_ptr = (pProtoTrait->getPloidy() == 1) ? &SNPTrait::inheritHaploid : &SNPTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance + _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &SNPTrait::inheritHaploid : &SNPTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance if (mutationDistribution == SSM) _mutate_func_ptr = &SNPTrait::mutate_SSM; @@ -30,8 +30,8 @@ SNPTrait::SNPTrait(SpeciesTrait* P) if (wildType > SNPvalUpperBound) cout << endl << "Error:: max number of alleles cannot exceed " << SNPvalUpperBound << ".\n"; - DistributionType initialDistribution = pProtoTrait->getInitialDistribution(); - map initialParameters = pProtoTrait->getInitialParameters(); + DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); + map initialParameters = pSpeciesTrait->getInitialParameters(); if (mutationDistribution == SSM && initialDistribution != UNIFORM) cout << endl << ("Error:: If using SSM mutation model must initialise genome with alleles (microsats) \n"); @@ -68,7 +68,7 @@ SNPTrait::SNPTrait(SpeciesTrait* P) // ---------------------------------------------------------------------------------------- SNPTrait::SNPTrait(const SNPTrait& T) : - pProtoTrait(T.pProtoTrait), _mutate_func_ptr(T._mutate_func_ptr), _inherit_func_ptr(T._inherit_func_ptr) { + pSpeciesTrait(T.pSpeciesTrait), _mutate_func_ptr(T._mutate_func_ptr), _inherit_func_ptr(T._inherit_func_ptr) { } @@ -82,15 +82,14 @@ SNPTrait::SNPTrait(const SNPTrait& T) : // ---------------------------------------------------------------------------------------- void SNPTrait::mutate_KAM() { - const int positionsSize = pProtoTrait->getPositionsSize(); - const auto& positions = pProtoTrait->getPositions(); - const short ploidy = pProtoTrait->getPloidy(); - const float mutationRate = pProtoTrait->getMutationRate(); + const int positionsSize = pSpeciesTrait->getPositionsSize(); + const auto& genePositions = pSpeciesTrait->getGenePositions(); + const short ploidy = pSpeciesTrait->getPloidy(); + const float mutationRate = pSpeciesTrait->getMutationRate(); auto rng = pRandom->getRNG(); unsigned char mut; - map mutationParameters = pProtoTrait->getMutationParameters(); - + map mutationParameters = pSpeciesTrait->getMutationParameters(); int maxSNPval = (int)mutationParameters.find(MAX)->second; @@ -103,7 +102,7 @@ void SNPTrait::mutate_KAM() if (NbMut > 0) { vector mutationPositions; - sample(positions.begin(), positions.end(), std::back_inserter(mutationPositions), + sample(genePositions.begin(), genePositions.end(), std::back_inserter(mutationPositions), NbMut, rng); // without replacement for (int m : mutationPositions) { @@ -131,13 +130,13 @@ void SNPTrait::mutate_KAM() // ---------------------------------------------------------------------------------------- void SNPTrait::mutate_SSM() { - const int positionsSize = pProtoTrait->getPositionsSize(); - const auto& positions = pProtoTrait->getPositions(); - const short ploidy = pProtoTrait->getPloidy(); - const float mutationRate = pProtoTrait->getMutationRate(); + const int positionsSize = pSpeciesTrait->getPositionsSize(); + const auto& genePositions = pSpeciesTrait->getGenePositions(); + const short ploidy = pSpeciesTrait->getPloidy(); + const float mutationRate = pSpeciesTrait->getMutationRate(); auto rng = pRandom->getRNG(); - map mutationParameters = pProtoTrait->getMutationParameters(); + map mutationParameters = pSpeciesTrait->getMutationParameters(); int maxSNPval = (int)mutationParameters.find(MAX)->second; if (maxSNPval > SNPvalUpperBound) maxSNPval = SNPvalUpperBound; //reserved max value for wildtype @@ -148,7 +147,7 @@ void SNPTrait::mutate_SSM() if (NbMut > 0) { vector mutationPositions; - sample(positions.begin(), positions.end(), std::back_inserter(mutationPositions), + sample(genePositions.begin(), genePositions.end(), std::back_inserter(mutationPositions), NbMut, rng); for (int m : mutationPositions) { @@ -233,10 +232,10 @@ void SNPTrait::inheritHaploid(sex_t chromosome, map> void SNPTrait::initialiseFull(int maxAlleleVal) { - const auto& positions = pProtoTrait->getPositions(); - short ploidy = pProtoTrait->getPloidy(); + const auto& genePositions = pSpeciesTrait->getGenePositions(); + short ploidy = pSpeciesTrait->getPloidy(); - for (auto position : positions) { + for (auto position : genePositions) { vector allelePair; for (int i = 0; i < ploidy; i++) { diff --git a/SNPTrait.h b/SNPTrait.h index 59e7b7d..d841eac 100644 --- a/SNPTrait.h +++ b/SNPTrait.h @@ -18,7 +18,7 @@ class SNPTrait : public TTrait { const int SNPvalUpperBound = UCHAR_MAX; // i.e. 256 // allele is char, can take value 0-255 - SpeciesTrait* pProtoTrait; + SpeciesTrait* pSpeciesTrait; map> genes; //position > @@ -47,9 +47,9 @@ class SNPTrait : public TTrait { virtual void inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) override; virtual void mutate() override { (this->*_mutate_func_ptr) (); } - virtual int getNLoci() const override { return pProtoTrait->getPositionsSize(); } - float getMutationRate() const override { return pProtoTrait->getMutationRate(); } - bool isInherited() const override { return pProtoTrait->isInherited(); } + virtual int getNLoci() const override { return pSpeciesTrait->getPositionsSize(); } + float getMutationRate() const override { return pSpeciesTrait->getMutationRate(); } + bool isInherited() const override { return pSpeciesTrait->isInherited(); } map>& getGenes() { return genes; } //returning reference, reciever must be const virtual float getAlleleValueAtLocus(short chromosome, int position) const override; diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 08588c1..a1b1527 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -11,7 +11,7 @@ SpeciesTrait::SpeciesTrait( const DistributionType& mutationDist, const map mutationParams, Species* pSpecies) : sex{sx}, - positions{pos}, + genePositions{pos}, expressionType{expr}, initialDistribution{initDist}, initialParameters{initParams}, diff --git a/SpeciesTrait.h b/SpeciesTrait.h index 14356e2..090012e 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -17,7 +17,7 @@ class SpeciesTrait { inline static int ploidy = 0; float mutationRate; sex_t sex; - set positions; + set genePositions; ExpressionType expressionType; DistributionType initialDistribution; map initialParameters; @@ -49,8 +49,8 @@ class SpeciesTrait { sex_t getSex() const { return sex; } float getMutationRate() const { return mutationRate; } short getPloidy() const { return ploidy; } - set& getPositions() { return positions; } // returning by reference, make sure receiver is const - int getPositionsSize() const { return static_cast(positions.size()); } + set& getGenePositions() { return genePositions; } // returning by reference, make sure receiver is const + int getPositionsSize() const { return static_cast(genePositions.size()); } bool isInherited() const { return inherited; } DistributionType getMutationDistribution() const { return mutationDistribution; }; map getMutationParameters() const { return mutationParameters; }; From 61f4d487389a18f6171b988fca7ad66e539abae1 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 12 Apr 2024 16:38:21 +0100 Subject: [PATCH 088/332] inheritance mechanism more explicit --- Community.cpp | 13 ------------- GeneticLoad.cpp | 36 ++++++++++++++++++------------------ GeneticLoad.h | 6 +++--- Individual.cpp | 8 +++++--- Model.cpp | 20 ++++++++++++++++++++ QTLTrait.cpp | 22 ++++++++++------------ QTLTrait.h | 10 ++++------ SNPTrait.cpp | 14 ++++++++------ SNPTrait.h | 7 +++---- SubCommunity.cpp | 1 - 10 files changed, 71 insertions(+), 66 deletions(-) diff --git a/Community.cpp b/Community.cpp index 74c9355..12d07ba 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1270,10 +1270,6 @@ void Community::outTraits(traitCanvas tcanv, Species* pSpecies, void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int y, traitsums ts) { - //simParams sim = paramsSim->getSim(); - //simView v = paramsSim->getViews(); - //landData land = pLandscape->getLandData(); - //landOrigin origin = pLandscape->getOrigin(); emigRules emig = pSpecies->getEmigRules(); transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); @@ -1284,7 +1280,6 @@ void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int int popsize = ts.ninds[0] + ts.ninds[1]; outtraitsrows << rep << "\t" << yr << "\t" << gen << "\t" << y; - // << "\t" << y*land.resol + origin.minNorth; if ((emig.indVar && emig.sexDep) || (trfr.indVar && trfr.sexDep)) outtraitsrows << "\t" << ts.ninds[0] << "\t" << ts.ninds[1]; else @@ -1349,14 +1344,6 @@ void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int if (popsize > 1) sd = ts.ssqRho[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - // if (ts.ninds[0] > 0) mn = ts.sumStepL[0]/(double)ts.ninds[0]; else mn = 0.0; - // if (ts.ninds[0] > 1) sd = ts.ssqStepL[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; - // if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - // outtraitsrows << "\t" << mn << "\t" << sd; - // if (ts.ninds[0] > 0) mn = ts.sumRho[0]/(double)ts.ninds[0]; else mn = 0.0; - // if (ts.ninds[0] > 1) sd = ts.ssqRho[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; - // if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - // outtraitsrows << "\t" << mn << "\t" << sd; } } else { // dispersal kernel diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index 3a88e7f..a6c0012 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -146,6 +146,7 @@ void GeneticLoad::mutate() // Determine nb of mutations unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); + if (NbMut > positionsSize) NbMut = positionsSize; if (NbMut > 0) { vector mutationPositions; @@ -158,14 +159,16 @@ void GeneticLoad::mutate() float newSelectionCoef = drawSelectionCoef(); float newDominanceCoef = drawDominance(newSelectionCoef); - auto it = genes.find(m); //find if position in map already has mutations there - - if (it == genes.end()) { // not found so create new entry in map with wildtype as char default + auto it = genes.find(m); + if (it == genes.end()) { + /* vector> newAllelePair(2); newAllelePair[p] = make_shared(newSelectionCoef, newDominanceCoef); //put new mutation value in genes.insert(make_pair(m, newAllelePair)); + */ + throw runtime_error("Locus sampled for mutation doesn't exist."); } - else { //position found, already mutations there + else { it->second[p] = make_shared(newSelectionCoef, newDominanceCoef); } } @@ -287,53 +290,50 @@ float GeneticLoad::drawSelectionCoef() { // ---------------------------------------------------------------------------------------- -void GeneticLoad::inherit(TTrait* parentTrait, set const& recomPositions, sex_t whichChromosome, int startingChromosome) +void GeneticLoad::inherit(const bool& fromMother, TTrait* parentTrait, set const& recomPositions, int startingChromosome) { auto parentCast = dynamic_cast (parentTrait); //horrible const auto& parent_seq = parentCast->getGenes(); if (parent_seq.size() > 0) //else nothing to inherit - (this->*_inherit_func_ptr) (whichChromosome, parent_seq, recomPositions, startingChromosome); + (this->*_inherit_func_ptr) (fromMother, parent_seq, recomPositions, startingChromosome); } -void GeneticLoad::inheritDiploid(sex_t whichChromosome, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { +void GeneticLoad::inheritDiploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { auto it = recomPositions.lower_bound(parentGenes.begin()->first); - int nextBreakpoint = *it; - auto distance = std::distance(recomPositions.begin(), it); if (distance % 2 != 0) parentChromosome = 1 - parentChromosome; // switch to the other one // use 1-parentChromosome, or switch to a sex_t ? for (auto const& [locus, allelePair] : parentGenes) { - while (locus > nextBreakpoint) { std::advance(it, 1); nextBreakpoint = *it; parentChromosome = 1 - parentChromosome; // switch to the other one } - if (locus <= nextBreakpoint) { auto& allele = allelePair[parentChromosome]; + auto it = genes.find(locus); if (it == genes.end()) { // locus does not exist yet, initiate it + if (!fromMother) throw runtime_error("Father-inherited locus does not exist."); vector> newAllelePair(2); - newAllelePair[whichChromosome] = allele; + newAllelePair[sex_t::FEM] = allele; genes.insert(make_pair(locus, newAllelePair)); - } - else { - // locus already exists - // set corresponding allele - it->second[whichChromosome] = allele; + } + else { // father, locus already exists + if (fromMother) throw runtime_error("Mother-inherited locus already exists."); + it->second[sex_t::MAL] = allele; } } } } -void GeneticLoad::inheritHaploid(sex_t chromosome, map>> const& parentGenes, set const& recomPositions, int parentChromosome) +void GeneticLoad::inheritHaploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { genes = parentGenes; } diff --git a/GeneticLoad.h b/GeneticLoad.h index 817f22d..33e4c26 100644 --- a/GeneticLoad.h +++ b/GeneticLoad.h @@ -25,8 +25,8 @@ class GeneticLoad : public TTrait { void (GeneticLoad::* _inherit_func_ptr) (sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); //float (AdaptiveTrait::* _express_func_ptr) (void); - void inheritDiploid(sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); - void inheritHaploid(sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); + void inheritDiploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); + void inheritHaploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); float drawDominance(float); float drawSelectionCoef(); @@ -42,7 +42,7 @@ class GeneticLoad : public TTrait { virtual unique_ptr clone() const override { return std::make_unique(*this); } - virtual void inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) override; + virtual void inherit(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; virtual void mutate() override; diff --git a/Individual.cpp b/Individual.cpp index bcf93dc..92c4688 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -171,15 +171,17 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi const auto fatherTrait = father->getTrait(trait); auto newTrait = motherTrait->clone(); // shallow copy, pointer to proto trait initialised and empty sequence - newTrait->inherit(motherTrait, maternalRecomPositions, FEM, maternalStartingChromosome); + newTrait->inherit(true, motherTrait, maternalRecomPositions, maternalStartingChromosome); if (newTrait->isInherited()) { - newTrait->inherit(fatherTrait, paternalRecomPositions, MAL, paternalStartingChromosome); + // Inherit father trait values + newTrait->inherit(false, fatherTrait, paternalRecomPositions, paternalStartingChromosome); if (newTrait->getMutationRate() > 0 && pSpecies->areMutationsOn()) newTrait->mutate(); } if (trait == GENETIC_LOAD1 || trait == GENETIC_LOAD2 || trait == GENETIC_LOAD3 || trait == GENETIC_LOAD4 || trait == GENETIC_LOAD5) fitness *= newTrait->express(); + // Add the inherited trait and genes to the newborn's list spTraitTable.insert(make_pair(trait, move(newTrait))); } } @@ -187,7 +189,6 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi void Individual::inherit(Species* pSpecies, const Individual* mother) { set recomPositions; //not used here cos haploid but need it for inherit function, not ideal int startingChromosome = 0; - //const auto mumTraitTable = mother->getTraitTable(); //assuming mother and father share the same genetic structure.. const auto& mumTraits = getTraitTypes(); @@ -205,6 +206,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother) { if (trait == GENETIC_LOAD1 || trait == GENETIC_LOAD2 || trait == GENETIC_LOAD3 || trait == GENETIC_LOAD4 || trait == GENETIC_LOAD5) fitness *= newTrait->express(); + // Add the inherited trait and genes to the newborn's list spTraitTable.insert(make_pair(trait, move(newTrait))); } } diff --git a/Model.cpp b/Model.cpp index 9f51e94..0d301ba 100644 --- a/Model.cpp +++ b/Model.cpp @@ -241,6 +241,17 @@ int RunModel(Landscape* pLandscape, int seqsim) // open a new individuals file for each replicate if (sim.outInds) pComm->outInds(rep, 0, 0, ppLand.landNum); + + /* + if (sim.outGenetics) { + pComm->outGenetics(rep, 0, 0, ppLand.landNum); + if (!dem.stageStruct && sim.outStartGenetic == 0) { + // write genetic data for initialised individuals of non-strucutred population + pComm->outGenetics(rep, 0, 0, -1); + } + } + */ + // open a new genetics file for each replicate for per locus and pairwise stats if (sim.outputPerLocusWCFstat) { pComm->openWCPerLocusFstatFile(pSpecies, pLandscape, ppLand.landNum, rep); @@ -466,7 +477,11 @@ int RunModel(Landscape* pLandscape, int seqsim) // output Individuals if (sim.outInds && yr >= sim.outStartInd && yr % sim.outIntInd == 0) pComm->outInds(rep, yr, gen, -1); + // output Genetics + //if (sim.outGenetics && yr >= sim.outStartGenetic && yr % sim.outIntGenetic == 0) + // pComm->outGenetics(rep, yr, gen, -1); + if ((sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat) && yr % sim.outputGeneticInterval == 0) { simParams sim = paramsSim->getSim(); @@ -592,6 +607,10 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outInds) // close Individuals output file pComm->outInds(rep, 0, 0, -999); + + // if (sim.outGenetics) // close Genetics output file + // pComm->outGenetics(rep, 0, 0, -999); + if (sim.outputPerLocusWCFstat) //close per locus file pComm->openWCPerLocusFstatFile(pSpecies, pLandscape, -999, rep); if (sim.outputPairwiseFst) //close per locus file @@ -635,6 +654,7 @@ int RunModel(Landscape* pLandscape, int seqsim) // close Individuals & Genetics output files if open // they can still be open if the simulation was stopped by the user if (sim.outInds) pComm->outInds(0, 0, 0, -999); + // if (sim.outGenetics) pComm->outGenetics(0, 0, 0, -999); if (sim.outputWCFstat) pComm->openWCFstatFile(pSpecies, -999); if (sim.outputPerLocusWCFstat) pComm->openWCPerLocusFstatFile(pSpecies, pLandscape, -999, 0); if (sim.outputPairwiseFst) pComm->openPairwiseFSTFile(pSpecies, pLandscape, -999, 0); diff --git a/QTLTrait.cpp b/QTLTrait.cpp index a1dcff0..1dddc21 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -196,21 +196,19 @@ void QTLTrait::mutateNormal() // ---------------------------------------------------------------------------------------- -void QTLTrait::inherit(TTrait* parentTrait, set const& recomPositions, sex_t whichChromosome, int startingChromosome) +void QTLTrait::inherit(const bool& fromMother, TTrait* parentTrait, set const& recomPositions, int startingChromosome) { auto parentCast = dynamic_cast (parentTrait); //horrible const auto& parent_seq = parentCast->getGenes(); if (parent_seq.size() > 0) //else nothing to inherit, should always be something to inherit with QTL - (this->*_inherit_func_ptr) (whichChromosome, parent_seq, recomPositions, startingChromosome); + (this->*_inherit_func_ptr) (fromMother, parent_seq, recomPositions, startingChromosome); } -void QTLTrait::inheritDiploid(sex_t whichChromosome, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { +void QTLTrait::inheritDiploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { auto it = recomPositions.lower_bound(parentGenes.begin()->first); - int nextBreakpoint = *it; - auto distance = std::distance(recomPositions.begin(), it); if (distance % 2 != 0) parentChromosome = 1 - parentChromosome; //switch chromosome @@ -225,23 +223,23 @@ void QTLTrait::inheritDiploid(sex_t whichChromosome, map> newAllelePair(2); - newAllelePair[whichChromosome] = sp; - + newAllelePair[sex_t::FEM] = allele; genes.insert(make_pair(locus, newAllelePair)); } - else { - it->second[whichChromosome] = sp; + else { // father, locus already exists + if (fromMother) throw runtime_error("Mother-inherited locus already exists."); + it->second[sex_t::MAL] = allele; } } } } -void QTLTrait::inheritHaploid(sex_t chromosome, map>> const& parentGenes, set const& recomPositions, int parentChromosome) +void QTLTrait::inheritHaploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { genes = parentGenes; } diff --git a/QTLTrait.h b/QTLTrait.h index 62c08db..76e014b 100644 --- a/QTLTrait.h +++ b/QTLTrait.h @@ -19,7 +19,7 @@ class QTLTrait : public TTrait { SpeciesTrait* pSpeciesTrait; // would be better as const so immutable, but means passing positions list is heavy and can't be passed by reference - map>> genes; //position > + map>> genes; // position > void (QTLTrait::* _mutate_func_ptr) (void); void (QTLTrait::* _inherit_func_ptr) (sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); @@ -27,8 +27,8 @@ class QTLTrait : public TTrait { void initialiseUniform(float min, float max); void initialiseNormal(float mean, float sd); - void inheritDiploid(sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); - void inheritHaploid(sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); + void inheritDiploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); + void inheritHaploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); void inheritInitialParameters(sex_t chromosome, map>> const& parentMutations, set const& recomPositions, int parentChromosome); void mutateUniform(); void mutateNormal(); @@ -46,11 +46,9 @@ class QTLTrait : public TTrait { bool isInherited() const override { return pSpeciesTrait->isInherited(); } void mutate() override { (this->*_mutate_func_ptr) (); } float express() override { return (this->*_express_func_ptr) (); } - void inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) override; + void inherit(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; map>>& getGenes() { return genes; } // returning reference, receiver must be const - // virtual float getAlleleValueAtLocus(short chromosome, int i) const override { return (double)mutations[chromosome][i]->getSelectionCoef(); } - float getAlleleValueAtLocus(short chromosome, int i) const override; int countHeterozygoteLoci() const; bool isHeterozygoteAtLocus(int locus) const override; diff --git a/SNPTrait.cpp b/SNPTrait.cpp index 8b9da27..9535436 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -172,18 +172,18 @@ void SNPTrait::mutate_SSM() // inheritance options // ---------------------------------------------------------------------------------------- -void SNPTrait::inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) +void SNPTrait::inherit(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) { auto parentCast = dynamic_cast (parent); //horrible const auto& parent_seq = parentCast->getGenes(); if (parent_seq.size() > 0) //else nothing to inherit - (this->*_inherit_func_ptr) (chromosome, parent_seq, recomPositions, startingChromosome); + (this->*_inherit_func_ptr) (fromMother, parent_seq, recomPositions, startingChromosome); } -void SNPTrait::inheritDiploid(sex_t whichChromosome, map> const& parentGenes, set const& recomPositions, int parentChromosome) { +void SNPTrait::inheritDiploid(const bool& fromMother, map> const& parentGenes, set const& recomPositions, int parentChromosome) { if (parentGenes.size() > 0) { auto it = recomPositions.lower_bound(parentGenes.begin()->first); @@ -208,20 +208,22 @@ void SNPTrait::inheritDiploid(sex_t whichChromosome, map newAllelePair(2, wildType); - newAllelePair[whichChromosome] = sp; + newAllelePair[sex_t::FEM] = sp; genes.insert(make_pair(locus, newAllelePair)); } else { - it->second[whichChromosome] = sp; + if (fromMother) throw runtime_error("Mother-inherited locus already exists."); + it->second[sex_t::MAL] = sp; } } } } } -void SNPTrait::inheritHaploid(sex_t chromosome, map> const& parentGenes, set const& recomPositions, int parentChromosome) +void SNPTrait::inheritHaploid(const bool& fromMother, map> const& parentGenes, set const& recomPositions, int parentChromosome) { genes = parentGenes; } diff --git a/SNPTrait.h b/SNPTrait.h index d841eac..ca3b1d5 100644 --- a/SNPTrait.h +++ b/SNPTrait.h @@ -25,9 +25,8 @@ class SNPTrait : public TTrait { void (SNPTrait::* _mutate_func_ptr) (void); void (SNPTrait::* _inherit_func_ptr) (sex_t chromosome, map> const& parent, set const& recomPositions, int parentChromosome); - void inheritDiploid(sex_t chromosome, map> const&, set const& recomPositions, int parentChromosome); - - void inheritHaploid(sex_t chromosome, map> const& parentMutations, set const& recomPositions, int parentChromosome); + void inheritDiploid(const bool& fromMother, map> const&, set const& recomPositions, int parentChromosome); + void inheritHaploid(const bool& fromMother, map> const& parentMutations, set const& recomPositions, int parentChromosome); void initialiseFull(int max); //other option is that mutations map is empty until a mutation happens, default when empty is to return a 0 value for wildtype @@ -44,7 +43,7 @@ class SNPTrait : public TTrait { virtual unique_ptr clone() const override { return std::make_unique(*this); } - virtual void inherit(TTrait* parent, set const& recomPositions, sex_t chromosome, int startingChromosome) override; + virtual void inherit(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; virtual void mutate() override { (this->*_mutate_func_ptr) (); } virtual int getNLoci() const override { return pSpeciesTrait->getPositionsSize(); } diff --git a/SubCommunity.cpp b/SubCommunity.cpp index d15166e..e4f8145 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -105,7 +105,6 @@ void SubCommunity::initialise(Landscape* pLandscape, Species* pSpecies) void SubCommunity::initialInd(Landscape* pLandscape, Species* pSpecies, Patch* pPatch, Cell* pCell, int ix) { - demogrParams dem = pSpecies->getDemogrParams(); stageParams sstruct = pSpecies->getStageParams(); emigRules emig = pSpecies->getEmigRules(); From 036a988c2caa6f6cb5563fb72d374124b1208ef2 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 12 Apr 2024 16:56:21 +0100 Subject: [PATCH 089/332] uniform conditions for mutations across all traits --- GeneticLoad.cpp | 4 +--- QTLTrait.cpp | 11 ++++++----- SNPTrait.cpp | 1 + 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index a6c0012..bb36b80 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -168,9 +168,7 @@ void GeneticLoad::mutate() */ throw runtime_error("Locus sampled for mutation doesn't exist."); } - else { - it->second[p] = make_shared(newSelectionCoef, newDominanceCoef); - } + it->second[p] = make_shared(newSelectionCoef, newDominanceCoef); } } } diff --git a/QTLTrait.cpp b/QTLTrait.cpp index 1dddc21..8e3cff9 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -108,7 +108,6 @@ QTLTrait::QTLTrait(SpeciesTrait* P) } } - // ---------------------------------------------------------------------------------------- // for creating new individuals // ---------------------------------------------------------------------------------------- @@ -116,8 +115,6 @@ QTLTrait::QTLTrait(SpeciesTrait* P) QTLTrait::QTLTrait(const QTLTrait& T) : pSpeciesTrait(T.pSpeciesTrait), _mutate_func_ptr(T._mutate_func_ptr), _inherit_func_ptr(T._inherit_func_ptr), _express_func_ptr(T._express_func_ptr) {} - - // ---------------------------------------------------------------------------------------- // mutate uniform // ---------------------------------------------------------------------------------------- @@ -137,6 +134,7 @@ void QTLTrait::mutateUniform() for (int p = 0; p < ploidy; p++) { unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); + if (NbMut > positionsSize) NbMut = positionsSize; if (NbMut > 0) { vector mutationPositions; @@ -145,6 +143,8 @@ void QTLTrait::mutateUniform() for (int m : mutationPositions) { auto it = genes.find(m); + if (it == genes.end()) + throw runtime_error("Locus sampled for mutation doesn't exist."); float currentAlleleVal = it->second[p].get()->getAlleleValue();//current float newAlleleVal = pRandom->FRandom(minD, maxD) + currentAlleleVal; it->second[p] = make_shared(newAlleleVal, 1.0); @@ -159,7 +159,6 @@ void QTLTrait::mutateUniform() void QTLTrait::mutateNormal() { - const int positionsSize = pSpeciesTrait->getPositionsSize(); const auto& genePositions = pSpeciesTrait->getGenePositions(); const short ploidy = pSpeciesTrait->getPloidy(); @@ -167,7 +166,6 @@ void QTLTrait::mutateNormal() auto rng = pRandom->getRNG(); - const map mutationParameters = pSpeciesTrait->getMutationParameters(); const float mean = mutationParameters.find(MEAN)->second; const float sd = mutationParameters.find(SD)->second; @@ -175,6 +173,7 @@ void QTLTrait::mutateNormal() for (int p = 0; p < ploidy; p++) { unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); + if (NbMut > positionsSize) NbMut = positionsSize; if (NbMut > 0) { vector mutationPositions; @@ -183,6 +182,8 @@ void QTLTrait::mutateNormal() for (int m : mutationPositions) { auto it = genes.find(m); + if (it == genes.end()) + throw runtime_error("Locus sampled for mutation doesn't exist."); float currentAlleleVal = it->second[p].get()->getAlleleValue();//current float newAlleleVal = pRandom->Normal(mean, sd) + currentAlleleVal; it->second[p] = make_shared(newAlleleVal, 1.0); diff --git a/SNPTrait.cpp b/SNPTrait.cpp index 9535436..3ea5903 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -144,6 +144,7 @@ void SNPTrait::mutate_SSM() for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); + if (NbMut > positionsSize) NbMut = positionsSize; if (NbMut > 0) { vector mutationPositions; From 2e79aa328109f5b71ae5908d0a2e379d687d18c3 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 15 Apr 2024 14:34:07 +0100 Subject: [PATCH 090/332] tmp commit need to rewind in commit history --- GeneticLoad.cpp | 31 ++++++++++--------------------- QTLTrait.cpp | 2 -- SNPTrait.cpp | 4 ++-- SNPTrait.h | 2 +- 4 files changed, 13 insertions(+), 26 deletions(-) diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index bb36b80..2c5eaa1 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -117,9 +117,6 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) break; //should return false } } - - DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); - map initialParameters = pSpeciesTrait->getInitialParameters(); } @@ -173,11 +170,10 @@ void GeneticLoad::mutate() } } } + // ---------------------------------------------------------------------------------------- // get dominance value for new mutation // ---------------------------------------------------------------------------------------- - - float GeneticLoad::drawDominance(float selCoef) { DistributionType dominanceDistribution = pSpeciesTrait->getDominanceDistribution(); @@ -234,8 +230,6 @@ float GeneticLoad::drawDominance(float selCoef) { // ---------------------------------------------------------------------------------------- // get selection coefficient for new mutation // ---------------------------------------------------------------------------------------- - - float GeneticLoad::drawSelectionCoef() { DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); @@ -287,7 +281,6 @@ float GeneticLoad::drawSelectionCoef() { // inheritance options // ---------------------------------------------------------------------------------------- - void GeneticLoad::inherit(const bool& fromMother, TTrait* parentTrait, set const& recomPositions, int startingChromosome) { auto parentCast = dynamic_cast (parentTrait); //horrible @@ -346,8 +339,10 @@ float GeneticLoad::express() { for (auto const& [locus, pAllelePair] : genes) { - shared_ptr pAlleleLeft = (!pAllelePair[0]) ? wildType : pAllelePair[0]; - shared_ptr pAlleleRight = (!pAllelePair[1]) ? wildType : pAllelePair[1]; + + // If not initialised yet, initialise now? + shared_ptr pAlleleLeft = pAllelePair[0] == 0 ? wildType : pAllelePair[0]; + shared_ptr pAlleleRight = pAllelePair[1] == 0 ? wildType : pAllelePair[1]; if (pAlleleLeft.get()->getId() != pAlleleRight.get()->getId()) // heterozygote { @@ -365,8 +360,6 @@ float GeneticLoad::express() { // ---------------------------------------------------------------------------------------- // check if particular locus is heterozygote // ---------------------------------------------------------------------------------------- - - bool GeneticLoad::isHeterozygoteAtLocus(int locus) const { auto it = genes.find(locus); @@ -374,8 +367,8 @@ bool GeneticLoad::isHeterozygoteAtLocus(int locus) const { if (it == genes.end()) //not found so must be wildtype homozygous return false; else { - shared_ptr alleleRight = (!it->second[0]) ? wildType : it->second[0]; - shared_ptr alleleLeft = (!it->second[1]) ? wildType : it->second[1]; + shared_ptr alleleRight = it->second[0] == 0 ? wildType : it->second[0]; + shared_ptr alleleLeft = it->second[1] == 0 ? wildType : it->second[1]; return alleleRight != alleleLeft; } } @@ -383,15 +376,12 @@ bool GeneticLoad::isHeterozygoteAtLocus(int locus) const { // ---------------------------------------------------------------------------------------- // count heterozygote loci in genome // ---------------------------------------------------------------------------------------- - - int GeneticLoad::countHeterozygoteLoci() const { int count = 0; - for (auto const& [locus, allelePair] : genes) { - shared_ptr alleleLeft = (!allelePair[0]) ? wildType : allelePair[0]; - shared_ptr alleleRight = (!allelePair[1]) ? wildType : allelePair[1]; + shared_ptr alleleLeft = allelePair[0] == 0 ? wildType : allelePair[0]; + shared_ptr alleleRight = allelePair[1] == 0 ? wildType : allelePair[1]; count += alleleLeft != alleleRight; } return count; @@ -405,10 +395,9 @@ int GeneticLoad::countHeterozygoteLoci() const { float GeneticLoad::getAlleleValueAtLocus(short whichChromosome, int position) const { auto it = genes.find(position); - if (it == genes.end()) { return wildType->getAlleleValue(); //must still be wildtype at loci } else - return (!it->second[whichChromosome]) ? wildType->getAlleleValue() : it->second[whichChromosome]->getAlleleValue(); + return it->second[whichChromosome] == 0 ? wildType->getAlleleValue() : it->second[whichChromosome]->getAlleleValue(); } \ No newline at end of file diff --git a/QTLTrait.cpp b/QTLTrait.cpp index 8e3cff9..d0713fb 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -267,7 +267,6 @@ void QTLTrait::inheritInitialParameters(sex_t whichChromosome, mapsecond; initialiseUniform(minD, maxD); - break; } case NORMAL: @@ -282,7 +281,6 @@ void QTLTrait::inheritInitialParameters(sex_t whichChromosome, mapsecond; initialiseNormal(mean, sd); - break; } diff --git a/SNPTrait.cpp b/SNPTrait.cpp index 3ea5903..d3cd13a 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -47,7 +47,7 @@ SNPTrait::SNPTrait(SpeciesTrait* P) cout << endl << "Warning:: initial SNP/Microsat distribution parameter max cannot exceed " << SNPvalUpperBound << ", resetting to " << SNPvalUpperBound << "\n"; maxSNPval = SNPvalUpperBound; //reserve 255 for wildtype } - initialiseFull(maxSNPval); + initialiseUniform(maxSNPval); break; } @@ -233,7 +233,7 @@ void SNPTrait::inheritHaploid(const bool& fromMother, mapgetGenePositions(); short ploidy = pSpeciesTrait->getPloidy(); diff --git a/SNPTrait.h b/SNPTrait.h index ca3b1d5..d6881fc 100644 --- a/SNPTrait.h +++ b/SNPTrait.h @@ -28,7 +28,7 @@ class SNPTrait : public TTrait { void inheritDiploid(const bool& fromMother, map> const&, set const& recomPositions, int parentChromosome); void inheritHaploid(const bool& fromMother, map> const& parentMutations, set const& recomPositions, int parentChromosome); - void initialiseFull(int max); //other option is that mutations map is empty until a mutation happens, default when empty is to return a 0 value for wildtype + void initialiseUniform(int max); //other option is that mutations map is empty until a mutation happens, default when empty is to return a 0 value for wildtype void mutate_KAM(); void mutate_SSM(); From 2af103d05c8024e9a579b8eb0746fea3a0428d90 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 15 Apr 2024 16:05:26 +0100 Subject: [PATCH 091/332] fix uninitialized genetic load traits --- GeneticLoad.cpp | 22 +++++++++++----------- GeneticLoad.h | 8 +++++--- Individual.cpp | 2 +- QTLTrait.cpp | 6 +++--- QTLTrait.h | 4 ++-- SNPTrait.h | 2 +- TTrait.h | 2 +- 7 files changed, 24 insertions(+), 22 deletions(-) diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index 2c5eaa1..55b3b9d 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -8,8 +8,7 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) { pSpeciesTrait = P; - if (wildType.get() == nullptr) - wildType = make_shared(0.0, 0.0); + initialise(); ExpressionType expressionType = pSpeciesTrait->getExpressionType(); @@ -72,45 +71,36 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) { if (dominanceParameters.count(MAX) != 1) cout << endl << ("Error:: genetic load dominance uniform distribution parameter must contain one max value (e.g. max= ) \n"); - if (dominanceParameters.count(MIN) != 1) cout << endl << ("Error:: genetic load dominance uniform distribution parameter must contain one min value (e.g. min= ) \n"); - break; } case NORMAL: { - if (dominanceParameters.count(MEAN) != 1) cout << endl << ("Error:: genetic load dominance distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); - if (dominanceParameters.count(SD) != 1) cout << endl << ("Error:: genetic load dominance distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); - break; } case GAMMA: { if (dominanceParameters.count(SHAPE) != 1) cout << endl << ("Error:: genetic load dominance distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); - if (dominanceParameters.count(SCALE) != 1) cout << endl << ("Error:: genetic load dominance distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); - break; } case NEGEXP: { if (dominanceParameters.count(MEAN) != 1) cout << endl << ("Error:: genetic load dominance distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); - break; } case SCALED: { break; } - default: { cout << endl << ("Error:: wrong parameter value for genetic load dominance model, must be uniform/normal/gamma/negExp/scaled \n"); @@ -119,6 +109,16 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) } } +void GeneticLoad::initialise() { + // All positions start at wild type, mutations accumulate through simulation + const set genePositions = pSpeciesTrait->getGenePositions(); + short ploidy = pSpeciesTrait->getPloidy(); + const vector> wildTypeGene(ploidy, wildType); + for (auto position : genePositions) { + genes.insert(make_pair(position, wildTypeGene)); + } +} + // ---------------------------------------------------------------------------------------- // for creating new individuals diff --git a/GeneticLoad.h b/GeneticLoad.h index 33e4c26..4dfb21d 100644 --- a/GeneticLoad.h +++ b/GeneticLoad.h @@ -19,12 +19,14 @@ class GeneticLoad : public TTrait { map>> genes; // position > - inline static shared_ptr wildType; + inline static shared_ptr wildType = make_shared(0.0, 0.0); // void (AdaptiveTrait::* _mutate_func_ptr) (void); - void (GeneticLoad::* _inherit_func_ptr) (sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); + void (GeneticLoad::* _inherit_func_ptr) (const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); //float (AdaptiveTrait::* _express_func_ptr) (void); + void initialise(); + void inheritDiploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); void inheritHaploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); @@ -42,7 +44,7 @@ class GeneticLoad : public TTrait { virtual unique_ptr clone() const override { return std::make_unique(*this); } - virtual void inherit(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; + virtual void inherit(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; virtual void mutate() override; diff --git a/Individual.cpp b/Individual.cpp index 92c4688..8531b0f 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -198,7 +198,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother) { auto newTrait = motherTrait->clone(); //shallow copy, pointer to proto trait initialised and empty sequence - newTrait->inherit(motherTrait, recomPositions, FEM, startingChromosome); + newTrait->inherit(true, motherTrait, recomPositions, startingChromosome); if (newTrait->isInherited()) { if (newTrait->getMutationRate() > 0 && pSpecies->areMutationsOn()) newTrait->mutate(); diff --git a/QTLTrait.cpp b/QTLTrait.cpp index d0713fb..a458f9a 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -229,12 +229,12 @@ void QTLTrait::inheritDiploid(const bool& fromMother, map> newAllelePair(2); - newAllelePair[sex_t::FEM] = allele; + newAllelePair[sex_t::FEM] = sp; genes.insert(make_pair(locus, newAllelePair)); } else { // father, locus already exists if (fromMother) throw runtime_error("Mother-inherited locus already exists."); - it->second[sex_t::MAL] = allele; + it->second[sex_t::MAL] = sp; } } } @@ -249,7 +249,7 @@ void QTLTrait::inheritHaploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) +void QTLTrait::inheritInitialParameters(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); map initialParameters = pSpeciesTrait->getInitialParameters(); diff --git a/QTLTrait.h b/QTLTrait.h index 76e014b..305ee9a 100644 --- a/QTLTrait.h +++ b/QTLTrait.h @@ -22,14 +22,14 @@ class QTLTrait : public TTrait { map>> genes; // position > void (QTLTrait::* _mutate_func_ptr) (void); - void (QTLTrait::* _inherit_func_ptr) (sex_t chromosome, map>> const& parent, set const& recomPositions, int parentChromosome); + void (QTLTrait::* _inherit_func_ptr) (const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); float (QTLTrait::* _express_func_ptr) (void); void initialiseUniform(float min, float max); void initialiseNormal(float mean, float sd); void inheritDiploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); void inheritHaploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); - void inheritInitialParameters(sex_t chromosome, map>> const& parentMutations, set const& recomPositions, int parentChromosome); + void inheritInitialParameters(const bool& fromMother, map>> const& parentMutations, set const& recomPositions, int parentChromosome); void mutateUniform(); void mutateNormal(); float expressAverage(); diff --git a/SNPTrait.h b/SNPTrait.h index d6881fc..32fdf41 100644 --- a/SNPTrait.h +++ b/SNPTrait.h @@ -23,7 +23,7 @@ class SNPTrait : public TTrait { map> genes; //position > void (SNPTrait::* _mutate_func_ptr) (void); - void (SNPTrait::* _inherit_func_ptr) (sex_t chromosome, map> const& parent, set const& recomPositions, int parentChromosome); + void (SNPTrait::* _inherit_func_ptr) (const bool& fromMother, map> const& parent, set const& recomPositions, int parentChromosome); void inheritDiploid(const bool& fromMother, map> const&, set const& recomPositions, int parentChromosome); void inheritHaploid(const bool& fromMother, map> const& parentMutations, set const& recomPositions, int parentChromosome); diff --git a/TTrait.h b/TTrait.h index ff6f954..014eadb 100644 --- a/TTrait.h +++ b/TTrait.h @@ -17,7 +17,7 @@ class TTrait { virtual void mutate() = 0; virtual unique_ptr clone() const = 0; //copies parameters (if not static) not gene seqeunces - virtual void inherit(TTrait*, set const& , sex_t, int ) = 0; + virtual void inherit(const bool&, TTrait*, set const& , int ) = 0; virtual int getNLoci() const = 0; virtual float getMutationRate() const = 0; From a3517d9e933711e68551648367373a9f45c25800 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 15 Apr 2024 16:30:39 +0100 Subject: [PATCH 092/332] clearer phrasing --- QTLTrait.cpp | 11 ++--------- QTLTrait.h | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/QTLTrait.cpp b/QTLTrait.cpp index a458f9a..9dfccdd 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -10,7 +10,7 @@ QTLTrait::QTLTrait(SpeciesTrait* P) ExpressionType expressionType = pSpeciesTrait->getExpressionType(); if (!pSpeciesTrait->isInherited()) //there is a trait for individual variation but this isn't inherited variation it's sampled from initial distribution - _inherit_func_ptr = &QTLTrait::inheritInitialParameters; + _inherit_func_ptr = &QTLTrait::reInitialiseGenes; else { _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &QTLTrait::inheritHaploid : &QTLTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance @@ -249,7 +249,7 @@ void QTLTrait::inheritHaploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) +void QTLTrait::reInitialiseGenes(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); map initialParameters = pSpeciesTrait->getInitialParameters(); @@ -259,13 +259,10 @@ void QTLTrait::inheritInitialParameters(const bool& fromMother, mapsecond; float minD = initialParameters.find(MIN)->second; - initialiseUniform(minD, maxD); break; } @@ -273,17 +270,13 @@ void QTLTrait::inheritInitialParameters(const bool& fromMother, mapsecond; float sd = initialParameters.find(SD)->second; - initialiseNormal(mean, sd); break; } - default: { cout << endl << ("wrong parameter value for parameter \"initialisation of qtl\", must be uniform/normal \n"); diff --git a/QTLTrait.h b/QTLTrait.h index 305ee9a..b18ccc2 100644 --- a/QTLTrait.h +++ b/QTLTrait.h @@ -29,7 +29,7 @@ class QTLTrait : public TTrait { void initialiseNormal(float mean, float sd); void inheritDiploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); void inheritHaploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); - void inheritInitialParameters(const bool& fromMother, map>> const& parentMutations, set const& recomPositions, int parentChromosome); + void reInitialiseGenes(const bool& fromMother, map>> const& parentMutations, set const& recomPositions, int parentChromosome); void mutateUniform(); void mutateNormal(); float expressAverage(); From ccfb5d395099349c8215b4e257a1f50a3b844580 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 15 Apr 2024 16:55:57 +0100 Subject: [PATCH 093/332] not finding a locus is an error --- GeneticLoad.cpp | 8 +++----- QTLTrait.cpp | 9 +++------ SNPTrait.cpp | 9 +++------ SNPTrait.h | 2 +- 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index 55b3b9d..0b49e66 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -395,9 +395,7 @@ int GeneticLoad::countHeterozygoteLoci() const { float GeneticLoad::getAlleleValueAtLocus(short whichChromosome, int position) const { auto it = genes.find(position); - if (it == genes.end()) { - return wildType->getAlleleValue(); //must still be wildtype at loci - } - else - return it->second[whichChromosome] == 0 ? wildType->getAlleleValue() : it->second[whichChromosome]->getAlleleValue(); + if (it == genes.end()) + throw runtime_error("The genetic load locus queried for its allele value does not exist."); + return it->second[whichChromosome] == 0 ? wildType->getAlleleValue() : it->second[whichChromosome]->getAlleleValue(); } \ No newline at end of file diff --git a/QTLTrait.cpp b/QTLTrait.cpp index 9dfccdd..76c5b23 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -396,11 +396,8 @@ float QTLTrait::getAlleleValueAtLocus(short whichChromosome, int position) const auto it = genes.find(position); - if (it == genes.end()) { //no mutations there, should never happen at QTLs should always hold a value - return 0; //must still be wildtype at loci - cout << endl << ("Error:: trying to find QTL at ", position, " but doesn't exist \n"); - } - else - return it->second[whichChromosome].get()->getAlleleValue(); + if (it == genes.end()) + throw runtime_error("The QTL locus queried for its allele value does not exist."); + return it->second[whichChromosome].get()->getAlleleValue(); } \ No newline at end of file diff --git a/SNPTrait.cpp b/SNPTrait.cpp index d3cd13a..88450fc 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -24,8 +24,7 @@ SNPTrait::SNPTrait(SpeciesTrait* P) if (mutationParameters.count(MAX) != 1) cout << endl << ("Error:: KAM or SSM mutation distribution parameter must contain max value (e.g. max= ), max cannot exceed 256 \n"); - if (wildType == -999) - wildType = (int)mutationParameters.find(MAX)->second - 1; + wildType = (int)mutationParameters.find(MAX)->second - 1; if (wildType > SNPvalUpperBound) cout << endl << "Error:: max number of alleles cannot exceed " << SNPvalUpperBound << ".\n"; @@ -286,9 +285,7 @@ int SNPTrait::countHeterozygoteLoci() const { float SNPTrait::getAlleleValueAtLocus(short whichChromosome, int position) const { auto it = genes.find(position); - if (it == genes.end()) //no mutations there - return wildType; //must still be wildtype at loci - else - return it->second[whichChromosome]; + throw runtime_error("The neutral locus queried for its allele value does not exist."); + return it->second[whichChromosome]; } \ No newline at end of file diff --git a/SNPTrait.h b/SNPTrait.h index 32fdf41..6491fd1 100644 --- a/SNPTrait.h +++ b/SNPTrait.h @@ -14,7 +14,7 @@ class SNPTrait : public TTrait { private: - inline static int wildType = -999; + inline static int wildType; const int SNPvalUpperBound = UCHAR_MAX; // i.e. 256 // allele is char, can take value 0-255 From 3a0f852843799fdebe4c9b152345bb5a55d3a69a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 15 Apr 2024 18:01:42 +0100 Subject: [PATCH 094/332] scaffold for outputting gene values --- Community.cpp | 67 ++++++++++++++++++++++++++++---------------------- Community.h | 2 ++ Model.cpp | 20 +++++++++++---- Parameters.cpp | 2 ++ Parameters.h | 5 +++- 5 files changed, 60 insertions(+), 36 deletions(-) diff --git a/Community.cpp b/Community.cpp index 12d07ba..4cb274d 100644 --- a/Community.cpp +++ b/Community.cpp @@ -30,6 +30,7 @@ ofstream outrange; ofstream outoccup, outsuit; ofstream outtraitsrows; +ofstream outgenes; ofstream outwcfstat; ofstream outperlocusfstat; ofstream outpairwisefst; @@ -1397,34 +1398,6 @@ void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int } if (sett.indVar) { - // NB - CURRENTLY CANNOT BE SEX-DEPENDENT... - // if (sett.sexDep) { - // if (ts.ninds[0] > 0) mn = ts.sumS0[0]/(double)ts.ninds[0]; else mn = 0.0; - // if (ts.ninds[0] > 1) sd = ts.ssqS0[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; - // if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - // outtraitsrows << "\t" << mn << "\t" << sd; - // if (ts.ninds[1] > 0) mn = ts.sumS0[1]/(double)ts.ninds[1]; else mn = 0.0; - // if (ts.ninds[1] > 1) sd = ts.ssqS0[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; - // if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - // outtraitsrows << "\t" << mn << "\t" << sd; - // if (ts.ninds[0] > 0) mn = ts.sumAlphaS[0]/(double)ts.ninds[0]; else mn = 0.0; - // if (ts.ninds[0] > 1) sd = ts.ssqAlphaS[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; - // if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - // outtraitsrows << "\t" << mn << "\t" << sd; - // if (ts.ninds[1] > 0) mn = ts.sumAlphaS[1]/(double)ts.ninds[1]; else mn = 0.0; - // if (ts.ninds[1] > 1) sd = ts.ssqAlphaS[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; - // if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - // outtraitsrows << "\t" << mn << "\t" << sd; - // if (ts.ninds[0] > 0) mn = ts.sumBetaS[0]/(double)ts.ninds[0]; else mn = 0.0; - // if (ts.ninds[0] > 1) sd = ts.ssqBetaS[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; - // if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - // outtraitsrows << "\t" << mn << "\t" << sd; - // if (ts.ninds[1] > 0) mn = ts.sumBetaS[1]/(double)ts.ninds[1]; else mn = 0.0; - // if (ts.ninds[1] > 1) sd = ts.ssqBetaS[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; - // if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - // outtraitsrows << "\t" << mn << "\t" << sd; - // } - // else { // no sex dependence in settlement if (popsize > 0) mn = ts.sumS0[0] / (double)popsize; else mn = 0.0; if (popsize > 1) sd = ts.ssqS0[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; @@ -1437,7 +1410,6 @@ void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int if (popsize > 1) sd = ts.ssqBetaS[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - // } } if (pSpecies->getNumberOfAdaptiveTraits() > 0) { @@ -1607,11 +1579,46 @@ Rcpp::IntegerMatrix Community::addYearToPopList(int rep, int yr) { // TODO: def } #endif +bool Community::openOutGenesFile(const bool& isDiploid, const int landNr, const int rep) +{ + if (landNr == -999) { // close the file + if (outperlocusfstat.is_open()) outperlocusfstat.close(); + outperlocusfstat.clear(); + return true; + } + + string name; + simParams sim = paramsSim->getSim(); + + if (sim.batchMode) { + name = paramsSim->getDir(2) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + "_Land" + + Int2Str(landNr) + "_Rep" + + Int2Str(rep) + + "_geneValues.txt"; + } + else { + name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Rep" + Int2Str(rep) + "_geneValues.txt"; + } + + outgenes.open(name.c_str()); + outgenes << "Year\tRepSeason\tIndID\ttraitType\tlocusPosition"; + if (isDiploid) { + outgenes << "\talleleValueA\talleleValueB"; + } + else { + outgenes << "\talleleValue"; + } + outgenes << endl; + + return outgenes.is_open(); +} + // ---------------------------------------------------------------------------------------- // Sample individuals from sample patches // ---------------------------------------------------------------------------------------- - void Community::sampleIndividuals(Species* pSpecies) { const set patchList = pSpecies->getSamplePatches(); diff --git a/Community.h b/Community.h index f559e60..32ffe02 100644 --- a/Community.h +++ b/Community.h @@ -208,6 +208,8 @@ class Community { //sample individuals for genetics (or could be used for anything) void sampleIndividuals(Species* pSpecies); + bool openOutGenesFile(const bool& isDiploid, const int landNr, const int rep); + //control neutral stat output void outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool fstat, bool perLocus, bool pairwise); diff --git a/Model.cpp b/Model.cpp index 0d301ba..e2a09d6 100644 --- a/Model.cpp +++ b/Model.cpp @@ -252,6 +252,14 @@ int RunModel(Landscape* pLandscape, int seqsim) } */ + if (sim.outGenes) { + if (!pComm->openOutGenesFile(pSpecies->isDiploid(), ppLand.landNum, rep)) + throw logic_error("Output genes file could not be initialised."); + if (outStartGenes == 0) { + pComm->outGenes(); + } + } + // open a new genetics file for each replicate for per locus and pairwise stats if (sim.outputPerLocusWCFstat) { pComm->openWCPerLocusFstatFile(pSpecies, pLandscape, ppLand.landNum, rep); @@ -479,8 +487,9 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->outInds(rep, yr, gen, -1); // output Genetics - //if (sim.outGenetics && yr >= sim.outStartGenetic && yr % sim.outIntGenetic == 0) - // pComm->outGenetics(rep, yr, gen, -1); + if (sim.outGenes && yr >= sim.outStartGenetic && yr % sim.outputGeneticInterval == 0) { + pComm->outGenes(yr, gen); + } if ((sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat) && yr % sim.outputGeneticInterval == 0) { @@ -608,8 +617,9 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outInds) // close Individuals output file pComm->outInds(rep, 0, 0, -999); - // if (sim.outGenetics) // close Genetics output file - // pComm->outGenetics(rep, 0, 0, -999); + if (sim.outGenes) { + pComm->openOutGenesFile(pSpecies->isDiploid(), -999, rep); + } if (sim.outputPerLocusWCFstat) //close per locus file pComm->openWCPerLocusFstatFile(pSpecies, pLandscape, -999, rep); @@ -654,7 +664,7 @@ int RunModel(Landscape* pLandscape, int seqsim) // close Individuals & Genetics output files if open // they can still be open if the simulation was stopped by the user if (sim.outInds) pComm->outInds(0, 0, 0, -999); - // if (sim.outGenetics) pComm->outGenetics(0, 0, 0, -999); + if (sim.outGenes) pComm->openOutGenesFile(pSpecies->isDiploid(), -999, 0); if (sim.outputWCFstat) pComm->openWCFstatFile(pSpecies, -999); if (sim.outputPerLocusWCFstat) pComm->openWCPerLocusFstatFile(pSpecies, pLandscape, -999, 0); if (sim.outputPairwiseFst) pComm->openPairwiseFSTFile(pSpecies, pLandscape, -999, 0); diff --git a/Parameters.cpp b/Parameters.cpp index bf7bf42..308d4ac 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -325,9 +325,11 @@ simParams paramSim::getSim(void) { #endif s.drawLoaded = drawLoaded; s.patchSamplingOption = patchSamplingOption; + s.outGenes = outputGenes; s.outputWCFstat = outputWCFstat; s.outputPerLocusWCFstat = outputPerLocusWCFstat; s.outputPairwiseFst = outputPairwiseFst; + s.outStartGenetics = outputStartGenetics; s.outputGeneticInterval = outputGeneticInterval; return s; diff --git a/Parameters.h b/Parameters.h index fe55111..c7ceb0e 100644 --- a/Parameters.h +++ b/Parameters.h @@ -337,8 +337,9 @@ struct simParams { #endif bool fixReplicateSeed; string patchSamplingOption; + bool outGenes; bool outputWCFstat, outputPerLocusWCFstat, outputPairwiseFst; - int outputGeneticInterval; + int outputGeneticInterval, outStartGenetics; }; struct simView { @@ -417,9 +418,11 @@ class paramSim { bool fixReplicateSeed; string patchSamplingOption; + bool outputGenes; bool outputWCFstat; bool outputPerLocusWCFstat; bool outputPairwiseFst; + int outputStartGenetics; int outputGeneticInterval; }; From 1dba7c4f2c37f1541c850f17c15898629851320d Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 16 Apr 2024 18:09:34 +0100 Subject: [PATCH 095/332] output gene values, but linking issue --- Community.cpp | 38 ++++++++++------------------ Community.h | 1 + GeneticLoad.h | 1 - Individual.h | 8 ------ Model.cpp | 16 +++--------- Population.cpp | 64 +++++++++++++++++++++++++----------------------- Population.h | 2 +- SNPTrait.h | 1 - SubCommunity.cpp | 6 +++++ SubCommunity.h | 2 ++ TTrait.h | 2 ++ 11 files changed, 61 insertions(+), 80 deletions(-) diff --git a/Community.cpp b/Community.cpp index 4cb274d..0cb26d1 100644 --- a/Community.cpp +++ b/Community.cpp @@ -30,7 +30,7 @@ ofstream outrange; ofstream outoccup, outsuit; ofstream outtraitsrows; -ofstream outgenes; +ofstream ofsGenes; ofstream outwcfstat; ofstream outperlocusfstat; ofstream outpairwisefst; @@ -1086,7 +1086,6 @@ bool Community::outOccupancyHeaders(int option) string name, nameI; simParams sim = paramsSim->getSim(); - //demogrParams dem = pSpecies->getDemogr(); landParams ppLand = pLandscape->getLandParams(); int outrows = (sim.years / sim.outIntOcc) + 1; @@ -1129,7 +1128,6 @@ bool Community::outOccupancyHeaders(int option) void Community::outOccupancy(void) { landParams ppLand = pLandscape->getLandParams(); simParams sim = paramsSim->getSim(); - //streamsize prec = outoccup.precision(); locn loc; int nsubcomms = (int)subComms.size(); @@ -1152,7 +1150,6 @@ void Community::outOccupancy(void) { void Community::outOccSuit(bool view) { double sum, ss, mean, sd, se; simParams sim = paramsSim->getSim(); - //streamsize prec = outsuit.precision(); for (int i = 0; i < (sim.years / sim.outIntOcc) + 1; i++) { sum = ss = 0.0; @@ -1166,8 +1163,6 @@ void Community::outOccSuit(bool view) { else sd = 0.0; se = sd / sqrt((double)(sim.reps)); -// outsuit << i*sim.outInt << "\t" << mean << "\t" << se << endl; -// if (view) viewOccSuit(i*sim.outInt,mean,se); outsuit << i * sim.outIntOcc << "\t" << mean << "\t" << se << endl; if (view) viewOccSuit(i * sim.outIntOcc, mean, se); } @@ -1185,18 +1180,12 @@ only, this function relies on the fact that subcommunities are created in the sa sequence as patches, which is in asecending order of x nested within descending order of y */ -//void Community::outTraits(emigCanvas ecanv,trfrCanvas tcanv,Species *pSpecies, -// int rep,int yr,int gen) void Community::outTraits(traitCanvas tcanv, Species* pSpecies, int rep, int yr, int gen) { simParams sim = paramsSim->getSim(); simView v = paramsSim->getViews(); landParams land = pLandscape->getLandParams(); - //demogrParams dem = pSpecies->getDemogr(); - //emigRules emig = pSpecies->getEmig(); - //trfrRules trfr = pSpecies->getTrfr(); - //locn loc; traitsums* ts = 0; traitsums sctraits; if (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0) { @@ -1227,8 +1216,6 @@ void Community::outTraits(traitCanvas tcanv, Species* pSpecies, // generate output for each sub-community (patch) in the community int nsubcomms = (int)subComms.size(); for (int i = 1; i < nsubcomms; i++) { // // all except matrix sub-community - // sctraits = subComms[i]->outTraits(ecanv,tcanv,pLandscape,rep,yr,gen); - // sctraits = subComms[i]->outTraits(tcanv,pLandscape,rep,yr,gen,v.viewGrad); sctraits = subComms[i]->outTraits(tcanv, pLandscape, rep, yr, gen, false); locn loc = subComms[i]->getLocn(); int y = loc.y; @@ -1260,10 +1247,6 @@ void Community::outTraits(traitCanvas tcanv, Species* pSpecies, } } } - //if (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr%sim.outIntTraitRow == 0) - //{ - // if (ts != 0) delete[] ts; - //} if (ts != 0) { delete[] ts; ts = 0; } } @@ -1586,7 +1569,6 @@ bool Community::openOutGenesFile(const bool& isDiploid, const int landNr, const outperlocusfstat.clear(); return true; } - string name; simParams sim = paramsSim->getSim(); @@ -1602,17 +1584,23 @@ bool Community::openOutGenesFile(const bool& isDiploid, const int landNr, const name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Rep" + Int2Str(rep) + "_geneValues.txt"; } - outgenes.open(name.c_str()); - outgenes << "Year\tRepSeason\tIndID\ttraitType\tlocusPosition"; + ofsGenes.open(name.c_str()); + ofsGenes << "Year\tGeneration\tIndID\ttraitType\tlocusPosition"; if (isDiploid) { - outgenes << "\talleleValueA\talleleValueB"; + ofsGenes << "\talleleValueA\talleleValueB"; } else { - outgenes << "\talleleValue"; + ofsGenes << "\talleleValue"; } - outgenes << endl; + ofsGenes << endl; + return ofsGenes.is_open(); +} - return outgenes.is_open(); +void Community::outGenes(const int& year, const int& gen) { + if (!ofsGenes.is_open()) + throw runtime_error("Could not open output gene values file."); + for (auto sub : subComms) + sub->outGenes(ofsGenes, year, gen); } // ---------------------------------------------------------------------------------------- diff --git a/Community.h b/Community.h index 32ffe02..e3e790f 100644 --- a/Community.h +++ b/Community.h @@ -209,6 +209,7 @@ class Community { void sampleIndividuals(Species* pSpecies); bool openOutGenesFile(const bool& isDiploid, const int landNr, const int rep); + void outGenes(const int& year, const int& gen); //control neutral stat output void outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool fstat, bool perLocus, bool pairwise); diff --git a/GeneticLoad.h b/GeneticLoad.h index 4dfb21d..0e85e21 100644 --- a/GeneticLoad.h +++ b/GeneticLoad.h @@ -63,7 +63,6 @@ class GeneticLoad : public TTrait { virtual bool isHeterozygoteAtLocus(int locus) const override; virtual float express(); - virtual ~GeneticLoad() { } }; #endif // GENETICLOADH diff --git a/Individual.h b/Individual.h index 4f20482..ef41c9e 100644 --- a/Individual.h +++ b/Individual.h @@ -261,7 +261,6 @@ class Individual { Individual* traitClone(Cell*, Patch*, float, bool, short); - void setEmigTraits(Species* pSpecies, bool sexDep, bool densityDep); void setTransferTraits(Species* pSpecies, transferRules trfr, int resol); @@ -365,13 +364,6 @@ class Individual { const short, // landscape change index const bool // absorbing boundaries? ); - void outGenetics( // Write records to genetics file - const int, // replicate - const int, // year - const int, // species number - const int, // landscape number - const bool // output as cross table? - ); #if RS_RCPP void outMovePath( // Write records to movement paths file const int // year diff --git a/Model.cpp b/Model.cpp index e2a09d6..cccead2 100644 --- a/Model.cpp +++ b/Model.cpp @@ -242,21 +242,11 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outInds) pComm->outInds(rep, 0, 0, ppLand.landNum); - /* - if (sim.outGenetics) { - pComm->outGenetics(rep, 0, 0, ppLand.landNum); - if (!dem.stageStruct && sim.outStartGenetic == 0) { - // write genetic data for initialised individuals of non-strucutred population - pComm->outGenetics(rep, 0, 0, -1); - } - } - */ - if (sim.outGenes) { if (!pComm->openOutGenesFile(pSpecies->isDiploid(), ppLand.landNum, rep)) throw logic_error("Output genes file could not be initialised."); - if (outStartGenes == 0) { - pComm->outGenes(); + if (sim.outStartGenetics == 0) { + pComm->outGenes(0, 0); } } @@ -487,7 +477,7 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->outInds(rep, yr, gen, -1); // output Genetics - if (sim.outGenes && yr >= sim.outStartGenetic && yr % sim.outputGeneticInterval == 0) { + if (sim.outGenes && yr >= sim.outStartGenetics && yr % sim.outputGeneticInterval == 0) { pComm->outGenes(yr, gen); } diff --git a/Population.cpp b/Population.cpp index ee9d172..b877e25 100644 --- a/Population.cpp +++ b/Population.cpp @@ -463,23 +463,10 @@ popStats Population::getStats(void) p.nInds = (int)inds.size(); p.nNonJuvs = p.nAdults = 0; p.breeding = false; -#if RSDEBUG - //DEBUGLOG << "Population::getStats(): this=" << this - //// << " p.pSpecies=" << p.pSpecies << " p.spNum=" << p.spNum - // << " p.pPatch=" << p.pPatch << " patchNum=" << p.pPatch->getPatchNum() - // << " nStages=" << nStages << " nSexes=" << nSexes << " p.nInds=" << p.nInds - // << endl; -#endif for (int stg = 1; stg < nStages; stg++) { for (int sex = 0; sex < nSexes; sex++) { ninds = nInds[stg][sex]; p.nNonJuvs += ninds; -#if RSDEBUG - //DEBUGLOG << "Population::getStats(): this=" << this - // << " stg=" << stg << " sex=" << sex - // << " nInds[stg][sex]=" << nInds[stg][sex] << " p.nNonJuvs=" << p.nNonJuvs - // << endl; -#endif if (ninds > 0) { if (pSpecies->stageStructured()) { if (dem.repType == 2) fec = pSpecies->getFec(stg, sex); @@ -497,13 +484,6 @@ popStats Population::getStats(void) else { if (breeders[0] && breeders[1]) p.breeding = true; } -#if RSDEBUG - //DEBUGLOG << "Population::getStats(): this=" << this - // << " p.nInds=" << p.nInds << " p.nAdults=" << p.nAdults << " p.nNonJuvs=" << p.nNonJuvs - // << " breeders[0]=" << breeders[0] << " breeders[1]=" << breeders[1] - // << " p.breeding=" << p.breeding - // << endl; -#endif return p; } @@ -1890,7 +1870,6 @@ void Population::outIndsHeaders(int rep, int landNr, bool patchModel) void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, int patchNum) { - //int x, y, p_id; bool writeInd; pathSteps steps; Cell* pCell; @@ -1933,24 +1912,14 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, else loc = pCell->getLocn(); pCell = inds[i]->getLocn(0); locn natalloc = pCell->getLocn(); - //#if SEASONAL - // pCell = inds[i]->getLocn(2); - // locn prevloc = pCell->getLocn(); - //#endif if (ppLand.patchModel) { outInds << "\t" << inds[i]->getNatalPatch()->getPatchNum(); if (loc.x == -1) outInds << "\t-1"; else outInds << "\t" << patchNum; } else { // cell-based model - // EITHER write co-ordinates in cell units ... outInds << "\t" << (float)natalloc.x << "\t" << natalloc.y; outInds << "\t" << (float)loc.x << "\t" << (float)loc.y; - // ... OR write co-ordinates in real-world units - // outInds << "\t" << (float)natalloc.x * (float)ppLand.resol + (float)lim.minEast - // << "\t" << natalloc.y * (float)ppLand.resol + (float)lim.minNorth; - // outInds << "\t" << (float)loc.x * (float)ppLand.resol + (float)lim.minEast - // << "\t" << (float)loc.y * (float)ppLand.resol + (float)lim.minNorth; } if (dem.repType != 0) outInds << "\t" << ind.sex; if (dem.stageStruct) outInds << "\t" << ind.age << "\t" << ind.stage; @@ -2024,6 +1993,39 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, } } +void Population::outGenes(ofstream& oGenes, const int& yr, const int& gen) const { + + const bool isDiploid = pSpecies->isDiploid(); + auto traitTypes = pSpecies->getTraitTypes(); + int indID; + float alleleOnChromA, alleleOnChromB; + + // Fetch map to positions for each trait + // Presumably faster than fetching for every individual + map> allGenePositions; + for (auto trType : traitTypes) { + set traitPositions = pSpecies->getSpTrait(trType)->getGenePositions(); + allGenePositions.insert(make_pair(trType, traitPositions)); + } + + set positions; + for (Individual* ind : inds) { + indID = ind->getId(); + for (auto trType : traitTypes) { + positions = allGenePositions[trType]; + auto indTrait = ind->getTrait(trType); + for (auto pos : positions) { + alleleOnChromA = indTrait->getAlleleValueAtLocus(0, pos); + oGenes << yr << '\t' << gen << '\t' << indID << '\t' << trType << '\t' << pos << '\t' << alleleOnChromA; + if (isDiploid) { + alleleOnChromB = indTrait->getAlleleValueAtLocus(1, pos); + oGenes << '\t' << alleleOnChromB; + } + oGenes << endl; + } + } + } +} //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- diff --git a/Population.h b/Population.h index d20cf06..fd1a644 100644 --- a/Population.h +++ b/Population.h @@ -218,7 +218,7 @@ class Population { int, // generation int // Patch number ); - + void outGenes(ofstream& oGenes, const int& yr, const int& gen) const; void clean(void); // Remove zero pointers to dead or dispersed individuals void updatePopSNPtables(); diff --git a/SNPTrait.h b/SNPTrait.h index 6491fd1..542787f 100644 --- a/SNPTrait.h +++ b/SNPTrait.h @@ -58,6 +58,5 @@ class SNPTrait : public TTrait { virtual bool isHeterozygoteAtLocus(int locus) const override; virtual float express() { return -9999; } - }; #endif \ No newline at end of file diff --git a/SubCommunity.cpp b/SubCommunity.cpp index e4f8145..5ca3269 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -1063,6 +1063,12 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, return ts; } + +void SubCommunity::outGenes(ofstream& oGenes, const int& year, const int& gen) { + for (auto pop : popns) + pop->outGenes(oGenes, year, gen); +} + //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- diff --git a/SubCommunity.h b/SubCommunity.h index 05baa23..dfe3cfd 100644 --- a/SubCommunity.h +++ b/SubCommunity.h @@ -184,6 +184,8 @@ class SubCommunity { int // stage ); + void outGenes(ofstream& oGenes, const int& year, const int& gen); + private: intptr subCommNum; // SubCommunity number // 0 is reserved for the SubCommunity in the inter-patch matrix diff --git a/TTrait.h b/TTrait.h index 014eadb..dd55e54 100644 --- a/TTrait.h +++ b/TTrait.h @@ -11,6 +11,8 @@ using namespace std; +ofstream outGenes; + class TTrait { public: /** Mutation procedure, perform mutations on the genes sequence. **/ From 358cbd78477b164bc7fb11dbafb604933d77fcca Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 17 Apr 2024 11:11:45 +0100 Subject: [PATCH 096/332] enable output of gene values --- Community.cpp | 4 ++-- Community.h | 2 +- Model.cpp | 12 ++++++------ Parameters.cpp | 6 ++++-- Parameters.h | 4 ++-- Population.cpp | 2 +- Population.h | 2 +- SubCommunity.cpp | 9 ++++----- SubCommunity.h | 2 +- TTrait.h | 2 -- 10 files changed, 22 insertions(+), 23 deletions(-) diff --git a/Community.cpp b/Community.cpp index 0cb26d1..b849bd3 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1596,11 +1596,11 @@ bool Community::openOutGenesFile(const bool& isDiploid, const int landNr, const return ofsGenes.is_open(); } -void Community::outGenes(const int& year, const int& gen) { +void Community::outputGeneValues(const int& year, const int& gen) { if (!ofsGenes.is_open()) throw runtime_error("Could not open output gene values file."); for (auto sub : subComms) - sub->outGenes(ofsGenes, year, gen); + sub->outputGeneValues(ofsGenes, year, gen); } // ---------------------------------------------------------------------------------------- diff --git a/Community.h b/Community.h index e3e790f..b6036ae 100644 --- a/Community.h +++ b/Community.h @@ -209,7 +209,7 @@ class Community { void sampleIndividuals(Species* pSpecies); bool openOutGenesFile(const bool& isDiploid, const int landNr, const int rep); - void outGenes(const int& year, const int& gen); + void outputGeneValues(const int& year, const int& gen); //control neutral stat output void outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool fstat, bool perLocus, bool pairwise); diff --git a/Model.cpp b/Model.cpp index cccead2..19f7b6a 100644 --- a/Model.cpp +++ b/Model.cpp @@ -242,11 +242,11 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outInds) pComm->outInds(rep, 0, 0, ppLand.landNum); - if (sim.outGenes) { + if (sim.outputGeneValues) { if (!pComm->openOutGenesFile(pSpecies->isDiploid(), ppLand.landNum, rep)) throw logic_error("Output genes file could not be initialised."); if (sim.outStartGenetics == 0) { - pComm->outGenes(0, 0); + pComm->outputGeneValues(0, 0); } } @@ -477,8 +477,8 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->outInds(rep, yr, gen, -1); // output Genetics - if (sim.outGenes && yr >= sim.outStartGenetics && yr % sim.outputGeneticInterval == 0) { - pComm->outGenes(yr, gen); + if (sim.outputGeneValues && yr >= sim.outStartGenetics && yr % sim.outputGeneticInterval == 0) { + pComm->outputGeneValues(yr, gen); } if ((sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat) && yr % sim.outputGeneticInterval == 0) { @@ -607,7 +607,7 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outInds) // close Individuals output file pComm->outInds(rep, 0, 0, -999); - if (sim.outGenes) { + if (sim.outputGeneValues) { pComm->openOutGenesFile(pSpecies->isDiploid(), -999, rep); } @@ -654,7 +654,7 @@ int RunModel(Landscape* pLandscape, int seqsim) // close Individuals & Genetics output files if open // they can still be open if the simulation was stopped by the user if (sim.outInds) pComm->outInds(0, 0, 0, -999); - if (sim.outGenes) pComm->openOutGenesFile(pSpecies->isDiploid(), -999, 0); + if (sim.outputGeneValues) pComm->openOutGenesFile(pSpecies->isDiploid(), -999, 0); if (sim.outputWCFstat) pComm->openWCFstatFile(pSpecies, -999); if (sim.outputPerLocusWCFstat) pComm->openWCPerLocusFstatFile(pSpecies, pLandscape, -999, 0); if (sim.outputPairwiseFst) pComm->openPairwiseFSTFile(pSpecies, pLandscape, -999, 0); diff --git a/Parameters.cpp b/Parameters.cpp index 308d4ac..26a4d20 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -286,11 +286,13 @@ void paramSim::setSim(simParams s) { fixReplicateSeed = s.fixReplicateSeed; } -void paramSim::setGeneticSim(string patchSamplingOption, bool outputWCFstat, bool outputPerLocusWCFstat, bool outputPairwiseFst, int outputGeneticInterval) { +void paramSim::setGeneticSim(string patchSamplingOption, bool outputGeneticValues, bool outputWCFstat, bool outputPerLocusWCFstat, bool outputPairwiseFst, int outputStartGenetics, int outputGeneticInterval) { this->patchSamplingOption = patchSamplingOption; + this->outputGenes = outputGeneticValues; this->outputWCFstat = outputWCFstat; this->outputPerLocusWCFstat = outputPerLocusWCFstat; this->outputPairwiseFst = outputPairwiseFst; + this->outputStartGenetics = outputGeneticInterval; this->outputGeneticInterval = outputGeneticInterval; } @@ -325,7 +327,7 @@ simParams paramSim::getSim(void) { #endif s.drawLoaded = drawLoaded; s.patchSamplingOption = patchSamplingOption; - s.outGenes = outputGenes; + s.outputGeneValues = outputGenes; s.outputWCFstat = outputWCFstat; s.outputPerLocusWCFstat = outputPerLocusWCFstat; s.outputPairwiseFst = outputPairwiseFst; diff --git a/Parameters.h b/Parameters.h index c7ceb0e..8296fa5 100644 --- a/Parameters.h +++ b/Parameters.h @@ -337,7 +337,7 @@ struct simParams { #endif bool fixReplicateSeed; string patchSamplingOption; - bool outGenes; + bool outputGeneValues; bool outputWCFstat, outputPerLocusWCFstat, outputPairwiseFst; int outputGeneticInterval, outStartGenetics; }; @@ -354,7 +354,7 @@ class paramSim { paramSim(void); ~paramSim(void); void setSim(simParams); - void setGeneticSim(string patchSamplingOption, bool outputWCFstat, bool outputPerLocusWCFstat, bool outputPairwiseFst, int outputGeneticInterval); + void setGeneticSim(string patchSamplingOption, bool outputGeneticValues, bool outputWCFstat, bool outputPerLocusWCFstat, bool outputPairwiseFst, int outputStartGenetics, int outputGeneticInterval); simParams getSim(void); int getSimNum(void); void setViews(simView); diff --git a/Population.cpp b/Population.cpp index b877e25..24351e6 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1993,7 +1993,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, } } -void Population::outGenes(ofstream& oGenes, const int& yr, const int& gen) const { +void Population::outputGeneValues(ofstream& oGenes, const int& yr, const int& gen) const { const bool isDiploid = pSpecies->isDiploid(); auto traitTypes = pSpecies->getTraitTypes(); diff --git a/Population.h b/Population.h index fd1a644..9f78973 100644 --- a/Population.h +++ b/Population.h @@ -218,7 +218,7 @@ class Population { int, // generation int // Patch number ); - void outGenes(ofstream& oGenes, const int& yr, const int& gen) const; + void outputGeneValues(ofstream& oGenes, const int& yr, const int& gen) const; void clean(void); // Remove zero pointers to dead or dispersed individuals void updatePopSNPtables(); diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 5ca3269..36e6d8e 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -1047,9 +1047,9 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, ts.ssqBetaDB[iSex] += indTraitsSums.ssqBetaDB[iSex]; ts.sumStepL[iSex] += indTraitsSums.sumStepL[iSex]; ts.ssqStepL[iSex] += indTraitsSums.ssqStepL[iSex]; - ts.sumRho[iSex] += indTraitsSums.sumRho[iSex]; + ts.sumRho[iSex] += indTraitsSums.sumRho[iSex]; ts.ssqRho[iSex] += indTraitsSums.ssqRho[iSex]; - ts.sumS0[iSex] += indTraitsSums.sumS0[iSex]; + ts.sumS0[iSex] += indTraitsSums.sumS0[iSex]; ts.ssqS0[iSex] += indTraitsSums.ssqS0[iSex]; ts.sumAlphaS[iSex] += indTraitsSums.sumAlphaS[iSex]; ts.ssqAlphaS[iSex] += indTraitsSums.ssqAlphaS[iSex]; @@ -1063,10 +1063,9 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, return ts; } - -void SubCommunity::outGenes(ofstream& oGenes, const int& year, const int& gen) { +void SubCommunity::outputGeneValues(ofstream& oGenes, const int& year, const int& gen) { for (auto pop : popns) - pop->outGenes(oGenes, year, gen); + pop->outputGeneValues(oGenes, year, gen); } //--------------------------------------------------------------------------- diff --git a/SubCommunity.h b/SubCommunity.h index dfe3cfd..9e12700 100644 --- a/SubCommunity.h +++ b/SubCommunity.h @@ -184,7 +184,7 @@ class SubCommunity { int // stage ); - void outGenes(ofstream& oGenes, const int& year, const int& gen); + void outputGeneValues(ofstream& oGenes, const int& year, const int& gen); private: intptr subCommNum; // SubCommunity number diff --git a/TTrait.h b/TTrait.h index dd55e54..014eadb 100644 --- a/TTrait.h +++ b/TTrait.h @@ -11,8 +11,6 @@ using namespace std; -ofstream outGenes; - class TTrait { public: /** Mutation procedure, perform mutations on the genes sequence. **/ From 854e4ab3782b001912000998546e60d92440a492 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 17 Apr 2024 12:12:25 +0100 Subject: [PATCH 097/332] fix genetic output filestream --- Community.cpp | 12 +++++++----- Model.cpp | 11 ++++------- Parameters.h | 2 -- Population.cpp | 8 ++++---- Population.h | 2 +- SubCommunity.cpp | 4 ++-- SubCommunity.h | 2 +- 7 files changed, 19 insertions(+), 22 deletions(-) diff --git a/Community.cpp b/Community.cpp index b849bd3..b24c00e 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1565,8 +1565,8 @@ Rcpp::IntegerMatrix Community::addYearToPopList(int rep, int yr) { // TODO: def bool Community::openOutGenesFile(const bool& isDiploid, const int landNr, const int rep) { if (landNr == -999) { // close the file - if (outperlocusfstat.is_open()) outperlocusfstat.close(); - outperlocusfstat.clear(); + if (ofsGenes.is_open()) ofsGenes.close(); + ofsGenes.clear(); return true; } string name; @@ -1576,12 +1576,14 @@ bool Community::openOutGenesFile(const bool& isDiploid, const int landNr, const name = paramsSim->getDir(2) + "Batch" + Int2Str(sim.batchNum) + "_" + "Sim" + Int2Str(sim.simulation) + "_Land" - + Int2Str(landNr) + "_Rep" - + Int2Str(rep) + + Int2Str(landNr) + "_Rep" + Int2Str(rep) + "_geneValues.txt"; } else { - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Rep" + Int2Str(rep) + "_geneValues.txt"; + name = paramsSim->getDir(2) + + "Sim" + Int2Str(sim.simulation) + "_Land" + + Int2Str(landNr) + "_Rep" + Int2Str(rep) + + "_geneValues.txt"; } ofsGenes.open(name.c_str()); diff --git a/Model.cpp b/Model.cpp index 19f7b6a..441ec51 100644 --- a/Model.cpp +++ b/Model.cpp @@ -244,10 +244,7 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outputGeneValues) { if (!pComm->openOutGenesFile(pSpecies->isDiploid(), ppLand.landNum, rep)) - throw logic_error("Output genes file could not be initialised."); - if (sim.outStartGenetics == 0) { - pComm->outputGeneValues(0, 0); - } + throw logic_error("Output gene value file could not be initialised."); } // open a new genetics file for each replicate for per locus and pairwise stats @@ -607,8 +604,8 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outInds) // close Individuals output file pComm->outInds(rep, 0, 0, -999); - if (sim.outputGeneValues) { - pComm->openOutGenesFile(pSpecies->isDiploid(), -999, rep); + if (sim.outputGeneValues) { // close genetic values output file + pComm->openOutGenesFile(false, -999, rep); } if (sim.outputPerLocusWCFstat) //close per locus file @@ -654,7 +651,7 @@ int RunModel(Landscape* pLandscape, int seqsim) // close Individuals & Genetics output files if open // they can still be open if the simulation was stopped by the user if (sim.outInds) pComm->outInds(0, 0, 0, -999); - if (sim.outputGeneValues) pComm->openOutGenesFile(pSpecies->isDiploid(), -999, 0); + if (sim.outputGeneValues) pComm->openOutGenesFile(0, -999, 0); if (sim.outputWCFstat) pComm->openWCFstatFile(pSpecies, -999); if (sim.outputPerLocusWCFstat) pComm->openWCPerLocusFstatFile(pSpecies, pLandscape, -999, 0); if (sim.outputPairwiseFst) pComm->openPairwiseFSTFile(pSpecies, pLandscape, -999, 0); diff --git a/Parameters.h b/Parameters.h index 8296fa5..ffe0b0c 100644 --- a/Parameters.h +++ b/Parameters.h @@ -318,8 +318,6 @@ class paramInit { struct simParams { int batchNum; int simulation; int reps; int years; - // int outStartRange; - // int outStartOcc; int outStartPop; int outStartInd; int outStartTraitCell; int outStartTraitRow; int outStartConn; int outIntRange; int outIntOcc; int outIntPop; int outIntInd; diff --git a/Population.cpp b/Population.cpp index 24351e6..0334e24 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1993,7 +1993,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, } } -void Population::outputGeneValues(ofstream& oGenes, const int& yr, const int& gen) const { +void Population::outputGeneValues(ofstream& ofsGenes, const int& yr, const int& gen) const { const bool isDiploid = pSpecies->isDiploid(); auto traitTypes = pSpecies->getTraitTypes(); @@ -2016,12 +2016,12 @@ void Population::outputGeneValues(ofstream& oGenes, const int& yr, const int& ge auto indTrait = ind->getTrait(trType); for (auto pos : positions) { alleleOnChromA = indTrait->getAlleleValueAtLocus(0, pos); - oGenes << yr << '\t' << gen << '\t' << indID << '\t' << trType << '\t' << pos << '\t' << alleleOnChromA; + ofsGenes << yr << '\t' << gen << '\t' << indID << '\t' << trType << '\t' << pos << '\t' << alleleOnChromA; if (isDiploid) { alleleOnChromB = indTrait->getAlleleValueAtLocus(1, pos); - oGenes << '\t' << alleleOnChromB; + ofsGenes << '\t' << alleleOnChromB; } - oGenes << endl; + ofsGenes << endl; } } } diff --git a/Population.h b/Population.h index 9f78973..5bf25d3 100644 --- a/Population.h +++ b/Population.h @@ -218,7 +218,7 @@ class Population { int, // generation int // Patch number ); - void outputGeneValues(ofstream& oGenes, const int& yr, const int& gen) const; + void outputGeneValues(ofstream& ofsGenes, const int& yr, const int& gen) const; void clean(void); // Remove zero pointers to dead or dispersed individuals void updatePopSNPtables(); diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 36e6d8e..d88a46c 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -1063,9 +1063,9 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, return ts; } -void SubCommunity::outputGeneValues(ofstream& oGenes, const int& year, const int& gen) { +void SubCommunity::outputGeneValues(ofstream& ofsGenes, const int& year, const int& gen) { for (auto pop : popns) - pop->outputGeneValues(oGenes, year, gen); + pop->outputGeneValues(ofsGenes, year, gen); } //--------------------------------------------------------------------------- diff --git a/SubCommunity.h b/SubCommunity.h index 9e12700..e51790b 100644 --- a/SubCommunity.h +++ b/SubCommunity.h @@ -184,7 +184,7 @@ class SubCommunity { int // stage ); - void outputGeneValues(ofstream& oGenes, const int& year, const int& gen); + void outputGeneValues(ofstream& ofsGenes, const int& year, const int& gen); private: intptr subCommNum; // SubCommunity number From 7a366c350dce7efcee88ba611a3771dfea935894 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 17 Apr 2024 14:15:14 +0100 Subject: [PATCH 098/332] output gene values uses neutral genetics sampling feature --- Community.cpp | 16 +++++++++++++--- Community.h | 2 +- Model.cpp | 19 ++++++++++--------- Population.cpp | 2 +- SubCommunity.cpp | 5 ----- SubCommunity.h | 2 -- 6 files changed, 25 insertions(+), 21 deletions(-) diff --git a/Community.cpp b/Community.cpp index b24c00e..c2e51af 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1598,11 +1598,21 @@ bool Community::openOutGenesFile(const bool& isDiploid, const int landNr, const return ofsGenes.is_open(); } -void Community::outputGeneValues(const int& year, const int& gen) { +void Community::outputGeneValues(const int& year, const int& gen, Species* pSpecies) { if (!ofsGenes.is_open()) throw runtime_error("Could not open output gene values file."); - for (auto sub : subComms) - sub->outputGeneValues(ofsGenes, year, gen); + + const set patchList = pSpecies->getSamplePatches(); + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + if (patch == 0) { + throw runtime_error("Sampled patch does not exist"); + } + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + if (pPop != 0) { + pPop->outputGeneValues(ofsGenes, year, gen); + } + } } // ---------------------------------------------------------------------------------------- diff --git a/Community.h b/Community.h index b6036ae..9d5f15e 100644 --- a/Community.h +++ b/Community.h @@ -209,7 +209,7 @@ class Community { void sampleIndividuals(Species* pSpecies); bool openOutGenesFile(const bool& isDiploid, const int landNr, const int rep); - void outputGeneValues(const int& year, const int& gen); + void outputGeneValues(const int& year, const int& gen, Species* pSpecies); //control neutral stat output void outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool fstat, bool perLocus, bool pairwise); diff --git a/Model.cpp b/Model.cpp index 441ec51..5e6f7e6 100644 --- a/Model.cpp +++ b/Model.cpp @@ -473,15 +473,11 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outInds && yr >= sim.outStartInd && yr % sim.outIntInd == 0) pComm->outInds(rep, yr, gen, -1); - // output Genetics - if (sim.outputGeneValues && yr >= sim.outStartGenetics && yr % sim.outputGeneticInterval == 0) { - pComm->outputGeneValues(yr, gen); - } - - if ((sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat) && yr % sim.outputGeneticInterval == 0) { + if ((sim.outputGeneValues || sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat) + && yr >= sim.outStartGenetics + && yr % sim.outputGeneticInterval == 0) { simParams sim = paramsSim->getSim(); - if (sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat) { if (sim.patchSamplingOption != "list") { // then patches must be re-sampled every gen int nbToSample = pSpecies->getNbPatchesToSample(); @@ -489,9 +485,14 @@ int RunModel(Landscape* pLandscape, int seqsim) pSpecies->setSamplePatchList(patchesToSample); } // otherwise always use the user-specified list (even if patches are empty) - } pComm->sampleIndividuals(pSpecies); - pComm->outNeutralGenetics(pSpecies, rep, yr, gen, sim.outputWCFstat, sim.outputPerLocusWCFstat, sim.outputPairwiseFst); + + if (sim.outputGeneValues) { + pComm->outputGeneValues(yr, gen, pSpecies); + } + if (sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat) { + pComm->outNeutralGenetics(pSpecies, rep, yr, gen, sim.outputWCFstat, sim.outputPerLocusWCFstat, sim.outputPairwiseFst); + } } if (dem.stageStruct) { pComm->survival(1, 0, 1); diff --git a/Population.cpp b/Population.cpp index 0334e24..4554ae4 100644 --- a/Population.cpp +++ b/Population.cpp @@ -2009,7 +2009,7 @@ void Population::outputGeneValues(ofstream& ofsGenes, const int& yr, const int& } set positions; - for (Individual* ind : inds) { + for (Individual* ind : sampledInds) { indID = ind->getId(); for (auto trType : traitTypes) { positions = allGenePositions[trType]; diff --git a/SubCommunity.cpp b/SubCommunity.cpp index d88a46c..dc83c8b 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -1063,11 +1063,6 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, return ts; } -void SubCommunity::outputGeneValues(ofstream& ofsGenes, const int& year, const int& gen) { - for (auto pop : popns) - pop->outputGeneValues(ofsGenes, year, gen); -} - //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- diff --git a/SubCommunity.h b/SubCommunity.h index e51790b..05baa23 100644 --- a/SubCommunity.h +++ b/SubCommunity.h @@ -184,8 +184,6 @@ class SubCommunity { int // stage ); - void outputGeneValues(ofstream& ofsGenes, const int& year, const int& gen); - private: intptr subCommNum; // SubCommunity number // 0 is reserved for the SubCommunity in the inter-patch matrix From d5c86230a76ef56b164c0704d718fca83974b733 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 17 Apr 2024 17:35:06 +0100 Subject: [PATCH 099/332] post merge fixes to README and RSrandom --- CONTRIBUTING.md | 7 +------ RSrandom.cpp | 2 ++ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 08fafa1..cab5892 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,7 +17,7 @@ RangeShifter is distributed with three user interfaces, each living in their own All three share the same source code for the core simulation (i.e., the actual model), which lives in this repo (RScore). Each of the interfaces keeps a copy of this core code in a subfolder called RScore, kept in sync with the RScore repo via a git subtree (see Git subtree usage section). -⚠️ If you wish to propose a change to one of the interfaces, please do so in the corresponding repo: [RangeShifter batch mode](https://github.com/RangeShifter/RangeShifter_batch_dev), [RangeShiftR package](https://github.com/RangeShifter/RangeShiftR-package-dev). +âš  If you wish to propose a change to one of the interfaces, please do so in the corresponding repo: [RangeShifter batch mode](https://github.com/RangeShifter/RangeShifter_batch_dev), [RangeShiftR package](https://github.com/RangeShifter/RangeShiftR-package-dev). *The RangeShifter GUI is currently being rewritten, and is not open source yet. @@ -40,13 +40,10 @@ Anyone who whishes to make changes to RangeShifter's code, including regular dev ## Branching policy -<<<<<<<< HEAD:src/RScore/CONTRIBUTING.md ![](branches.png) *Check out the [Git cheatsheet](https://github.com/RangeShifter/RScore/blob/main/git_cheatsheet.md) for a reminder on the main git commands* -======== ->>>>>>>> develop:CONTRIBUTING.md This policy applies to RScore and all three RangeShifter interfaces. RangeShifter uses the following branching structure: @@ -87,5 +84,3 @@ Please get in touch with the RangeShifter development team (rangeshiftr@uni-pots Alternatively, proceed as with the bug fix above: create your own branch or fork _from `develop`_ and work from there, and submit a pull request when your new features are ready to join the core code. We recommend that you update your branch regularly to new changes on `develop` (using `git merge develop`) to reduce the risk of merge conflicts or your version getting out-of-touch in the late stages of development. We also recommend that you work in small commits, as this makes the code easier to debug, and makes it easier for maintainers to understand your contributions when reviewing a pull request. - -*Do we welcome independent contributions? diff --git a/RSrandom.cpp b/RSrandom.cpp index 6844831..16ae964 100644 --- a/RSrandom.cpp +++ b/RSrandom.cpp @@ -98,6 +98,8 @@ float RSrandom::FRandom(float min, float max) { } int RSrandom::Bernoulli(double p) { + if (p < 0) throw runtime_error("Bernoulli's p cannot be negative.\n"); + if (p > 1) throw runtime_error("Bernoulli's p cannot be above 1.\n"); return Random() < p; } From ef7cf7eb5d61c48444e0ba31f81ef62ba857f203 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 18 Apr 2024 15:47:38 +0100 Subject: [PATCH 100/332] refactor adaptive trait and fitness into genetic load and p survival --- Community.cpp | 24 ++++++++++++------------ GeneticLoad.h | 2 -- Individual.cpp | 8 ++++---- Individual.h | 4 ++-- Population.cpp | 14 +++++++------- Population.h | 4 ++-- Species.cpp | 14 +++++++------- Species.h | 6 +++--- SubCommunity.cpp | 32 ++++++++++++++++---------------- 9 files changed, 53 insertions(+), 55 deletions(-) diff --git a/Community.cpp b/Community.cpp index c2e51af..88a17a6 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1205,7 +1205,7 @@ void Community::outTraits(traitCanvas tcanv, Species* pSpecies, ts[y].sumS0[i] = ts[y].ssqS0[i] = 0.0; ts[y].sumAlphaS[i] = ts[y].ssqAlphaS[i] = 0.0; ts[y].sumBetaS[i] = ts[y].ssqBetaS[i] = 0.0; - ts[y].sumFitness[i] = ts[y].ssqFitness[i] = 0.0; + ts[y].sumProbViability[i] = ts[y].ssqProbViability[i] = 0.0; } } } @@ -1234,7 +1234,7 @@ void Community::outTraits(traitCanvas tcanv, Species* pSpecies, ts[y].sumS0[s] += sctraits.sumS0[s]; ts[y].ssqS0[s] += sctraits.ssqS0[s]; ts[y].sumAlphaS[s] += sctraits.sumAlphaS[s]; ts[y].ssqAlphaS[s] += sctraits.ssqAlphaS[s]; ts[y].sumBetaS[s] += sctraits.sumBetaS[s]; ts[y].ssqBetaS[s] += sctraits.ssqBetaS[s]; - ts[y].sumFitness[s] += sctraits.sumFitness[s]; ts[y].ssqFitness[s] += sctraits.ssqFitness[s]; + ts[y].sumProbViability[s] += sctraits.sumProbViability[s]; ts[y].ssqProbViability[s] += sctraits.ssqProbViability[s]; } } } @@ -1395,20 +1395,20 @@ void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int outtraitsrows << "\t" << mn << "\t" << sd; } - if (pSpecies->getNumberOfAdaptiveTraits() > 0) { + if (pSpecies->getNbGenLoadTraits() > 0) { if (maxNbSexes > 1) { - if (ts.ninds[0] > 0) mn = ts.sumFitness[0] / (double)ts.ninds[0]; else mn = 0.0; - if (ts.ninds[0] > 1) sd = ts.ssqFitness[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; + if (ts.ninds[0] > 0) mn = ts.sumProbViability[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqProbViability[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[1] > 0) mn = ts.sumFitness[1] / (double)ts.ninds[1]; else mn = 0.0; - if (ts.ninds[1] > 1) sd = ts.ssqFitness[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; + if (ts.ninds[1] > 0) mn = ts.sumProbViability[1] / (double)ts.ninds[1]; else mn = 0.0; + if (ts.ninds[1] > 1) sd = ts.ssqProbViability[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; } else { - if (ts.ninds[0] > 0) mn = ts.sumFitness[0] / (double)ts.ninds[0]; else mn = 0.0; - if (ts.ninds[0] > 1) sd = ts.ssqFitness[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; + if (ts.ninds[0] > 0) mn = ts.sumProbViability[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqProbViability[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; } @@ -1504,12 +1504,12 @@ bool Community::outTraitsRowsHeaders(Species* pSpecies, int landNr) { // } } - if (pSpecies->getNumberOfAdaptiveTraits() > 0) { + if (pSpecies->getNbGenLoadTraits() > 0) { if (maxNbSexes > 1) { - outtraitsrows << "\tF_meanFitness\tF_stdFitness\tM_meanFitness\tM_stdFitness"; + outtraitsrows << "\tF_meanProbViable\tF_stdProbViable\tM_meanProbViable\tM_stdProbViable"; } else - outtraitsrows << "\tmeanFitness\tstdFitness"; + outtraitsrows << "\tmeanProbViable\tstdProbViable"; } outtraitsrows << endl; diff --git a/GeneticLoad.h b/GeneticLoad.h index 0e85e21..979ff49 100644 --- a/GeneticLoad.h +++ b/GeneticLoad.h @@ -21,9 +21,7 @@ class GeneticLoad : public TTrait { inline static shared_ptr wildType = make_shared(0.0, 0.0); - // void (AdaptiveTrait::* _mutate_func_ptr) (void); void (GeneticLoad::* _inherit_func_ptr) (const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); - //float (AdaptiveTrait::* _express_func_ptr) (void); void initialise(); diff --git a/Individual.cpp b/Individual.cpp index 8531b0f..a794bb8 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -35,7 +35,7 @@ Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short rep float probmale, bool movt, short moveType) { indId = indCounter; indCounter++; // unique identifier for each individual - fitness = 1.0; + probViability = 1.0; stage = stg; if (probmale <= 0.0) sex = FEM; else sex = pRandom->Bernoulli(probmale) ? FEM : MAL; @@ -179,7 +179,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi newTrait->mutate(); } if (trait == GENETIC_LOAD1 || trait == GENETIC_LOAD2 || trait == GENETIC_LOAD3 || trait == GENETIC_LOAD4 || trait == GENETIC_LOAD5) - fitness *= newTrait->express(); + probViability *= newTrait->express(); // Add the inherited trait and genes to the newborn's list spTraitTable.insert(make_pair(trait, move(newTrait))); @@ -204,7 +204,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother) { newTrait->mutate(); } if (trait == GENETIC_LOAD1 || trait == GENETIC_LOAD2 || trait == GENETIC_LOAD3 || trait == GENETIC_LOAD4 || trait == GENETIC_LOAD5) - fitness *= newTrait->express(); + probViability *= newTrait->express(); // Add the inherited trait and genes to the newborn's list spTraitTable.insert(make_pair(trait, move(newTrait))); @@ -309,7 +309,7 @@ sex_t Individual::getSex(void) { return sex; } int Individual::getStatus(void) { return status; } -float Individual::getFitness(void) { return fitness; } +float Individual::getProbViability(void) { return probViability; } indStats Individual::getStats(void) { indStats s; diff --git a/Individual.h b/Individual.h index ef41c9e..91c4888 100644 --- a/Individual.h +++ b/Individual.h @@ -293,7 +293,7 @@ class Individual { int getId(void); sex_t getSex(void); int getStatus(void); - float getFitness(void); + float getProbViability(void); indStats getStats(void); Cell* getLocn( // Return location (as pointer to Cell) const short // option: 0 = get natal locn, 1 = get current locn @@ -372,7 +372,7 @@ class Individual { private: int indId; - float fitness; + float probViability; short stage; sex_t sex; short age; diff --git a/Population.cpp b/Population.cpp index 4554ae4..c48dada 100644 --- a/Population.cpp +++ b/Population.cpp @@ -224,7 +224,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { ts.sumS0[sex] = ts.ssqS0[sex] = 0.0; ts.sumAlphaS[sex] = ts.ssqAlphaS[sex] = 0.0; ts.sumBetaS[sex] = ts.ssqBetaS[sex] = 0.0; - ts.sumFitness[sex] = ts.ssqFitness[sex] = 0.0; + ts.sumProbViability[sex] = ts.ssqProbViability[sex] = 0.0; } emigRules emig = pSpecies->getEmigRules(); @@ -309,8 +309,8 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { if (maxNbSexes > 1) g = sex; else g = 0; - ts.sumFitness[g] += inds[iInd]->getFitness(); - ts.ssqFitness[g] += inds[iInd]->getFitness() * inds[iInd]->getFitness(); + ts.sumProbViability[g] += inds[iInd]->getProbViability(); + ts.ssqProbViability[g] += inds[iInd]->getProbViability() * inds[iInd]->getProbViability(); } return ts; } @@ -683,7 +683,7 @@ void Population::reproduction(const float localK, const float envval, const int newJuv->inheritTraits(pSpecies, inds[i], father, resol); } - if (newJuv->getFitness() < pRandom->Random()) { + if (newJuv->getProbViability() < pRandom->Random()) { delete newJuv; } else { @@ -763,7 +763,7 @@ void Population::reproduction(const float localK, const float envval, const int if (pSpecies->getNTraits() > 0) { newJuv->inheritTraits(pSpecies, inds[i], father, resol); } - if (newJuv->getFitness() < pRandom->Random()) { + if (newJuv->getProbViability() < pRandom->Random()) { delete newJuv; } else { @@ -1833,7 +1833,7 @@ void Population::outIndsHeaders(int rep, int landNr, bool patchModel) else outInds << "\tNatal_X\tNatal_Y\tX\tY"; if (dem.repType != 0) outInds << "\tSex"; if (dem.stageStruct) outInds << "\tAge\tStage"; - if (pSpecies->getNumberOfAdaptiveTraits() > 0) outInds << "\tFitness"; + if (pSpecies->getNbGenLoadTraits() > 0) outInds << "\tProbViable"; if (emig.indVar) { if (emig.densDep) outInds << "\tD0\tAlpha\tBeta"; else outInds << "\tEP"; @@ -1924,7 +1924,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, if (dem.repType != 0) outInds << "\t" << ind.sex; if (dem.stageStruct) outInds << "\t" << ind.age << "\t" << ind.stage; - if (pSpecies->getNumberOfAdaptiveTraits() > 0) outInds << "\t" << inds[i]->getFitness(); + if (pSpecies->getNbGenLoadTraits() > 0) outInds << "\t" << inds[i]->getProbViability(); if (emig.indVar) { emigTraits e = inds[i]->getEmigTraits(); diff --git a/Population.h b/Population.h index 5bf25d3..b405e27 100644 --- a/Population.h +++ b/Population.h @@ -103,8 +103,8 @@ struct traitsums { // sums of trait genes for dispersal double ssqAlphaS[maxNbSexes]; // sum of squares of slope of settlement den-dep reaction norm double sumBetaS[maxNbSexes]; // sum of inflection point of settlement reaction norm double ssqBetaS[maxNbSexes]; // sum of squares of inflection point of settlement reaction norm - double sumFitness[maxNbSexes]; - double ssqFitness[maxNbSexes]; + double sumProbViability[maxNbSexes]; + double ssqProbViability[maxNbSexes]; }; class Population { diff --git a/Species.cpp b/Species.cpp index 6288724..83c7f01 100644 --- a/Species.cpp +++ b/Species.cpp @@ -379,7 +379,7 @@ bool Species::areMutationsOn(void) { void Species::resetGeneticParameters() { mutationsOn = true; - numberOfAdaptiveTraits = 0; + nbGeneticLoadTraits = 0; genomeSize = -9999; recombinationRate = -9999; nPatchesToSample = 0; @@ -392,15 +392,15 @@ bool Species::isDiploid() const { return diploid; } -int Species::incrementAdaptiveTraits() +int Species::incrNbGenLoadTraits() { - numberOfAdaptiveTraits++; - return numberOfAdaptiveTraits; + nbGeneticLoadTraits++; + return nbGeneticLoadTraits; } -int Species::getNumberOfAdaptiveTraits() const +int Species::getNbGenLoadTraits() const { - return numberOfAdaptiveTraits; + return nbGeneticLoadTraits; } void Species::addTrait(TraitType traitType, const SpeciesTrait& trait) { @@ -408,7 +408,7 @@ void Species::addTrait(TraitType traitType, const SpeciesTrait& trait) { TraitType traitT = traitType; // hack to deal with multiple genetic load traits, could be handled better if (traitType == GENETIC_LOAD) { - int n = incrementAdaptiveTraits(); + int n = incrNbGenLoadTraits(); switch (n) { case 1: diff --git a/Species.h b/Species.h index 09e0c20..4755ea8 100644 --- a/Species.h +++ b/Species.h @@ -306,8 +306,8 @@ class Species { void resetGeneticParameters(); bool areMutationsOn(void); bool isDiploid() const; - int incrementAdaptiveTraits(); - int getNumberOfAdaptiveTraits() const; + int incrNbGenLoadTraits(); + int getNbGenLoadTraits() const; // emigration parameter functions @@ -489,7 +489,7 @@ class Species { int genomeSize; bool diploid; bool mutationsOn; - int numberOfAdaptiveTraits; + int nbGeneticLoadTraits; float recombinationRate; std::set samplePatchList; int nPatchesToSample; //for cell based landscape diff --git a/SubCommunity.cpp b/SubCommunity.cpp index dc83c8b..7439c1a 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -715,12 +715,12 @@ bool SubCommunity::outTraitsHeaders(Landscape* pLandscape, Species* pSpecies, in outtraits << "\tmeanBetaS\tstdBetaS"; } } - if (pSpecies->getNumberOfAdaptiveTraits() > 0) { + if (pSpecies->getNbGenLoadTraits() > 0) { if (maxNbSexes > 1) { - outtraits << "\tF_meanFitness\tF_stdFitness\tM_meanFitness\tM_stdFitness"; + outtraits << "\tF_meanProbViable\tF_stdProbViable\tM_meanProbViable\tM_stdProbViable"; } else { - outtraits << "\tmeanFitness\tstdFitness"; + outtraits << "\tmeanProbViable\tstdProbViable"; } } @@ -753,7 +753,7 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; ts.sumS0[i] = ts.ssqS0[i] = 0.0; ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; - ts.sumFitness[i] = ts.ssqFitness[i] = 0.0; + ts.sumProbViability[i] = ts.ssqProbViability[i] = 0.0; } // generate output for each population within the sub-community (patch) @@ -990,32 +990,32 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, } } - if (pSpecies->getNumberOfAdaptiveTraits() > 0) { + if (pSpecies->getNbGenLoadTraits() > 0) { ngenes = pSpecies->isDiploid() + 1; - double mnFitness[2], sdFitness[2]; + double mnProbViable[2], sdProbViable[2]; for (int iGene = 0; iGene < ngenes; iGene++) { - mnFitness[iGene] = sdFitness[iGene] = 0.0; + mnProbViable[iGene] = sdProbViable[iGene] = 0.0; if (ngenes == 2) popsize = indTraitsSums.ninds[iGene]; else popsize = indTraitsSums.ninds[0] + indTraitsSums.ninds[1]; if (popsize > 0) { - mnFitness[iGene] = indTraitsSums.sumFitness[iGene] / (double)popsize; + mnProbViable[iGene] = indTraitsSums.sumProbViability[iGene] / (double)popsize; if (popsize > 1) { - sdFitness[iGene] = indTraitsSums.ssqFitness[iGene] / (double)popsize - mnFitness[iGene] * mnFitness[iGene]; - if (sdFitness[iGene] > 0.0) sdFitness[iGene] = sqrt(sdFitness[iGene]); else sdFitness[iGene] = 0.0; + sdProbViable[iGene] = indTraitsSums.ssqProbViability[iGene] / (double)popsize - mnProbViable[iGene] * mnProbViable[iGene]; + if (sdProbViable[iGene] > 0.0) sdProbViable[iGene] = sqrt(sdProbViable[iGene]); else sdProbViable[iGene] = 0.0; } else { - sdFitness[iGene] = 0.0; + sdProbViable[iGene] = 0.0; } } } if (writefile) { if (maxNbSexes > 1) { - outtraits << "\t" << mnFitness[0] << "\t" << sdFitness[0]; - outtraits << "\t" << mnFitness[1] << "\t" << sdFitness[1]; + outtraits << "\t" << mnProbViable[0] << "\t" << sdProbViable[0]; + outtraits << "\t" << mnProbViable[1] << "\t" << sdProbViable[1]; } else { // sex-independent - outtraits << "\t" << mnFitness[0] << "\t" << sdFitness[0]; + outtraits << "\t" << mnProbViable[0] << "\t" << sdProbViable[0]; } } } @@ -1055,8 +1055,8 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, ts.ssqAlphaS[iSex] += indTraitsSums.ssqAlphaS[iSex]; ts.sumBetaS[iSex] += indTraitsSums.sumBetaS[iSex]; ts.ssqBetaS[iSex] += indTraitsSums.ssqBetaS[iSex]; - ts.sumFitness[iSex] += indTraitsSums.sumFitness[iSex]; - ts.ssqFitness[iSex] += indTraitsSums.ssqFitness[iSex]; + ts.sumProbViability[iSex] += indTraitsSums.sumProbViability[iSex]; + ts.ssqProbViability[iSex] += indTraitsSums.ssqProbViability[iSex]; } } } From 42e241a5369e8ee835766fc868cdeda1ac7ffdab Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 22 Apr 2024 17:44:12 +0100 Subject: [PATCH 101/332] allele dominance is calculated on a locus basis --- GeneticLoad.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index 0b49e66..2c167bc 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -336,23 +336,26 @@ void GeneticLoad::inheritHaploid(const bool& fromMother, map pAlleleLeft = pAllelePair[0] == 0 ? wildType : pAllelePair[0]; - shared_ptr pAlleleRight = pAllelePair[1] == 0 ? wildType : pAllelePair[1]; - - if (pAlleleLeft.get()->getId() != pAlleleRight.get()->getId()) // heterozygote - { - phenotype *= 1 + pAlleleLeft->getAlleleValue() * pAlleleLeft->getDominanceCoef(); - phenotype *= 1 + pAlleleRight->getAlleleValue() * pAlleleRight->getDominanceCoef(); + shared_ptr pAlleleA = pAllelePair[0] == 0 ? wildType : pAllelePair[0]; + shared_ptr pAlleleB = pAllelePair[1] == 0 ? wildType : pAllelePair[1]; + + sA = pAlleleA->getAlleleValue(); + hA = pAlleleA->getDominanceCoef(); + if (pSpeciesTrait->getPloidy() == 2) { + sB = pAlleleB->getAlleleValue(); + hB = pAlleleB->getDominanceCoef(); } - else { // homozygote - phenotype *= 1 + pAlleleLeft->getAlleleValue(); - phenotype *= 1 + pAlleleRight->getAlleleValue(); + else { + sB = 0.0; + hB = 0.0; } + sumDomCoeffs = hA + hB; + hLocus = sumDomCoeffs == 0.0 ? 0.0 : hA / sumDomCoeffs; + phenotype *= 1 - hLocus * sA - (1 - hLocus) * sB; } return phenotype; } From a29fcb11c24cedf47e349df98c1e4f35ea1bbc2c Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 22 Apr 2024 17:46:23 +0100 Subject: [PATCH 102/332] debug assert to try to catch a rare overflow --- Population.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Population.cpp b/Population.cpp index c48dada..eb4fd94 100644 --- a/Population.cpp +++ b/Population.cpp @@ -844,6 +844,9 @@ void Population::sampleIndsWithoutReplacement(string strNbToSample, const set Date: Tue, 23 Apr 2024 12:28:50 +0100 Subject: [PATCH 103/332] fix heterozygosity calls in haploid cases --- GeneticLoad.cpp | 10 +++++----- NeutralStatsManager.cpp | 20 +++++++++++--------- Population.cpp | 22 +++++++++++++--------- QTLTrait.cpp | 15 ++++----------- SNPTrait.cpp | 13 +++++-------- 5 files changed, 38 insertions(+), 42 deletions(-) diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index 0b49e66..0fa6b2c 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -312,7 +312,7 @@ void GeneticLoad::inheritDiploid(const bool& fromMother, map> newAllelePair(2); + vector> newAllelePair(2); // always diploid newAllelePair[sex_t::FEM] = allele; genes.insert(make_pair(locus, newAllelePair)); } @@ -361,11 +361,11 @@ float GeneticLoad::express() { // check if particular locus is heterozygote // ---------------------------------------------------------------------------------------- bool GeneticLoad::isHeterozygoteAtLocus(int locus) const { - + // assumes diploidy auto it = genes.find(locus); - if (it == genes.end()) //not found so must be wildtype homozygous - return false; + if (it == genes.end()) + throw runtime_error("Genetic load gene queried for heterozygosity does not exist."); else { shared_ptr alleleRight = it->second[0] == 0 ? wildType : it->second[0]; shared_ptr alleleLeft = it->second[1] == 0 ? wildType : it->second[1]; @@ -377,7 +377,7 @@ bool GeneticLoad::isHeterozygoteAtLocus(int locus) const { // count heterozygote loci in genome // ---------------------------------------------------------------------------------------- int GeneticLoad::countHeterozygoteLoci() const { - + // assumes diploidy int count = 0; for (auto const& [locus, allelePair] : genes) { shared_ptr alleleLeft = allelePair[0] == 0 ? wildType : allelePair[0]; diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index fcf978c..6be76b8 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -186,7 +186,7 @@ void NeutralStatsManager::calculateHo(set const& patchList, const int nbInd int nbHetero = 0; int nLoci = nbInds * nbrLoci; - if (nLoci != 0) { + if (nLoci != 0 && pSpecies->isDiploid()) { for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); @@ -260,14 +260,16 @@ void NeutralStatsManager::calculateHo2(set const& patchList, const int nbIn vector hetero(nbrLoci, 0); - for (int patchId : patchList) { - const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - if (pPop != 0) { - if (pPop->sampleSize() > 0) { - const vector heteroPatch = pPop->countLociHeterozyotes(); - transform(hetero.begin(), hetero.end(), heteroPatch.begin(), - hetero.begin(), plus()); + if (pSpecies->isDiploid()) { + for (int patchId : patchList) { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + if (pPop != 0) { + if (pPop->sampleSize() > 0) { + const vector heteroPatch = pPop->countLociHeterozyotes(); + transform(hetero.begin(), hetero.end(), heteroPatch.begin(), + hetero.begin(), plus()); + } } } } diff --git a/Population.cpp b/Population.cpp index c48dada..1b143e4 100644 --- a/Population.cpp +++ b/Population.cpp @@ -399,9 +399,11 @@ int Population::getHeteroTally(int thisLocus, int whichAllele) { int Population::countHeterozygoteLoci() { int nbHetero = 0; - for (Individual* ind : sampledInds) { - const auto trait = ind->getTrait(SNP); - nbHetero += trait->countHeterozygoteLoci(); + if (pSpecies->isDiploid()) { + for (Individual* ind : sampledInds) { + const auto trait = ind->getTrait(SNP); + nbHetero += trait->countHeterozygoteLoci(); + } } return nbHetero; } @@ -414,12 +416,14 @@ vector Population::countLociHeterozyotes() { const auto& positions = pSpecies->getSpTrait(SNP)->getGenePositions(); vector hetero(positions.size(), 0); - for (Individual* ind : sampledInds) { - const auto trait = ind->getTrait(SNP); - int counter = 0; - for (auto position : positions) { - hetero[counter] += trait->isHeterozygoteAtLocus(position); - counter++; + if (pSpecies->isDiploid()) { + for (Individual* ind : sampledInds) { + const auto trait = ind->getTrait(SNP); + int counter = 0; + for (auto position : positions) { + hetero[counter] += trait->isHeterozygoteAtLocus(position); + counter++; + } } } return hetero; diff --git a/QTLTrait.cpp b/QTLTrait.cpp index 76c5b23..b360c38 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -357,16 +357,12 @@ float QTLTrait::expressAverage() { // ---------------------------------------------------------------------------------------- bool QTLTrait::isHeterozygoteAtLocus(int locus) const { - + // assumes diploidy auto it = genes.find(locus); - if (it == genes.end()) //not found - return false; + throw runtime_error("QTL gene queried for heterozygosity does not exist."); else { - if (it->second.size() == 1) //only one ptr there so must be allele and wildtype at loci (heterozygote) - return true; - else - return(it->second[0].get()->getId() != it->second[1].get()->getId()); + return(it->second[0].get()->getId() != it->second[1].get()->getId()); } } @@ -375,13 +371,10 @@ bool QTLTrait::isHeterozygoteAtLocus(int locus) const { // ---------------------------------------------------------------------------------------- int QTLTrait::countHeterozygoteLoci() const { + // assumes diploidy int count = 0; for (auto const& [locus, allelePair] : genes) { - - if (allelePair.size() == 1) //only one ptr there so must be allele and wildtype at loci (heterozygote) - count++; - if (allelePair.size() == 2) count += (allelePair[0].get()->getId() != allelePair[1].get()->getId()); } diff --git a/SNPTrait.cpp b/SNPTrait.cpp index 88450fc..7302013 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -255,13 +255,10 @@ void SNPTrait::initialiseUniform(int maxAlleleVal) bool SNPTrait::isHeterozygoteAtLocus(int locus) const { - + // assumes diploidy auto it = genes.find(locus); - - if (it == genes.end()) //not found - return false; - else - return(it->second[0] != it->second[1]); + if (it == genes.end()) throw runtime_error("SNP gene queried for heterozygosity does not exist."); + else return(it->second[0] != it->second[1]); } // ---------------------------------------------------------------------------------------- @@ -269,10 +266,10 @@ bool SNPTrait::isHeterozygoteAtLocus(int locus) const { // ---------------------------------------------------------------------------------------- int SNPTrait::countHeterozygoteLoci() const { - + // assumes diploidy int count = 0; for (auto const& [locus, allelePair] : genes) { - count += (allelePair[0] != allelePair[1]); + count += (allelePair[0] != allelePair[1]); } return count; } From 3d7bc694d07a770fea0b2cf13f300d260a117f1c Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 23 Apr 2024 21:40:26 +0100 Subject: [PATCH 104/332] progress with genetics doc --- Allele.h | 2 +- Individual.cpp | 5 ++--- QTLTrait.cpp | 23 ++++++------------- QTLTrait.h | 57 +++++++++++++++++++++++++++++------------------- SpeciesTrait.cpp | 5 +++-- SpeciesTrait.h | 46 +++++++++++++++++++++----------------- TTrait.h | 4 +--- TraitFactory.h | 1 + 8 files changed, 76 insertions(+), 67 deletions(-) diff --git a/Allele.h b/Allele.h index 1b00706..90a6007 100644 --- a/Allele.h +++ b/Allele.h @@ -5,7 +5,7 @@ class Allele { const int id; const float value; const float dominance; - inline static int counter = 0; + inline static int counter = 0; // track nb alleles to set unique ID for each allele public: Allele(float alleleValue, float alleleDominance) : value(alleleValue), dominance(alleleDominance), id(counter) { ++counter; } ~Allele() {} diff --git a/Individual.cpp b/Individual.cpp index a794bb8..373a210 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -169,7 +169,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi { const auto motherTrait = mother->getTrait(trait); const auto fatherTrait = father->getTrait(trait); - auto newTrait = motherTrait->clone(); // shallow copy, pointer to proto trait initialised and empty sequence + auto newTrait = motherTrait->clone(); // shallow copy, pointer to species trait initialised and empty sequence newTrait->inherit(true, motherTrait, maternalRecomPositions, maternalStartingChromosome); if (newTrait->isInherited()) { @@ -195,8 +195,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother) { for (auto const& trait : mumTraits) { const auto motherTrait = mother->getTrait(trait); - - auto newTrait = motherTrait->clone(); //shallow copy, pointer to proto trait initialised and empty sequence + auto newTrait = motherTrait->clone(); // shallow copy, pointer to species trait initialised and empty sequence newTrait->inherit(true, motherTrait, recomPositions, startingChromosome); if (newTrait->isInherited()) { diff --git a/QTLTrait.cpp b/QTLTrait.cpp index b360c38..ea9bda5 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -1,9 +1,9 @@ #include "QTLTrait.h" // ---------------------------------------------------------------------------------------- -// for initialising population +// Species-level constructor +// Sets members and functions that are invariant across individuals // ---------------------------------------------------------------------------------------- - QTLTrait::QTLTrait(SpeciesTrait* P) { pSpeciesTrait = P; @@ -17,15 +17,14 @@ QTLTrait::QTLTrait(SpeciesTrait* P) DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); map mutationParameters = pSpeciesTrait->getMutationParameters(); + // Set mutation parameters switch (mutationDistribution) { case UNIFORM: { if (mutationParameters.count(MAX) != 1) cout << endl << ("Error:: mutation uniform qtl distribution parameter must contain max value (e.g. max= ) \n"); - if (mutationParameters.count(MIN) != 1) cout << endl << ("Error:: mutation uniform qtl distribution parameter must contain min value (e.g. min= ) \n"); - _mutate_func_ptr = &QTLTrait::mutateUniform; break; } @@ -33,14 +32,11 @@ QTLTrait::QTLTrait(SpeciesTrait* P) { if (mutationParameters.count(MEAN) != 1) cout << endl << ("Error:: qtl mutation distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); - if (mutationParameters.count(SD) != 1) cout << endl << ("Error::qtl mutation distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); - _mutate_func_ptr = &QTLTrait::mutateNormal; break; } - default: { cout << endl << ("Error:: wrong parameter value for qtl mutation model, must be uniform/normal \n"); //unless want to add gamma or negative exp @@ -49,21 +45,18 @@ QTLTrait::QTLTrait(SpeciesTrait* P) } } + // Set initialisation parameters DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); map initialParameters = pSpeciesTrait->getInitialParameters(); - switch (initialDistribution) { case UNIFORM: { if (initialParameters.count(MAX) != 1) cout << endl << ("Error:: initial uniform qtl distribution parameter must contain max value (e.g. max= ) \n"); - if (initialParameters.count(MIN) != 1) cout << endl << ("Error:: initial uniform qtl distribution parameter must contain min value (e.g. min= ) \n"); - float maxD = initialParameters.find(MAX)->second; float minD = initialParameters.find(MIN)->second; - initialiseUniform(minD, maxD); break; } @@ -71,17 +64,13 @@ QTLTrait::QTLTrait(SpeciesTrait* P) { if (initialParameters.count(MEAN) != 1) cout << endl << ("Error:: initial normal qtl distribution parameter must contain mean value (e.g. mean= ) \n"); - if (initialParameters.count(SD) != 1) cout << endl << ("Error:: initial normal qtl distribution parameter must contain sdev value (e.g. sdev= ) \n"); - float mean = initialParameters.find(MEAN)->second; float sd = initialParameters.find(SD)->second; - initialiseNormal(mean, sd); break; } - default: { cout << endl << ("wrong parameter value for parameter \"initialisation of qtl\", must be uniform/normal \n"); @@ -89,6 +78,7 @@ QTLTrait::QTLTrait(SpeciesTrait* P) } } + // Set expression mode parameters switch (expressionType) { case AVERAGE: { @@ -109,7 +99,8 @@ QTLTrait::QTLTrait(SpeciesTrait* P) } // ---------------------------------------------------------------------------------------- -// for creating new individuals +// Individual-level constructor +// Copies members from a species-level reference // ---------------------------------------------------------------------------------------- QTLTrait::QTLTrait(const QTLTrait& T) : pSpeciesTrait(T.pSpeciesTrait), _mutate_func_ptr(T._mutate_func_ptr), _inherit_func_ptr(T._inherit_func_ptr), _express_func_ptr(T._express_func_ptr) diff --git a/QTLTrait.h b/QTLTrait.h index b18ccc2..86380bd 100644 --- a/QTLTrait.h +++ b/QTLTrait.h @@ -10,14 +10,46 @@ using namespace std; - +// Quantitative-trait-loci (QTL) trait +// +// That is, all dispersal traits in RangeShifter, +// which individual phenotype is determined by small contributions +// from (potentially) many quantitative loci class QTLTrait : public TTrait { +public: + + // Species-level constructor, initialise + QTLTrait(SpeciesTrait* P); + + // Individual-level constructor, called when new individual is created + QTLTrait(const QTLTrait& T); + + virtual ~QTLTrait() { } + + virtual unique_ptr clone() const override { return std::make_unique(*this); } + + // Getters + int getNLoci() const override { return pSpeciesTrait->getPositionsSize(); } + float getMutationRate() const override { return pSpeciesTrait->getMutationRate(); } + bool isInherited() const override { return pSpeciesTrait->isInherited(); } + + map>>& getGenes() { return genes; } // returning reference, receiver must be const + + void mutate() override { (this->*_mutate_func_ptr) (); } + float express() override { return (this->*_express_func_ptr) (); } + void inherit(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; + + float getAlleleValueAtLocus(short chromosome, int i) const override; + int countHeterozygoteLoci() const; + bool isHeterozygoteAtLocus(int locus) const override; + private: - const double QTLDominanceFactor = 1.0; // that is, no dominance + const double QTLDominanceFactor = 1.0; // no dominance for QTL traits (yet?) - SpeciesTrait* pSpeciesTrait; // would be better as const so immutable, but means passing positions list is heavy and can't be passed by reference + // Species-level trait attributes, invariant across individuals + SpeciesTrait* pSpeciesTrait; map>> genes; // position > @@ -34,25 +66,6 @@ class QTLTrait : public TTrait { void mutateNormal(); float expressAverage(); float expressAdditive(); - -public: - - //this one for species held trait table, e.g. prototype table, sets static members - QTLTrait(SpeciesTrait* P); - QTLTrait(const QTLTrait& T); - virtual unique_ptr clone() const override { return std::make_unique(*this); } - int getNLoci() const override { return pSpeciesTrait->getPositionsSize(); } - float getMutationRate() const override { return pSpeciesTrait->getMutationRate(); } - bool isInherited() const override { return pSpeciesTrait->isInherited(); } - void mutate() override { (this->*_mutate_func_ptr) (); } - float express() override { return (this->*_express_func_ptr) (); } - void inherit(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; - map>>& getGenes() { return genes; } // returning reference, receiver must be const - - float getAlleleValueAtLocus(short chromosome, int i) const override; - int countHeterozygoteLoci() const; - bool isHeterozygoteAtLocus(int locus) const override; - virtual ~QTLTrait() { } }; #endif \ No newline at end of file diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index a1b1527..b65587a 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -1,7 +1,7 @@ #include "SpeciesTrait.h" -//could be handled in header file but here for now for flexibility +// Species trait constructor SpeciesTrait::SpeciesTrait( const TraitType& traitType, const sex_t& sx, const set& pos, const ExpressionType& expr, @@ -22,5 +22,6 @@ SpeciesTrait::SpeciesTrait( mutationParameters{mutationParams}, mutationRate{mutRate} { - if (ploidy == 0) this->ploidy = pSpecies->isDiploid() ? 2 : 1; + // Initialise ploidy only once per species + if (ploidy == NULL) this->ploidy = pSpecies->isDiploid() ? 2 : 1; } diff --git a/SpeciesTrait.h b/SpeciesTrait.h index 090012e..a83904f 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -9,26 +9,12 @@ #include #include -class Species; +class Species; // forward declaration to overcome circularity issue +// Species-level traits +// Features of traits that are shared across all individuals in the same species class SpeciesTrait { - -private: - inline static int ploidy = 0; - float mutationRate; - sex_t sex; - set genePositions; - ExpressionType expressionType; - DistributionType initialDistribution; - map initialParameters; - DistributionType dominanceDistribution; - map dominanceParameters; - bool inherited; - DistributionType mutationDistribution; - map mutationParameters; - public: - SpeciesTrait( const TraitType& traitType, const sex_t& sex, @@ -38,12 +24,12 @@ class SpeciesTrait { const map initParams, const DistributionType& dominanceDist, const map dominanceParams, - bool isInherited, + bool isInherited, const float& mutationRate, const DistributionType& mutationDist, const map mutationParams, Species* pSpecies - ); + ); // Getters sex_t getSex() const { return sex; } @@ -51,7 +37,8 @@ class SpeciesTrait { short getPloidy() const { return ploidy; } set& getGenePositions() { return genePositions; } // returning by reference, make sure receiver is const int getPositionsSize() const { return static_cast(genePositions.size()); } - bool isInherited() const { return inherited; } + bool isInherited() const { return inherited; } + DistributionType getMutationDistribution() const { return mutationDistribution; }; map getMutationParameters() const { return mutationParameters; }; DistributionType getDominanceDistribution() const { return dominanceDistribution; }; @@ -59,5 +46,24 @@ class SpeciesTrait { DistributionType getInitialDistribution() const { return initialDistribution; }; map getInitialParameters() const { return initialParameters; }; ExpressionType getExpressionType() const { return expressionType; }; + +private: + + inline static int ploidy = 0; + float mutationRate; + sex_t sex; + + // Positions in the genome of all genes (loci) pertaining to this trait + // The genome itself is not modelled explicitly + set genePositions; + + ExpressionType expressionType; + DistributionType initialDistribution; + map initialParameters; + DistributionType dominanceDistribution; + map dominanceParameters; + bool inherited; + DistributionType mutationDistribution; + map mutationParameters; }; #endif \ No newline at end of file diff --git a/TTrait.h b/TTrait.h index 014eadb..8b8a084 100644 --- a/TTrait.h +++ b/TTrait.h @@ -11,14 +11,12 @@ using namespace std; +// Base interface for all genetic traits class TTrait { public: - /** Mutation procedure, perform mutations on the genes sequence. **/ virtual void mutate() = 0; - virtual unique_ptr clone() const = 0; //copies parameters (if not static) not gene seqeunces virtual void inherit(const bool&, TTrait*, set const& , int ) = 0; - virtual int getNLoci() const = 0; virtual float getMutationRate() const = 0; virtual bool isInherited() const = 0; diff --git a/TraitFactory.h b/TraitFactory.h index 50a6208..25b10a5 100644 --- a/TraitFactory.h +++ b/TraitFactory.h @@ -8,6 +8,7 @@ #include "QTLTrait.h" #include "GeneticLoad.h" +// Create handled pointers to a new trait class TraitFactory { public: From 8adce177f068cf06f96f0fd85f2c3090a12949a3 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 25 Apr 2024 18:23:21 +0100 Subject: [PATCH 105/332] doc genetic traits --- GeneticLoad.cpp | 165 ++++++++++++++++++++------------------------- GeneticLoad.h | 78 +++++++++++++--------- Individual.cpp | 35 +++++----- QTLTrait.cpp | 131 ++++++++++++++++++------------------ QTLTrait.h | 32 ++++++--- SNPTrait.cpp | 174 ++++++++++++++++++++++++------------------------ SNPTrait.h | 80 +++++++++++++--------- TTrait.h | 2 +- 8 files changed, 363 insertions(+), 334 deletions(-) diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index 0fa6b2c..5d48877 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -1,17 +1,18 @@ #include "GeneticLoad.h" // ---------------------------------------------------------------------------------------- -// for initialising population +// Initialisation constructor +// Called when initialising community +// Sets up initial values, and immutable attributes (distributions and parameters) +// that are defined at the species-level // ---------------------------------------------------------------------------------------- - GeneticLoad::GeneticLoad(SpeciesTrait* P) { pSpeciesTrait = P; + ExpressionType expressionType = pSpeciesTrait->getExpressionType(); initialise(); - ExpressionType expressionType = pSpeciesTrait->getExpressionType(); - _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &GeneticLoad::inheritHaploid : &GeneticLoad::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); @@ -21,46 +22,35 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) case UNIFORM: { if (mutationParameters.count(MAX) != 1) - cout << endl << ("Error:: genetic load mutation uniform distribution parameter must contain one max value (e.g. max= ) \n"); - + throw logic_error("Error:: genetic load mutation uniform distribution parameter must contain one max value (e.g. max= ) \n"); if (mutationParameters.count(MIN) != 1) - cout << endl << ("Error:: genetic load mutation uniform distribution parameter must contain one min value (e.g. min= ) \n"); - + throw logic_error("Error:: genetic load mutation uniform distribution parameter must contain one min value (e.g. min= ) \n"); break; } case NORMAL: { - if (mutationParameters.count(MEAN) != 1) - cout << endl << ("Error:: genetic load mutation distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); - + throw logic_error("Error:: genetic load mutation distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); if (mutationParameters.count(SD) != 1) - cout << endl << ("Error:: genetic load mutation distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); - + throw logic_error("Error:: genetic load mutation distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); break; } case GAMMA: { if (mutationParameters.count(SHAPE) != 1) - cout << endl << ("Error:: genetic load mutation distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); - + throw logic_error("Error:: genetic load mutation distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); if (mutationParameters.count(SCALE) != 1) - cout << endl << ("Error:: genetic load mutation distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); - + throw logic_error("Error:: genetic load mutation distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); break; } case NEGEXP: { if (mutationParameters.count(MEAN) != 1) - cout << endl << ("Error:: genetic load mutation distribution set to negative exponential (negative decay) so parameters must contain one mean value (e.g. mean= ) \n"); - + throw logic_error("Error:: genetic load mutation distribution set to negative exponential (negative decay) so parameters must contain one mean value (e.g. mean= ) \n"); break; } - default: - { - cout << endl << ("Error:: wrong parameter value for genetic load mutation model, must be uniform/normal/gamma/negExp \n"); - } + throw logic_error("Error:: wrong parameter value for genetic load mutation model, must be uniform/normal/gamma/negExp \n"); } DistributionType dominanceDistribution = pSpeciesTrait->getDominanceDistribution(); @@ -70,45 +60,53 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) case UNIFORM: { if (dominanceParameters.count(MAX) != 1) - cout << endl << ("Error:: genetic load dominance uniform distribution parameter must contain one max value (e.g. max= ) \n"); + throw logic_error("Error:: genetic load dominance uniform distribution parameter must contain one max value (e.g. max= ) \n"); if (dominanceParameters.count(MIN) != 1) - cout << endl << ("Error:: genetic load dominance uniform distribution parameter must contain one min value (e.g. min= ) \n"); + throw logic_error("Error:: genetic load dominance uniform distribution parameter must contain one min value (e.g. min= ) \n"); break; } case NORMAL: { if (dominanceParameters.count(MEAN) != 1) - cout << endl << ("Error:: genetic load dominance distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); + throw logic_error("Error:: genetic load dominance distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); if (dominanceParameters.count(SD) != 1) - cout << endl << ("Error:: genetic load dominance distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); + throw logic_error("Error:: genetic load dominance distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); break; } case GAMMA: { if (dominanceParameters.count(SHAPE) != 1) - cout << endl << ("Error:: genetic load dominance distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); + throw logic_error("Error:: genetic load dominance distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); if (dominanceParameters.count(SCALE) != 1) - cout << endl << ("Error:: genetic load dominance distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); + throw logic_error("Error:: genetic load dominance distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); break; } case NEGEXP: { if (dominanceParameters.count(MEAN) != 1) - cout << endl << ("Error:: genetic load dominance distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); + throw logic_error("Error:: genetic load dominance distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); break; } case SCALED: { - break; + break; // no parameter } default: { - cout << endl << ("Error:: wrong parameter value for genetic load dominance model, must be uniform/normal/gamma/negExp/scaled \n"); - break; //should return false + throw logic_error("Error:: wrong parameter value for genetic load dominance model, must be uniform/normal/gamma/negExp/scaled \n"); + break; } } } +// ---------------------------------------------------------------------------------------- +// Inheritance constructor +// Copies immutable features from a parent trait +// Only called via clone() +// ---------------------------------------------------------------------------------------- +GeneticLoad::GeneticLoad(const GeneticLoad& T) : pSpeciesTrait(T.pSpeciesTrait), _inherit_func_ptr(T._inherit_func_ptr) +{} + void GeneticLoad::initialise() { // All positions start at wild type, mutations accumulate through simulation const set genePositions = pSpeciesTrait->getGenePositions(); @@ -119,16 +117,8 @@ void GeneticLoad::initialise() { } } - -// ---------------------------------------------------------------------------------------- -// for creating new individuals -// ---------------------------------------------------------------------------------------- - -GeneticLoad::GeneticLoad(const GeneticLoad& T) : pSpeciesTrait(T.pSpeciesTrait), _inherit_func_ptr(T._inherit_func_ptr) -{} - // ---------------------------------------------------------------------------------------- -// mutate uniform +// Mutate uniform // ---------------------------------------------------------------------------------------- void GeneticLoad::mutate() { @@ -140,7 +130,6 @@ void GeneticLoad::mutate() auto rng = pRandom->getRNG(); for (int p = 0; p < ploidy; p++) { - // Determine nb of mutations unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); if (NbMut > positionsSize) NbMut = positionsSize; @@ -152,19 +141,11 @@ void GeneticLoad::mutate() NbMut, rng); for (int m : mutationPositions) { - - float newSelectionCoef = drawSelectionCoef(); - float newDominanceCoef = drawDominance(newSelectionCoef); - auto it = genes.find(m); - if (it == genes.end()) { - /* - vector> newAllelePair(2); - newAllelePair[p] = make_shared(newSelectionCoef, newDominanceCoef); //put new mutation value in - genes.insert(make_pair(m, newAllelePair)); - */ + if (it == genes.end()) throw runtime_error("Locus sampled for mutation doesn't exist."); - } + float newSelectionCoef = drawSelectionCoef(); + float newDominanceCoef = drawDominance(newSelectionCoef); it->second[p] = make_shared(newSelectionCoef, newDominanceCoef); } } @@ -180,7 +161,6 @@ float GeneticLoad::drawDominance(float selCoef) { map dominanceParameters = pSpeciesTrait->getDominanceParameters(); float h = 1.0; //default dominance is 1 - switch (dominanceDistribution) { case UNIFORM: { @@ -219,16 +199,15 @@ float GeneticLoad::drawDominance(float selCoef) { default: { - cout << endl << ("Error:: wrong parameter value for genetic load dominance model, must be uniform/normal/gamma/negExp/scaled \n"); - break; //should return false + throw logic_error("Error:: wrong parameter value for genetic load dominance model, must be uniform/normal/gamma/negExp/scaled \n"); + break; } } - return h; } // ---------------------------------------------------------------------------------------- -// get selection coefficient for new mutation +// Get selection coefficient for new mutation // ---------------------------------------------------------------------------------------- float GeneticLoad::drawSelectionCoef() { @@ -243,7 +222,6 @@ float GeneticLoad::drawSelectionCoef() { float maxD = mutationParameters.find(MAX)->second; float minD = mutationParameters.find(MIN)->second; s = pRandom->FRandom(minD, maxD); - break; } case NORMAL: @@ -251,7 +229,6 @@ float GeneticLoad::drawSelectionCoef() { const float mean = mutationParameters.find(MEAN)->second; const float sd = mutationParameters.find(SD)->second; s = static_cast(pRandom->Normal(mean, sd)); - break; } case GAMMA: @@ -269,8 +246,8 @@ float GeneticLoad::drawSelectionCoef() { } default: { - cout << endl << ("Error:: wrong parameter value for genetic load mutation model, must be uniform/normal/gamma/negExp/scaled \n"); - break; //should return false + throw logic_error("Error:: wrong parameter value for genetic load mutation model, must be uniform/normal/gamma/negExp/scaled \n"); + break; } } return s; @@ -278,69 +255,78 @@ float GeneticLoad::drawSelectionCoef() { // ---------------------------------------------------------------------------------------- -// inheritance options +// Wrapper to inheritance function // ---------------------------------------------------------------------------------------- - -void GeneticLoad::inherit(const bool& fromMother, TTrait* parentTrait, set const& recomPositions, int startingChromosome) +void GeneticLoad::inheritGenes(const bool& fromMother, TTrait* parentTrait, set const& recomPositions, int startingChromosome) { - auto parentCast = dynamic_cast (parentTrait); //horrible - + auto parentCast = dynamic_cast (parentTrait); // must convert TTrait to GeneticLoadTrait const auto& parent_seq = parentCast->getGenes(); - if (parent_seq.size() > 0) //else nothing to inherit - (this->*_inherit_func_ptr) (fromMother, parent_seq, recomPositions, startingChromosome); + (this->*_inherit_func_ptr) (fromMother, parent_seq, recomPositions, startingChromosome); } +// ---------------------------------------------------------------------------------------- +// Inheritance for diploid, sexual species +// Called once for each parent. Given a list of recombinant sites, +// populates offspring genes with appropriate parent alleles +// Assumes mother genes are inherited first +// ---------------------------------------------------------------------------------------- void GeneticLoad::inheritDiploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { auto it = recomPositions.lower_bound(parentGenes.begin()->first); int nextBreakpoint = *it; auto distance = std::distance(recomPositions.begin(), it); if (distance % 2 != 0) - parentChromosome = 1 - parentChromosome; // switch to the other one - // use 1-parentChromosome, or switch to a sex_t ? + parentChromosome = 1 - parentChromosome; // switch chromosome for (auto const& [locus, allelePair] : parentGenes) { + + // Switch chromosome if locus is past recombination site while (locus > nextBreakpoint) { std::advance(it, 1); nextBreakpoint = *it; - parentChromosome = 1 - parentChromosome; // switch to the other one + parentChromosome = 1 - parentChromosome; } - if (locus <= nextBreakpoint) { - auto& allele = allelePair[parentChromosome]; - auto it = genes.find(locus); - if (it == genes.end()) { - // locus does not exist yet, initiate it + if (locus <= nextBreakpoint) { + auto& parentAllele = allelePair[parentChromosome]; + auto itGene = genes.find(locus); + if (itGene == genes.end()) { + // locus does not exist yet, create and initialise it if (!fromMother) throw runtime_error("Father-inherited locus does not exist."); vector> newAllelePair(2); // always diploid - newAllelePair[sex_t::FEM] = allele; + newAllelePair[sex_t::FEM] = parentAllele; genes.insert(make_pair(locus, newAllelePair)); } else { // father, locus already exists if (fromMother) throw runtime_error("Mother-inherited locus already exists."); - it->second[sex_t::MAL] = allele; + itGene->second[sex_t::MAL] = parentAllele; } } } } +// ---------------------------------------------------------------------------------------- +// Inheritance for haploid, asexual species +// Simply pass down parent genes +// Arguments are still needed to match overloaded function in base class +// ---------------------------------------------------------------------------------------- void GeneticLoad::inheritHaploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { genes = parentGenes; } // ---------------------------------------------------------------------------------------- -// expression options +// Expression genetic load +// +// // ---------------------------------------------------------------------------------------- - float GeneticLoad::express() { - float phenotype = 1.0; + float phenotype = 1.0; // base chance of viability for (auto const& [locus, pAllelePair] : genes) { - - // If not initialised yet, initialise now? + // If not initialised yet, initialise now shared_ptr pAlleleLeft = pAllelePair[0] == 0 ? wildType : pAllelePair[0]; shared_ptr pAlleleRight = pAllelePair[1] == 0 ? wildType : pAllelePair[1]; @@ -358,12 +344,11 @@ float GeneticLoad::express() { } // ---------------------------------------------------------------------------------------- -// check if particular locus is heterozygote +// Check if specific locus is heterozygote // ---------------------------------------------------------------------------------------- bool GeneticLoad::isHeterozygoteAtLocus(int locus) const { // assumes diploidy auto it = genes.find(locus); - if (it == genes.end()) throw runtime_error("Genetic load gene queried for heterozygosity does not exist."); else { @@ -374,7 +359,7 @@ bool GeneticLoad::isHeterozygoteAtLocus(int locus) const { } // ---------------------------------------------------------------------------------------- -// count heterozygote loci in genome +// Count heterozygote loci in genome // ---------------------------------------------------------------------------------------- int GeneticLoad::countHeterozygoteLoci() const { // assumes diploidy @@ -388,10 +373,8 @@ int GeneticLoad::countHeterozygoteLoci() const { } // ---------------------------------------------------------------------------------------- -// get allele value at loci +// Get allele value at locus // ---------------------------------------------------------------------------------------- - - float GeneticLoad::getAlleleValueAtLocus(short whichChromosome, int position) const { auto it = genes.find(position); diff --git a/GeneticLoad.h b/GeneticLoad.h index 0e85e21..a85861c 100644 --- a/GeneticLoad.h +++ b/GeneticLoad.h @@ -11,58 +11,70 @@ using namespace std; +// Genetic Load trait +// +// Alleles contribute to their value to reducing +// offspring viability. Alleles start with value +// zero but increase through simulation via mutations. +// There can be up to five genetic load traits. class GeneticLoad : public TTrait { -private: - - SpeciesTrait* pSpeciesTrait; - - map>> genes; // position > - - inline static shared_ptr wildType = make_shared(0.0, 0.0); - - // void (AdaptiveTrait::* _mutate_func_ptr) (void); - void (GeneticLoad::* _inherit_func_ptr) (const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); - //float (AdaptiveTrait::* _express_func_ptr) (void); - - void initialise(); - - void inheritDiploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); - void inheritHaploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); - - float drawDominance(float); - float drawSelectionCoef(); - public: - //this one for species held trait table, e.g. prototype table, sets static members - + // Initialisation constructor, set initial values and immutable features GeneticLoad(SpeciesTrait* P); - //this one for individuals, static members are not reset + // Inheritance constructor, copies pointers to immutable features when cloning from parent GeneticLoad(const GeneticLoad& T); + // Make a shallow copy to pass to offspring trait + // Return new pointer to new trait created by inheritance c'tor + // This avoids copying shared attributes: distributions and parameters virtual unique_ptr clone() const override { return std::make_unique(*this); } - virtual void inherit(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; - - virtual void mutate() override; + virtual ~GeneticLoad() { } + // Getters virtual int getNLoci() const override { return pSpeciesTrait->getPositionsSize(); } - float getMutationRate() const override { return pSpeciesTrait->getMutationRate(); } - bool isInherited() const override { return pSpeciesTrait->isInherited(); } - map>>& getGenes() { return genes; } //returning reference, reciever must be const + map>>& getGenes() { return genes; } // returning reference, reciever must be const - virtual float getAlleleValueAtLocus(short chromosome, int position) const override; + virtual void mutate() override; + virtual float express(); + virtual void inheritGenes(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; + virtual float getAlleleValueAtLocus(short chromosome, int position) const override; virtual int countHeterozygoteLoci() const; - virtual bool isHeterozygoteAtLocus(int locus) const override; - virtual float express(); - virtual ~GeneticLoad() { } +private: + + // Default allele has value 0 and dominance 0 + inline static shared_ptr wildType = make_shared(0.0, 0.0); + + // > + map>> genes; // position > + + // Initialisation + void initialise(); + + // Mutation + float drawDominance(float); + float drawSelectionCoef(); + + // Immutable features, set at initialisation + // and passed down to every subsequent trait copy + //// Species-level trait attributes, invariant across individuals + SpeciesTrait* pSpeciesTrait; + //// Species-level trait functions + void (GeneticLoad::* _inherit_func_ptr) (const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); + + // Possible values for immutable functions + //// Inheritance + void inheritDiploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); + void inheritHaploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); + }; #endif // GENETICLOADH diff --git a/Individual.cpp b/Individual.cpp index 373a210..e4f0c2e 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -111,10 +111,8 @@ set Individual::getTraitTypes() { } //--------------------------------------------------------------------------- - +// Inheritance for diploid, sexual species //--------------------------------------------------------------------------- - - void Individual::inherit(Species* pSpecies, const Individual* mother, const Individual* father) { int events = 0; @@ -127,9 +125,9 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi set maternalRecomPositions; set paternalRecomPositions; - // Determine at which chromosome ends does the genome break + // Determine which parental chromosomes are inherited for (int pos : chromosomeEnds) { - if (pRandom->Bernoulli(0.5)) + if (pRandom->Bernoulli(0.5)) // switch strand for next chromosome maternalRecomPositions.insert(pos); if (pRandom->Bernoulli(0.5)) paternalRecomPositions.insert(pos); @@ -138,7 +136,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi // Draw recombination events for maternal genome if (pSpecies->getRecombinationRate() > 0.0) events = pRandom->Poisson(genomeSize * pSpecies->getRecombinationRate()); - // if poisson exceeds genomeSize, bound to genomeSize? + // if poisson exceeds genomeSize, bound to genomeSize int nbrCrossOvers = events + maternalRecomPositions.size(); if (nbrCrossOvers > genomeSize) { nbrCrossOvers = genomeSize; @@ -163,18 +161,19 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi maternalRecomPositions.insert(genomeSize - 1); paternalRecomPositions.insert(genomeSize - 1); + // Inherit genes for each gene const auto& spTraits = pSpecies->getTraitTypes(); - for (auto const& trait : spTraits) { const auto motherTrait = mother->getTrait(trait); const auto fatherTrait = father->getTrait(trait); - auto newTrait = motherTrait->clone(); // shallow copy, pointer to species trait initialised and empty sequence + auto newTrait = motherTrait->clone(); // shallow copy pointer to species-level attributes - newTrait->inherit(true, motherTrait, maternalRecomPositions, maternalStartingChromosome); + // Inherit from mother first + newTrait->inheritGenes(true, motherTrait, maternalRecomPositions, maternalStartingChromosome); if (newTrait->isInherited()) { // Inherit father trait values - newTrait->inherit(false, fatherTrait, paternalRecomPositions, paternalStartingChromosome); + newTrait->inheritGenes(false, fatherTrait, paternalRecomPositions, paternalStartingChromosome); if (newTrait->getMutationRate() > 0 && pSpecies->areMutationsOn()) newTrait->mutate(); } @@ -186,6 +185,9 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi } } +//--------------------------------------------------------------------------- +// Inheritance for haploid, asexual species +//--------------------------------------------------------------------------- void Individual::inherit(Species* pSpecies, const Individual* mother) { set recomPositions; //not used here cos haploid but need it for inherit function, not ideal int startingChromosome = 0; @@ -197,7 +199,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother) { const auto motherTrait = mother->getTrait(trait); auto newTrait = motherTrait->clone(); // shallow copy, pointer to species trait initialised and empty sequence - newTrait->inherit(true, motherTrait, recomPositions, startingChromosome); + newTrait->inheritGenes(true, motherTrait, recomPositions, startingChromosome); if (newTrait->isInherited()) { if (newTrait->getMutationRate() > 0 && pSpecies->areMutationsOn()) newTrait->mutate(); @@ -210,13 +212,12 @@ void Individual::inherit(Species* pSpecies, const Individual* mother) { } } -// Set genes for individual variation from species initialisation parameters +// Initialise individual trait genes from species-level traits void Individual::setUpGenes(Species* pSpecies, int resol) { // this way to keep spp trait table immutable i.e. not able to call getTraitTable, // could pass it back by value (copy) instead but could be heavy if large map const auto& traitTypes = pSpecies->getTraitTypes(); - for (auto const& traitType : traitTypes) { const auto spTrait = pSpecies->getSpTrait(traitType); @@ -276,7 +277,7 @@ void Individual::setSettlementTraits(Species* pSpecies, bool sexDep) { } -// Inherit genome from parent(s) +// Inherit genome from parent(s), diploid void Individual::inheritTraits(Species* pSpecies, Individual* mother, Individual* father, int resol) { inherit(pSpecies, mother, father); @@ -557,17 +558,13 @@ void Individual::setCRWTraits(Species* pSpecies) { // Get phenotypic transfer by CRW traits trfrCRWTraits Individual::getCRWTraits(void) { - trfrCRWTraits c; c.stepLength = c.rho = 0.0; - + trfrCRWTraits c; c.stepLength = c.rho = 0.0; if (pTrfrData != 0) { - auto& pCRW = dynamic_cast(*pTrfrData); - c.stepLength = pCRW.stepLength; c.rho = pCRW.rho; } - return c; } diff --git a/QTLTrait.cpp b/QTLTrait.cpp index ea9bda5..a9cd3c2 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -1,15 +1,17 @@ #include "QTLTrait.h" // ---------------------------------------------------------------------------------------- -// Species-level constructor -// Sets members and functions that are invariant across individuals +// Initialisation constructor +// Called when initialising community +// Sets up initial values, and immutable attributes (distributions and parameters) +// that are defined at the species-level // ---------------------------------------------------------------------------------------- QTLTrait::QTLTrait(SpeciesTrait* P) { pSpeciesTrait = P; ExpressionType expressionType = pSpeciesTrait->getExpressionType(); - if (!pSpeciesTrait->isInherited()) //there is a trait for individual variation but this isn't inherited variation it's sampled from initial distribution + if (!pSpeciesTrait->isInherited()) // there is a trait for individual variation but this isn't inherited variation it's sampled from initial distribution _inherit_func_ptr = &QTLTrait::reInitialiseGenes; else { _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &QTLTrait::inheritHaploid : &QTLTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance @@ -22,25 +24,25 @@ QTLTrait::QTLTrait(SpeciesTrait* P) case UNIFORM: { if (mutationParameters.count(MAX) != 1) - cout << endl << ("Error:: mutation uniform qtl distribution parameter must contain max value (e.g. max= ) \n"); + throw logic_error("Error:: mutation uniform qtl distribution parameter must contain max value (e.g. max= ) \n"); if (mutationParameters.count(MIN) != 1) - cout << endl << ("Error:: mutation uniform qtl distribution parameter must contain min value (e.g. min= ) \n"); + throw logic_error("Error:: mutation uniform qtl distribution parameter must contain min value (e.g. min= ) \n"); _mutate_func_ptr = &QTLTrait::mutateUniform; break; } case NORMAL: { if (mutationParameters.count(MEAN) != 1) - cout << endl << ("Error:: qtl mutation distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); + throw logic_error("Error:: qtl mutation distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); if (mutationParameters.count(SD) != 1) - cout << endl << ("Error::qtl mutation distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); + throw logic_error("Error::qtl mutation distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); _mutate_func_ptr = &QTLTrait::mutateNormal; break; } default: { - cout << endl << ("Error:: wrong parameter value for qtl mutation model, must be uniform/normal \n"); //unless want to add gamma or negative exp - break; //should return false + throw logic_error("Error:: wrong parameter value for qtl mutation model, must be uniform/normal \n"); //unless want to add gamma or negative exp + break; } } } @@ -52,9 +54,9 @@ QTLTrait::QTLTrait(SpeciesTrait* P) case UNIFORM: { if (initialParameters.count(MAX) != 1) - cout << endl << ("Error:: initial uniform qtl distribution parameter must contain max value (e.g. max= ) \n"); + throw logic_error("Error:: initial uniform qtl distribution parameter must contain max value (e.g. max= ) \n"); if (initialParameters.count(MIN) != 1) - cout << endl << ("Error:: initial uniform qtl distribution parameter must contain min value (e.g. min= ) \n"); + throw logic_error("Error:: initial uniform qtl distribution parameter must contain min value (e.g. min= ) \n"); float maxD = initialParameters.find(MAX)->second; float minD = initialParameters.find(MIN)->second; initialiseUniform(minD, maxD); @@ -63,9 +65,9 @@ QTLTrait::QTLTrait(SpeciesTrait* P) case NORMAL: { if (initialParameters.count(MEAN) != 1) - cout << endl << ("Error:: initial normal qtl distribution parameter must contain mean value (e.g. mean= ) \n"); + throw logic_error("Error:: initial normal qtl distribution parameter must contain mean value (e.g. mean= ) \n"); if (initialParameters.count(SD) != 1) - cout << endl << ("Error:: initial normal qtl distribution parameter must contain sdev value (e.g. sdev= ) \n"); + throw logic_error("Error:: initial normal qtl distribution parameter must contain sdev value (e.g. sdev= ) \n"); float mean = initialParameters.find(MEAN)->second; float sd = initialParameters.find(SD)->second; initialiseNormal(mean, sd); @@ -73,8 +75,8 @@ QTLTrait::QTLTrait(SpeciesTrait* P) } default: { - cout << endl << ("wrong parameter value for parameter \"initialisation of qtl\", must be uniform/normal \n"); - break; //should return false + throw logic_error("wrong parameter value for parameter \"initialisation of qtl\", must be uniform/normal \n"); + break; } } @@ -92,22 +94,25 @@ QTLTrait::QTLTrait(SpeciesTrait* P) } default: { - cout << endl << ("wrong parameter value for parameter \"expression of qtl\", must be average/additive \n"); - break; //should return false + throw logic_error("wrong parameter value for parameter \"expression of qtl\", must be average/additive \n"); + break; } } } // ---------------------------------------------------------------------------------------- -// Individual-level constructor -// Copies members from a species-level reference +// Inheritance constructor +// Copies immutable features from a parent trait +// Only called via clone() // ---------------------------------------------------------------------------------------- - QTLTrait::QTLTrait(const QTLTrait& T) : pSpeciesTrait(T.pSpeciesTrait), _mutate_func_ptr(T._mutate_func_ptr), _inherit_func_ptr(T._inherit_func_ptr), _express_func_ptr(T._express_func_ptr) {} // ---------------------------------------------------------------------------------------- -// mutate uniform +// Sample and apply mutations from a uniform distribution +// +// Mutations drawn only for existing positions, +// that is no new genes are created during simulation // ---------------------------------------------------------------------------------------- void QTLTrait::mutateUniform() { @@ -145,9 +150,10 @@ void QTLTrait::mutateUniform() } // ---------------------------------------------------------------------------------------- -// mutate normal +// Sample and apply mutations from a normal distribution +// Mutations drawn only for existing positions, +// that is no new genes are created during simulation // ---------------------------------------------------------------------------------------- - void QTLTrait::mutateNormal() { const int positionsSize = pSpeciesTrait->getPositionsSize(); @@ -184,19 +190,21 @@ void QTLTrait::mutateNormal() } // ---------------------------------------------------------------------------------------- -// inheritance options +// Wrapper to inheritance function // ---------------------------------------------------------------------------------------- - - -void QTLTrait::inherit(const bool& fromMother, TTrait* parentTrait, set const& recomPositions, int startingChromosome) +void QTLTrait::inheritGenes(const bool& fromMother, TTrait* parentTrait, set const& recomPositions, int startingChromosome) { - auto parentCast = dynamic_cast (parentTrait); //horrible - + auto parentCast = dynamic_cast(parentTrait); // must convert TTrait to QTLTrait const auto& parent_seq = parentCast->getGenes(); - if (parent_seq.size() > 0) //else nothing to inherit, should always be something to inherit with QTL - (this->*_inherit_func_ptr) (fromMother, parent_seq, recomPositions, startingChromosome); + (this->*_inherit_func_ptr)(fromMother, parent_seq, recomPositions, startingChromosome); } +// ---------------------------------------------------------------------------------------- +// Inheritance for diploid, sexual species +// Called once for each parent. Given a list of recombinant sites, +// populates offspring genes with appropriate parent alleles +// Assumes mother genes are inherited first +// ---------------------------------------------------------------------------------------- void QTLTrait::inheritDiploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { auto it = recomPositions.lower_bound(parentGenes.begin()->first); @@ -207,39 +215,47 @@ void QTLTrait::inheritDiploid(const bool& fromMother, map nextBreakpoint) { - std::advance(it, 1); + parentChromosome = 1 - parentChromosome; + std::advance(it, 1); // go to next recombination site nextBreakpoint = *it; - parentChromosome = 1 - parentChromosome; //switch chromosome } if (locus <= nextBreakpoint) { - auto& sp = allelePair[parentChromosome]; - auto it = genes.find(locus); - if (it == genes.end()) { - // locus does not exist yet, initiate it + auto& parentAllele = allelePair[parentChromosome]; + auto itGene = genes.find(locus); + if (itGene == genes.end()) { + // locus does not exist yet, create and initialise it if (!fromMother) throw runtime_error("Father-inherited locus does not exist."); vector> newAllelePair(2); - newAllelePair[sex_t::FEM] = sp; + newAllelePair[sex_t::FEM] = parentAllele; genes.insert(make_pair(locus, newAllelePair)); } else { // father, locus already exists if (fromMother) throw runtime_error("Mother-inherited locus already exists."); - it->second[sex_t::MAL] = sp; + itGene->second[sex_t::MAL] = parentAllele; } } } } +// ---------------------------------------------------------------------------------------- +// Inheritance for haploid, asexual species +// Simply pass down parent genes +// Arguments are still needed to match overloaded function in base class +// ---------------------------------------------------------------------------------------- void QTLTrait::inheritHaploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { genes = parentGenes; } // ---------------------------------------------------------------------------------------- -// 'Inherit' from initialisation parameters, for simulations with individual variation but no inheritance +// Non-inheritance +// For cases where isInherited option is turned off +// In this case, offspring alleles are populated using the initialise functions +// Arguments are still needed to match overloaded function in base class // ---------------------------------------------------------------------------------------- - void QTLTrait::reInitialiseGenes(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); @@ -249,9 +265,9 @@ void QTLTrait::reInitialiseGenes(const bool& fromMother, mapsecond; float minD = initialParameters.find(MIN)->second; initialiseUniform(minD, maxD); @@ -260,9 +276,9 @@ void QTLTrait::reInitialiseGenes(const bool& fromMother, mapsecond; float sd = initialParameters.find(SD)->second; initialiseNormal(mean, sd); @@ -270,18 +286,15 @@ void QTLTrait::reInitialiseGenes(const bool& fromMother, map genePositions = pSpeciesTrait->getGenePositions(); @@ -313,9 +326,8 @@ void QTLTrait::initialiseUniform(float min, float max) { } // ---------------------------------------------------------------------------------------- -// expression options +// QTL gene expression options // ---------------------------------------------------------------------------------------- - float QTLTrait::expressAdditive() { float phenotype = 0.0; @@ -344,26 +356,22 @@ float QTLTrait::expressAverage() { } // ---------------------------------------------------------------------------------------- -// check if particular loci is heterozygote +// Check if specific locus is heterozygote // ---------------------------------------------------------------------------------------- - bool QTLTrait::isHeterozygoteAtLocus(int locus) const { // assumes diploidy auto it = genes.find(locus); if (it == genes.end()) //not found throw runtime_error("QTL gene queried for heterozygosity does not exist."); - else { + else return(it->second[0].get()->getId() != it->second[1].get()->getId()); - } } // ---------------------------------------------------------------------------------------- -// count heterozygote loci in genome +// Count heterozygote loci in genome // ---------------------------------------------------------------------------------------- - int QTLTrait::countHeterozygoteLoci() const { // assumes diploidy - int count = 0; for (auto const& [locus, allelePair] : genes) { if (allelePair.size() == 2) @@ -373,15 +381,12 @@ int QTLTrait::countHeterozygoteLoci() const { } // ---------------------------------------------------------------------------------------- -// get allele value at loci +// Get allele value at locus // ---------------------------------------------------------------------------------------- - float QTLTrait::getAlleleValueAtLocus(short whichChromosome, int position) const { auto it = genes.find(position); - if (it == genes.end()) throw runtime_error("The QTL locus queried for its allele value does not exist."); return it->second[whichChromosome].get()->getAlleleValue(); - } \ No newline at end of file diff --git a/QTLTrait.h b/QTLTrait.h index 86380bd..3248c7e 100644 --- a/QTLTrait.h +++ b/QTLTrait.h @@ -19,15 +19,18 @@ class QTLTrait : public TTrait { public: - // Species-level constructor, initialise + // Initialisation constructor, set initial values and immutable features QTLTrait(SpeciesTrait* P); - // Individual-level constructor, called when new individual is created + // Inheritance constructor, copies pointers to immutable features when cloning from parent QTLTrait(const QTLTrait& T); - virtual ~QTLTrait() { } - + // Make a shallow copy to pass to offspring trait + // Return new pointer to new trait created by inheritance c'tor + // This avoids copying shared attributes: distributions and parameters virtual unique_ptr clone() const override { return std::make_unique(*this); } + + virtual ~QTLTrait() { } // Getters int getNLoci() const override { return pSpeciesTrait->getPositionsSize(); } @@ -38,7 +41,7 @@ class QTLTrait : public TTrait { void mutate() override { (this->*_mutate_func_ptr) (); } float express() override { return (this->*_express_func_ptr) (); } - void inherit(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; + void inheritGenes(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; float getAlleleValueAtLocus(short chromosome, int i) const override; int countHeterozygoteLoci() const; @@ -48,22 +51,31 @@ class QTLTrait : public TTrait { const double QTLDominanceFactor = 1.0; // no dominance for QTL traits (yet?) - // Species-level trait attributes, invariant across individuals - SpeciesTrait* pSpeciesTrait; + // > + map>> genes; - map>> genes; // position > + // Initialisation + void initialiseUniform(float min, float max); + void initialiseNormal(float mean, float sd); + // Immutable features, set at initialisation + // and passed down to every subsequent trait copy + //// Species-level trait attributes, invariant across individuals + SpeciesTrait* pSpeciesTrait; + //// Species-level trait functions void (QTLTrait::* _mutate_func_ptr) (void); void (QTLTrait::* _inherit_func_ptr) (const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); float (QTLTrait::* _express_func_ptr) (void); - void initialiseUniform(float min, float max); - void initialiseNormal(float mean, float sd); + // Possible values for immutable functions + //// Inheritance void inheritDiploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); void inheritHaploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); void reInitialiseGenes(const bool& fromMother, map>> const& parentMutations, set const& recomPositions, int parentChromosome); + //// Mutation void mutateUniform(); void mutateNormal(); + //// Gene expression float expressAverage(); float expressAdditive(); }; diff --git a/SNPTrait.cpp b/SNPTrait.cpp index 7302013..6ff9d03 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -1,7 +1,10 @@ #include "SNPTrait.h" // ---------------------------------------------------------------------------------------- -// for initialising population +// Initialisation constructor +// Called when initialising community +// Sets up initial values, and immutable attributes (distributions and parameters) +// that are defined at the species-level // ---------------------------------------------------------------------------------------- SNPTrait::SNPTrait(SpeciesTrait* P) { @@ -10,6 +13,11 @@ SNPTrait::SNPTrait(SpeciesTrait* P) DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); map mutationParameters = pSpeciesTrait->getMutationParameters(); + // Set default value to user-specified max + wildType = (int)mutationParameters.find(MAX)->second - 1; + if (wildType > SNPvalUpperBound) + throw logic_error("Error:: max number of alleles cannot exceed " + to_string(SNPvalUpperBound) + ".\n"); + _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &SNPTrait::inheritHaploid : &SNPTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance if (mutationDistribution == SSM) @@ -19,65 +27,60 @@ SNPTrait::SNPTrait(SpeciesTrait* P) _mutate_func_ptr = &SNPTrait::mutate_KAM; if (mutationDistribution != SSM && mutationDistribution != KAM) - cout << endl << ("Error:: wrong mutation distribution for neutral markers, must be KAM or SSM \n"); + throw logic_error("Error:: wrong mutation distribution for neutral markers, must be KAM or SSM \n"); if (mutationParameters.count(MAX) != 1) - cout << endl << ("Error:: KAM or SSM mutation distribution parameter must contain max value (e.g. max= ), max cannot exceed 256 \n"); - - wildType = (int)mutationParameters.find(MAX)->second - 1; - - if (wildType > SNPvalUpperBound) - cout << endl << "Error:: max number of alleles cannot exceed " << SNPvalUpperBound << ".\n"; + throw logic_error("Error:: KAM or SSM mutation distribution parameter must contain max value (e.g. max= ), max cannot exceed 256 \n"); DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); map initialParameters = pSpeciesTrait->getInitialParameters(); if (mutationDistribution == SSM && initialDistribution != UNIFORM) - cout << endl << ("Error:: If using SSM mutation model must initialise genome with alleles (microsats) \n"); + throw logic_error("Error:: If using SSM mutation model must initialise genome with alleles (microsats) \n"); switch (initialDistribution) { case UNIFORM: { if (initialParameters.count(MAX) != 1) - cout << endl << "Error:: initial SNP/Microsat distribution parameter must contain one max value if set to UNIFORM (e.g. max= ), max cannot exceed " << SNPvalUpperBound << "\n"; + throw logic_error("Error:: initial SNP/Microsat distribution parameter must contain one max value if set to UNIFORM (e.g. max= ), max cannot exceed " + to_string(SNPvalUpperBound) + "\n"); float maxSNPval = initialParameters.find(MAX)->second; if (maxSNPval > SNPvalUpperBound) { - cout << endl << "Warning:: initial SNP/Microsat distribution parameter max cannot exceed " << SNPvalUpperBound << ", resetting to " << SNPvalUpperBound << "\n"; + throw logic_error("Warning:: initial SNP/Microsat distribution parameter max cannot exceed " + to_string(SNPvalUpperBound) + ", resetting to " + to_string(SNPvalUpperBound) + "\n"); maxSNPval = SNPvalUpperBound; //reserve 255 for wildtype } initialiseUniform(maxSNPval); - break; } - case NONE: - { - break; - } + case NONE: + break; default: { - cout << endl << ("wrong parameter value for parameter \"initialisation of snp/microsat\", must be left as default (#) or uniform \n"); + throw logic_error("wrong parameter value for parameter \"initialisation of snp/microsat\", must be left as default (#) or uniform \n"); break; //should return false } } } // ---------------------------------------------------------------------------------------- -// for creating new individuals +// Inheritance constructor +// Copies immutable features from a parent trait +// Only called via clone() // ---------------------------------------------------------------------------------------- - SNPTrait::SNPTrait(const SNPTrait& T) : pSpeciesTrait(T.pSpeciesTrait), _mutate_func_ptr(T._mutate_func_ptr), _inherit_func_ptr(T._inherit_func_ptr) { - } - // ---------------------------------------------------------------------------------------- // mutate options // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- -// mutate_KAM +// Draw and apply mutations according to a KAM process +// +// Mutations drawn only for existing positions, +// that is no new genes are created during simulation +// KAM = randomly drawn value in 0-MAX, differs from previous value // ---------------------------------------------------------------------------------------- void SNPTrait::mutate_KAM() { @@ -91,31 +94,27 @@ void SNPTrait::mutate_KAM() map mutationParameters = pSpeciesTrait->getMutationParameters(); int maxSNPval = (int)mutationParameters.find(MAX)->second; - if (maxSNPval > SNPvalUpperBound) maxSNPval = SNPvalUpperBound; //reserve max value for wildtype for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); if (NbMut > positionsSize) NbMut = positionsSize; - if (NbMut > 0) { vector mutationPositions; sample(genePositions.begin(), genePositions.end(), std::back_inserter(mutationPositions), NbMut, rng); // without replacement for (int m : mutationPositions) { - mut = (unsigned char)pRandom->IRandom(0, maxSNPval); // draw new mutation, could draw wildtype auto it = genes.find(m); if (it == genes.end()) throw runtime_error("Locus selected for mutation doesn't exist."); - - auto currentChar = it->second[whichChromosome]; //current mutation + auto currentChar = it->second[whichChromosome]; // current allele do { - mut = (unsigned char)pRandom->IRandom(0, maxSNPval); //make sure new value differs from old , could be a problem here with infinite loops - } while (mut == currentChar); + mut = (unsigned char)pRandom->IRandom(0, maxSNPval); + } while (mut == currentChar); // new allele value is different it->second[whichChromosome] = mut; //overwrite with new value } @@ -125,7 +124,12 @@ void SNPTrait::mutate_KAM() // ---------------------------------------------------------------------------------------- -// mutate_SSM +// Draw and apply single-step mutations (SSM) +// +// Mutations drawn only for existing positions, +// that is no new genes are created during simulation +// Increment previous value by 1 or -1, +// unless already 0 (then always +1) or MAX (then always -1) // ---------------------------------------------------------------------------------------- void SNPTrait::mutate_SSM() { @@ -144,24 +148,22 @@ void SNPTrait::mutate_SSM() unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); if (NbMut > positionsSize) NbMut = positionsSize; - if (NbMut > 0) { vector mutationPositions; sample(genePositions.begin(), genePositions.end(), std::back_inserter(mutationPositions), NbMut, rng); for (int m : mutationPositions) { - int mutateForward = pRandom->Bernoulli(0.5); + int mutateUp = pRandom->Bernoulli(0.5); auto it = genes.find(m); if (it == genes.end()) throw runtime_error("Locus selected for mutation doesn't exist."); - auto currentAllele = it->second[whichChromosome]; - if (mutateForward == 1 && currentAllele < maxSNPval) - it->second[whichChromosome] += 1; // shift one char to the right - else if (currentAllele > 0) - it->second[whichChromosome] -= 1; // shift one char to the left - else // current allele is 0 and mutate backwards + if (mutateUp == 1 && currentAllele < maxSNPval) + it->second[whichChromosome] += 1; // one step up + else if (currentAllele > 0) // step down or already max + it->second[whichChromosome] -= 1; // one step down + else // current allele is 0, step up it->second[whichChromosome] += 1; } } @@ -169,60 +171,61 @@ void SNPTrait::mutate_SSM() } // ---------------------------------------------------------------------------------------- -// inheritance options +// Wrapper to inheritance function // ---------------------------------------------------------------------------------------- - -void SNPTrait::inherit(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) +void SNPTrait::inheritGenes(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) { - auto parentCast = dynamic_cast (parent); //horrible - + auto parentCast = dynamic_cast (parent); // must convert TTrait to SNPTrait const auto& parent_seq = parentCast->getGenes(); - if (parent_seq.size() > 0) //else nothing to inherit - (this->*_inherit_func_ptr) (fromMother, parent_seq, recomPositions, startingChromosome); + (this->*_inherit_func_ptr) (fromMother, parent_seq, recomPositions, startingChromosome); } - - +// ---------------------------------------------------------------------------------------- +// Inheritance for diploid, sexual species +// Called once for each parent. Given a list of recombinant sites, +// populates offspring genes with appropriate parent alleles +// Assumes mother genes are inherited first +// ---------------------------------------------------------------------------------------- void SNPTrait::inheritDiploid(const bool& fromMother, map> const& parentGenes, set const& recomPositions, int parentChromosome) { - if (parentGenes.size() > 0) { - auto it = recomPositions.lower_bound(parentGenes.begin()->first); + auto it = recomPositions.lower_bound(parentGenes.begin()->first); + unsigned int nextBreakpoint = *it; + auto distance = std::distance(recomPositions.begin(), it); + if (distance - 1 % 2 != 0) + parentChromosome = 1 - parentChromosome; //switch chromosome - unsigned int nextBreakpoint = *it; + for (auto const& [locus, allelePair] : parentGenes) { - auto distance = std::distance(recomPositions.begin(), it); - if (distance - 1 % 2 != 0) + // Switch chromosome if locus is past recombination site + while (locus > nextBreakpoint) { + std::advance(it, 1); + nextBreakpoint = *it; parentChromosome = 1 - parentChromosome; //switch chromosome + } - - for (auto const& [locus, allelePair] : parentGenes) { - - while (locus > nextBreakpoint) { - std::advance(it, 1); - nextBreakpoint = *it; - parentChromosome = 1 - parentChromosome; //switch chromosome + if (locus <= nextBreakpoint) { + unsigned char sp = allelePair[parentChromosome]; + auto it = genes.find(locus); + if (it == genes.end()) { + // locus does not exist yet, create and initialise it + if (!fromMother) throw runtime_error("Father-inherited locus does not exist."); + vector newAllelePair(2, wildType); + newAllelePair[sex_t::FEM] = sp; + genes.insert(make_pair(locus, newAllelePair)); } - - if (locus <= nextBreakpoint) { - unsigned char sp = allelePair[parentChromosome]; - - auto it = genes.find(locus); - if (it == genes.end()) { - if (!fromMother) throw runtime_error("Father-inherited locus does not exist."); - // not found - vector newAllelePair(2, wildType); - newAllelePair[sex_t::FEM] = sp; - genes.insert(make_pair(locus, newAllelePair)); - } - else { - if (fromMother) throw runtime_error("Mother-inherited locus already exists."); - it->second[sex_t::MAL] = sp; - } + else { // father, locus already exists + if (fromMother) throw runtime_error("Mother-inherited locus already exists."); + it->second[sex_t::MAL] = sp; } } } } +// ---------------------------------------------------------------------------------------- +// Inheritance for haploid, asexual species +// Simply pass down parent genes +// Arguments are still needed to match overloaded function in base class +// ---------------------------------------------------------------------------------------- void SNPTrait::inheritHaploid(const bool& fromMother, map> const& parentGenes, set const& recomPositions, int parentChromosome) { genes = parentGenes; @@ -231,7 +234,6 @@ void SNPTrait::inheritHaploid(const bool& fromMother, mapgetGenePositions(); @@ -241,7 +243,8 @@ void SNPTrait::initialiseUniform(int maxAlleleVal) vector allelePair; for (int i = 0; i < ploidy; i++) { - auto alleleVal = (unsigned char)pRandom->IRandom(0, maxAlleleVal); // allele values span 0 - max (255 ceiling) inclusive, max == wildtype + // allele values span 0 - max inclusive, max is wildtype + auto alleleVal = (unsigned char)pRandom->IRandom(0, maxAlleleVal); allelePair.emplace_back(alleleVal); } genes.insert(make_pair(position, allelePair)); @@ -250,21 +253,20 @@ void SNPTrait::initialiseUniform(int maxAlleleVal) // ---------------------------------------------------------------------------------------- -// check if particular loci is heterozygote +// Check if particular loci is heterozygote // ---------------------------------------------------------------------------------------- - - bool SNPTrait::isHeterozygoteAtLocus(int locus) const { // assumes diploidy auto it = genes.find(locus); - if (it == genes.end()) throw runtime_error("SNP gene queried for heterozygosity does not exist."); - else return(it->second[0] != it->second[1]); + if (it == genes.end()) + throw runtime_error("SNP gene queried for heterozygosity does not exist."); + else + return(it->second[0] != it->second[1]); } // ---------------------------------------------------------------------------------------- -// count heterozygote loci in genome +// Count heterozygote loci in genome // ---------------------------------------------------------------------------------------- - int SNPTrait::countHeterozygoteLoci() const { // assumes diploidy int count = 0; @@ -275,10 +277,8 @@ int SNPTrait::countHeterozygoteLoci() const { } // ---------------------------------------------------------------------------------------- -// get allele value at loci +// Get allele value at loci // ---------------------------------------------------------------------------------------- - - float SNPTrait::getAlleleValueAtLocus(short whichChromosome, int position) const { auto it = genes.find(position); diff --git a/SNPTrait.h b/SNPTrait.h index 542787f..2e258c0 100644 --- a/SNPTrait.h +++ b/SNPTrait.h @@ -10,53 +10,73 @@ using namespace std; +// Single-nucleotide polymorphism (SNP) traits +// +// That is, neutral genetic variation - SNP traits +// do not express and are only used to compute neutral statistics +// e.g. the Fst. +// To save on mem usage, allele values are represented by character types, +// taking a value between 0 and a user-specified max >= 255 class SNPTrait : public TTrait { -private: - - inline static int wildType; - const int SNPvalUpperBound = UCHAR_MAX; // i.e. 256 - // allele is char, can take value 0-255 - - SpeciesTrait* pSpeciesTrait; - - map> genes; //position > - - void (SNPTrait::* _mutate_func_ptr) (void); - void (SNPTrait::* _inherit_func_ptr) (const bool& fromMother, map> const& parent, set const& recomPositions, int parentChromosome); - - void inheritDiploid(const bool& fromMother, map> const&, set const& recomPositions, int parentChromosome); - void inheritHaploid(const bool& fromMother, map> const& parentMutations, set const& recomPositions, int parentChromosome); - - void initialiseUniform(int max); //other option is that mutations map is empty until a mutation happens, default when empty is to return a 0 value for wildtype - - void mutate_KAM(); - void mutate_SSM(); - public: - //this one for species held trait table, e.g. prototype table, sets static members + + // Initialisation constructor, set initial values and immutable features SNPTrait(SpeciesTrait* P); - //this one for individuals, static members are not reset - SNPTrait(const SNPTrait& T); - virtual ~SNPTrait() { } + // Inheritance constructor, copies pointers to immutable features when cloning from parent + SNPTrait(const SNPTrait& T); + // Make a shallow copy to pass to offspring trait + // Return new pointer to new trait created by inheritance c'tor + // This avoids copying shared attributes: distributions and parameters virtual unique_ptr clone() const override { return std::make_unique(*this); } - virtual void inherit(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; - virtual void mutate() override { (this->*_mutate_func_ptr) (); } + virtual ~SNPTrait() { } + // Getters virtual int getNLoci() const override { return pSpeciesTrait->getPositionsSize(); } float getMutationRate() const override { return pSpeciesTrait->getMutationRate(); } bool isInherited() const override { return pSpeciesTrait->isInherited(); } map>& getGenes() { return genes; } //returning reference, reciever must be const - virtual float getAlleleValueAtLocus(short chromosome, int position) const override; + virtual void mutate() override { (this->*_mutate_func_ptr) (); } + virtual void inheritGenes(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; + virtual float express() { + throw runtime_error("SNP trait shouldn't be expressed."); + return -9999; + } + virtual float getAlleleValueAtLocus(short chromosome, int position) const override; virtual int countHeterozygoteLoci() const; - virtual bool isHeterozygoteAtLocus(int locus) const override; - virtual float express() { return -9999; } +private: + + inline static int wildType; // default allele value, value set at construction + const int SNPvalUpperBound = UCHAR_MAX; // alleles are char, can take value 0-255 + + // > + map> genes; + + // Initialisation + void initialiseUniform(int max); //other option is that mutations map is empty until a mutation happens, default when empty is to return a 0 value for wildtype + + // Immutable features, set at initialisation + // and passed down to every subsequent trait copy + //// Species-level trait attributes, invariant across individuals + SpeciesTrait* pSpeciesTrait; + //// Species-level trait functions + void (SNPTrait::* _mutate_func_ptr) (void); + void (SNPTrait::* _inherit_func_ptr) (const bool& fromMother, map> const& parent, set const& recomPositions, int parentChromosome); + + // Possible values for immutable functions + //// Inheritance + void inheritDiploid(const bool& fromMother, map> const&, set const& recomPositions, int parentChromosome); + void inheritHaploid(const bool& fromMother, map> const& parentMutations, set const& recomPositions, int parentChromosome); + //// Mutation + void mutate_KAM(); + void mutate_SSM(); // single-step mutations + }; #endif \ No newline at end of file diff --git a/TTrait.h b/TTrait.h index 8b8a084..2c42a9c 100644 --- a/TTrait.h +++ b/TTrait.h @@ -16,7 +16,7 @@ class TTrait { public: virtual void mutate() = 0; virtual unique_ptr clone() const = 0; //copies parameters (if not static) not gene seqeunces - virtual void inherit(const bool&, TTrait*, set const& , int ) = 0; + virtual void inheritGenes(const bool&, TTrait*, set const& , int ) = 0; virtual int getNLoci() const = 0; virtual float getMutationRate() const = 0; virtual bool isInherited() const = 0; From 9b73522f59fd8273ed6a32aa7935823905de2496 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 26 Apr 2024 12:10:35 +0100 Subject: [PATCH 106/332] progress with doc of neutral stats --- Landscape.cpp | 3 +- NeutralStatsManager.cpp | 27 +++------------ NeutralStatsManager.h | 76 ++++++++++++++++++++--------------------- Population.cpp | 4 +-- Population.h | 2 +- 5 files changed, 45 insertions(+), 67 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index e63b1dc..fedfed8 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -874,9 +874,8 @@ set Landscape::samplePatches(const string& samplingOption, int nbToSample, vector sampledPatches; vector occupiedPatches; - // Get list of viable patches + // Get list of viable patches where the species is present for (auto p : patches) { - // p->getPopn(); if (p->speciesIsPresent(pSpecies)) occupiedPatches.push_back(p->getPatchNum()); } diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 6be76b8..c550047 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -48,7 +48,7 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand } else { // populate the tables with default values for (int thisLocus = 0; thisLocus < nLoci; thisLocus++) { - SNPtable newSNPtbl = SNPtable(nAlleles); + SNPCountsTable newSNPtbl = SNPCountsTable(nAlleles); commSNPTables.push_back(newSNPtbl); } } @@ -82,7 +82,7 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand // Update global frequency std::for_each(commSNPTables.begin(), commSNPTables.end(), - [&](SNPtable& v) -> void { + [&](SNPCountsTable& v) -> void { v.setFrequencies(nbSampledInds * ploidy); }); } @@ -90,18 +90,15 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand // ---------------------------------------------------------------------------------------- // Reset allele tables in SNPtable structs // ---------------------------------------------------------------------------------------- - void NeutralStatsManager::resetCommSNPtables() { for (auto& entry : commSNPTables) { entry.reset(); } } - // ---------------------------------------------------------------------------------------- // set loci diversity // ---------------------------------------------------------------------------------------- - void NeutralStatsManager::setLociDiversityCounter(set const& patchList, const int nInds, Species* pSpecies, Landscape* pLandscape) { int i, j; @@ -202,8 +199,6 @@ void NeutralStatsManager::calculateHo(set const& patchList, const int nbInd // ---------------------------------------------------------------------------------------- // calculate Hs per Nei and Chesser, currently not used but may be useful // ---------------------------------------------------------------------------------------- - - void NeutralStatsManager::calculateHs(set const& patchList, const int nbrLoci, Species* pSpecies, Landscape* pLandscape) { double hs = 0; @@ -226,8 +221,6 @@ void NeutralStatsManager::calculateHs(set const& patchList, const int nbrLo // ---------------------------------------------------------------------------------------- // calculate Ht per Nei and Chesser, currently not used but may be useful // ---------------------------------------------------------------------------------------- - - void NeutralStatsManager::calculateHt(Species* pSpecies, Landscape* pLandscape, const int nLoci, const int nAlleles) { double ht = 0; @@ -255,7 +248,6 @@ void NeutralStatsManager::calculateHt(Species* pSpecies, Landscape* pLandscape, // ---------------------------------------------------------------------------------------- // calculate Ho per locus as per Nei and Chesser // ---------------------------------------------------------------------------------------- - void NeutralStatsManager::calculateHo2(set const& patchList, const int nbInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape) { vector hetero(nbrLoci, 0); @@ -281,12 +273,9 @@ void NeutralStatsManager::calculateHo2(set const& patchList, const int nbIn perLocusHo = hetero; } - // ---------------------------------------------------------------------------------------- // Fstat Weir & Cockerham // ---------------------------------------------------------------------------------------- - - void NeutralStatsManager::calculateFstatWC(set const& patchList, const int nbSampledIndsInComm, const int nLoci, const int nAlleles, Species* pSpecies, Landscape* pLandscape) { double inverseNtotal; @@ -369,11 +358,9 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int } } - // ---------------------------------------------------------------------------------------- // Fstat Weir & Cockerham using Mean square approach. Similar to implementation in Hierfstat // ---------------------------------------------------------------------------------------- - void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const int nInds, const int nLoci, const int maxNbAllelesPerLocus, Species* pSpecies, Landscape* pLandscape) { double sumWeights = 0; @@ -542,14 +529,12 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i } } - // ---------------------------------------------------------------------------------------- // Patch pairwise Fst // Computes the weighted within and between patch Fst's as well as the overall Fst (Theta). -// The method used here is that of Weir& Hill 2002, Ann.Rev.Genet. 36:721 - 750. +// The method used here is that of Weir& Hill 2002, Ann.Rev.Genet. 36:721 - 750. // The weighting is done for samples(patches) of unequal sizes. // ---------------------------------------------------------------------------------------- - void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape) { const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; @@ -567,7 +552,7 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd pairwiseFstMatrix = PatchMatrix(nPatches, nPatches); // Reset table - pairwiseFstMatrix.assign(0.0); // or nanf("NULL")? + pairwiseFstMatrix.setAll(0.0); // or nanf("NULL")? //init vector popWeights(nPatches); @@ -685,7 +670,3 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd } } - - - - diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index 09f4dad..6b5f2ac 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -6,80 +6,78 @@ using namespace std; -/**Creates an array of doubles of size = rows*cols, taken from NEMO**/ +// Patch * patch matrix to store pairwise Fst calculations +/** Creates an array of doubles of size = rows*cols, taken from NEMO **/ struct PatchMatrix { -private: - unsigned int rows, cols, nbCells; - vector value; - public: - PatchMatrix(int rows = 0, int cols = 0) : rows(0), cols(0), nbCells(0), value(0) { nbCells = rows * cols; value.resize(nbCells); rows = rows; cols = cols; }; - - /**Assigns a value to all element of the matrix.*/ - void assign(double val) - { - for (unsigned int i = 0; i < nbCells; ++i) value[i] = val; + // Get value at specified position + double get(unsigned int i, unsigned int j) { + if (!((i + 1) * (j + 1) > nbCells)) + return value[i * cols + j]; + else throw runtime_error("Error: PatchMatrix::get() out of range!\n"); + return 0; } int getNbCells() { return nbCells; }; - /**Sets element at row i and column j to value val**/ + /** Sets element at row i and column j to value val **/ void set(unsigned int i, unsigned int j, double val) { if (i * j < nbCells) value[i * cols + j] = val; - else - cout << endl << ("Error: PatchMatrix::set() out of range!\n"); + else throw runtime_error("Error: PatchMatrix::set() out of range!\n"); } - double get(unsigned int i, unsigned int j) { - if (!((i + 1) * (j + 1) > nbCells)) - return value[i * cols + j]; - else - cout << endl << ("Error: PatchMatrix::get() out of range!\n"); - return 0; + /** Assigns a value to all elements of the matrix. */ + void setAll(double val) + { + for (unsigned int i = 0; i < nbCells; ++i) value[i] = val; } -}; - - -struct SNPtable { private: - vector alleleTallies; - vector alleleFrequencies; - vector alleleHeterozygoteTallies; - -public: - //for population allele tables - SNPtable(int nAllele) : alleleTallies(nAllele), alleleFrequencies(nAllele), alleleHeterozygoteTallies(nAllele) {}; + unsigned int rows, cols, nbCells; + vector value; +}; - void setFrequencies(int sampleSize) { - for (int i = 0; i < alleleFrequencies.size(); i++) { - alleleFrequencies[i] = sampleSize > 0 ? static_cast(alleleTallies[i]) / sampleSize : 0.0; - } - }; +// Counts of SNP allele occurrences in populations +// for neutral statistics calculations +struct SNPCountsTable { +public: + SNPCountsTable(int nAllele) : alleleTallies(nAllele), alleleFrequencies(nAllele), alleleHeterozygoteTallies(nAllele) {}; + void reset() { fill(alleleTallies.begin(), alleleTallies.end(), 0); fill(alleleFrequencies.begin(), alleleFrequencies.end(), 0); fill(alleleHeterozygoteTallies.begin(), alleleHeterozygoteTallies.end(), 0); } + // Getters int getTally(int whichAllele) { return alleleTallies[whichAllele]; }; double getFrequency(int whichAllele) { return alleleFrequencies[whichAllele]; }; int getHeteroTally(int whichAllele) { return alleleHeterozygoteTallies[whichAllele]; }; + // Setters / increments void incrementTally(int whichAllele) { alleleTallies[whichAllele]++; }; void incrementTallyBy(int count, int whichAllele) { this->alleleTallies[whichAllele] += count; } void incrementHeteroTally(int whichAllele) { this->alleleHeterozygoteTallies[whichAllele]++; } -}; - + void setFrequencies(int sampleSize) { + for (int i = 0; i < alleleFrequencies.size(); i++) { + alleleFrequencies[i] = sampleSize > 0 ? static_cast(alleleTallies[i]) / sampleSize : 0.0; + } + }; +private: + // Tallies, one for each possible allele (so absolute max size is 255) + vector alleleTallies; // number of occurrences of each allele in pop + vector alleleFrequencies; // frequency of each allele in pop + vector alleleHeterozygoteTallies; // nb of times each allele is found in a heterozygous pair +}; class NeutralStatsManager { @@ -97,7 +95,7 @@ class NeutralStatsManager { /** Pairwise Fst matrix. */ PatchMatrix pairwiseFstMatrix; - vector commSNPTables; //don't have to be pointers, not shared or moved + vector commSNPTables; //don't have to be pointers, not shared or moved public: diff --git a/Population.cpp b/Population.cpp index 1b143e4..c14ae01 100644 --- a/Population.cpp +++ b/Population.cpp @@ -343,7 +343,7 @@ void Population::updatePopSNPtables() { popSNPtables.reserve(nLoci); for (int l = 0; l < nLoci; l++) { - popSNPtables.push_back(SNPtable(nAlleles)); + popSNPtables.push_back(SNPCountsTable(nAlleles)); } } @@ -375,7 +375,7 @@ void Population::updatePopSNPtables() { std::for_each( popSNPtables.begin(), popSNPtables.end(), - [&](SNPtable& thisLocus) -> void { + [&](SNPCountsTable& thisLocus) -> void { thisLocus.setFrequencies(static_cast(sampledInds.size()) * ploidy); }); } diff --git a/Population.h b/Population.h index b405e27..08d7378 100644 --- a/Population.h +++ b/Population.h @@ -241,7 +241,7 @@ class Population { // has been completed std::set sampledInds; - vector popSNPtables; + vector popSNPtables; void resetPopSNPtables(); }; From 96e0496f4fdc03dd8076d952cb6d0e43b7aaa909 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 26 Apr 2024 17:49:15 +0100 Subject: [PATCH 107/332] doc neutral stats --- Community.cpp | 16 ++-- NeutralStatsManager.cpp | 172 ++++++++++++++++++++-------------------- NeutralStatsManager.h | 102 ++++++++++++++---------- Population.cpp | 52 ++++++------ Population.h | 4 +- 5 files changed, 182 insertions(+), 164 deletions(-) diff --git a/Community.cpp b/Community.cpp index 88a17a6..d9ad95d 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1779,10 +1779,10 @@ void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const outperlocusfstat << yr << "\t" << gen << "\t" << position << "\t"; - outperlocusfstat << pNeutralStatistics->get_fst_WC_loc(thisLocus) << "\t" - << pNeutralStatistics->get_fis_WC_loc(thisLocus) << "\t" - << pNeutralStatistics->get_fit_WC_loc(thisLocus) << "\t" - << pNeutralStatistics->get_ho_loc(thisLocus); + outperlocusfstat << pNeutralStatistics->getPerLocusFst(thisLocus) << "\t" + << pNeutralStatistics->getPerLocusFis(thisLocus) << "\t" + << pNeutralStatistics->getPerLocusFit(thisLocus) << "\t" + << pNeutralStatistics->getPerLocusHo(thisLocus); for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); @@ -1873,19 +1873,19 @@ void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, if (fstat) { pNeutralStatistics->calculateHo(patchList, nInds, nLoci, pSpecies, pLandscape); - pNeutralStatistics->setLociDiversityCounter(patchList, nInds, pSpecies, pLandscape); + pNeutralStatistics->calcAllelicDiversityMetrics(patchList, nInds, pSpecies, pLandscape); pNeutralStatistics->calculateFstatWC(patchList, nInds, nLoci, nAlleles, pSpecies, pLandscape); writeWCFstatFile(rep, yr, gen); } if (perLocus) { - pNeutralStatistics->calculateFstatWC_MS(patchList, nInds, nLoci, nAlleles, pSpecies, pLandscape); - pNeutralStatistics->calculateHo2(patchList, nInds, nLoci, pSpecies, pLandscape); + pNeutralStatistics->calcPerLocusMeanSquaresFst(patchList, nInds, nLoci, nAlleles, pSpecies, pLandscape); + pNeutralStatistics->calculatePerLocusHo(patchList, nInds, nLoci, pSpecies, pLandscape); writeWCPerLocusFstatFile(pSpecies, yr, gen, nAlleles, nLoci, patchList); } if (pairwise) { - pNeutralStatistics->setFstMatrix(patchList, nInds, nLoci, pSpecies, pLandscape); + pNeutralStatistics->calcPairwiseWeightedFst(patchList, nInds, nLoci, pSpecies, pLandscape); writePairwiseFSTFile(pSpecies, yr, gen, nAlleles, nLoci, patchList); } } diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index c550047..ca46a56 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -25,37 +25,38 @@ --------------------------------------------------------------------------*/ // ---------------------------------------------------------------------------------------- - // Cstor + // Constructor // ---------------------------------------------------------------------------------------- - NeutralStatsManager::NeutralStatsManager(const int& nbSampledPatches, const int nLoci) { this->pairwiseFstMatrix = PatchMatrix(nbSampledPatches, nbSampledPatches); - commSNPTables.reserve(nLoci); //don't have to be pointers, not shared or moved + commSNPCountTables.reserve(nLoci); //don't have to be pointers, not shared or moved } // ---------------------------------------------------------------------------------------- -// Set allele tables in SNPtable structs +// Populate population and community-level SNP count tables +// Update allele occurrence and heterozygosity counts, and allele frequencies // ---------------------------------------------------------------------------------------- - void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLandscape, set const& patchList) { const int nLoci = pSpecies->getNPositionsForTrait(SNP); const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; const int ploidy = pSpecies->isDiploid() ? 2 : 1; - if (!commSNPTables.empty()) { + // Create / Update community-level SNP counts table + if (!commSNPCountTables.empty()) { resetCommSNPtables(); } else { // populate the tables with default values for (int thisLocus = 0; thisLocus < nLoci; thisLocus++) { SNPCountsTable newSNPtbl = SNPCountsTable(nAlleles); - commSNPTables.push_back(newSNPtbl); + commSNPCountTables.push_back(newSNPtbl); } } int nbSampledInds = 0; int patchAlleleCount; + // Update counts for each population for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); @@ -64,7 +65,7 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand pPop->updatePopSNPtables(); nbSampledInds += pPop->sampleSize(); } - // Update global SNP counts tables + // Add population-level counts to community-level counts for (int thisLocus = 0; thisLocus < nLoci; thisLocus++) { for (int allele = 0; allele < nAlleles; allele++) { @@ -74,14 +75,14 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand else { patchAlleleCount = 0; } - commSNPTables[thisLocus].incrementTallyBy(patchAlleleCount, allele); + commSNPCountTables[thisLocus].incrementTallyBy(patchAlleleCount, allele); } } } - // Update global frequency - std::for_each(commSNPTables.begin(), - commSNPTables.end(), + // Update community-level frequencies + std::for_each(commSNPCountTables.begin(), + commSNPCountTables.end(), [&](SNPCountsTable& v) -> void { v.setFrequencies(nbSampledInds * ploidy); }); @@ -91,15 +92,15 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand // Reset allele tables in SNPtable structs // ---------------------------------------------------------------------------------------- void NeutralStatsManager::resetCommSNPtables() { - for (auto& entry : commSNPTables) { + for (auto& entry : commSNPCountTables) { entry.reset(); } } // ---------------------------------------------------------------------------------------- -// set loci diversity +// Calculate allelic diversity metrics // ---------------------------------------------------------------------------------------- -void NeutralStatsManager::setLociDiversityCounter(set const& patchList, const int nInds, Species* pSpecies, Landscape* pLandscape) +void NeutralStatsManager::calcAllelicDiversityMetrics(set const& patchList, const int nInds, Species* pSpecies, Landscape* pLandscape) { int i, j; const int nLoci = pSpecies->getNPositionsForTrait(SNP); @@ -111,16 +112,14 @@ void NeutralStatsManager::setLociDiversityCounter(set const& patchList, con bool alleleExistsInPop = 0; bool** alleleExistsInCommTable; - - // number of alleles per locus, Patch and pop counters: alleleExistsInCommTable = new bool* [nLoci]; - for (i = 0; i < nLoci; ++i) { alleleExistsInCommTable[i] = new bool[nAlleles]; for (j = 0; j < nAlleles; ++j) alleleExistsInCommTable[i][j] = 0; } + // Compute mean nb alleles per locus per patch for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); @@ -141,7 +140,7 @@ void NeutralStatsManager::setLociDiversityCounter(set const& patchList, con } meanNbAllelesPerLocusPerPatch = nbPopulatedPatches > 0 ? meanAllelicDivInPatch / nbPopulatedPatches : 0; - // Compute mean allelic diversity per locus + // Compute mean nb alleles per locus meanNbAllelesPerLocus = 0; for (i = 0; i < nLoci; ++i) for (j = 0; j < nAlleles; ++j) @@ -172,32 +171,33 @@ void NeutralStatsManager::setLociDiversityCounter(set const& patchList, con nbGloballyFixedAlleles = 0; for (i = 0; i < nLoci; ++i) for (j = 0; j < nAlleles; ++j) - nbGloballyFixedAlleles += commSNPTables[i].getFrequency(j) == 1; + nbGloballyFixedAlleles += commSNPCountTables[i].getFrequency(j) == 1; } // ---------------------------------------------------------------------------------------- -// calculate Ho per Nei and Chesser +// Calculate Ho per Nei and Chesser +// Average (observed) heterozygosity per individual +// Sum (nb of heterozygote loci) across individuals / nb individuals / nb loci // ---------------------------------------------------------------------------------------- void NeutralStatsManager::calculateHo(set const& patchList, const int nbInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape) { int nbHetero = 0; - int nLoci = nbInds * nbrLoci; - if (nLoci != 0 && pSpecies->isDiploid()) { + if (nbInds != 0 && pSpecies->isDiploid()) { for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - if (pPop != 0) { - nbHetero += pPop->countHeterozygoteLoci(); - } + if (pPop != 0) nbHetero += pPop->countHeterozygoteLoci(); } - _ho = static_cast(nbHetero) / nLoci; + ho = static_cast(nbHetero) / (nbInds * nbrLoci); } - else _ho = 0.0; + else ho = 0.0; } // ---------------------------------------------------------------------------------------- -// calculate Hs per Nei and Chesser, currently not used but may be useful +// Calculate Hs per Nei and Chesser +// Average expected population-level heterozygosity per locus per population +// currently not used but may be useful // ---------------------------------------------------------------------------------------- void NeutralStatsManager::calculateHs(set const& patchList, const int nbrLoci, Species* pSpecies, Landscape* pLandscape) { @@ -207,19 +207,18 @@ void NeutralStatsManager::calculateHs(set const& patchList, const int nbrLo for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - if (pPop->sampleSize() > 0) { nPatches++; hs += pPop->computeHs(); } } - - _hs = (nPatches != 0 ? hs / (nbrLoci * nPatches) : 0.0); - + hs = (nPatches != 0 ? hs / (nbrLoci * nPatches) : 0.0); } // ---------------------------------------------------------------------------------------- -// calculate Ht per Nei and Chesser, currently not used but may be useful +// Calculate Ht per Nei and Chesser +// Average expected community-level heterozygosity per locus +// Currently not used but may be useful // ---------------------------------------------------------------------------------------- void NeutralStatsManager::calculateHt(Species* pSpecies, Landscape* pLandscape, const int nLoci, const int nAlleles) { @@ -229,28 +228,25 @@ void NeutralStatsManager::calculateHt(Species* pSpecies, Landscape* pLandscape, double freq; for (int thisLocus = 0; thisLocus < nLoci; ++thisLocus) { - for (int allele = 0; allele < nAlleles; ++allele) { - - freq = commSNPTables[thisLocus].getFrequency(allele); - + freq = commSNPCountTables[thisLocus].getFrequency(allele); freq *= freq; //squared frequencies - locihet[thisLocus] -= freq; //1 - sum of p2 = expected heterozygosity } - ht += locihet[thisLocus]; } - - _ht = ht / nLoci; + ht = ht / nLoci; } // ---------------------------------------------------------------------------------------- -// calculate Ho per locus as per Nei and Chesser +// Calculate Ho per locus as per Nei and Chesser +// Observed proportion of heterozygote individuals for each locus +// Sum (nb of heterozygote individuals) / nb individuals for each locus // ---------------------------------------------------------------------------------------- -void NeutralStatsManager::calculateHo2(set const& patchList, const int nbInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape) { +void NeutralStatsManager::calculatePerLocusHo(set const& patchList, const int nbInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape) { - vector hetero(nbrLoci, 0); + vector nbHeterosInComm(nbrLoci, 0); + vector nbHeterosInPop(nbrLoci); if (pSpecies->isDiploid()) { for (int patchId : patchList) { @@ -258,19 +254,21 @@ void NeutralStatsManager::calculateHo2(set const& patchList, const int nbIn const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop != 0) { if (pPop->sampleSize() > 0) { - const vector heteroPatch = pPop->countLociHeterozyotes(); - transform(hetero.begin(), hetero.end(), heteroPatch.begin(), - hetero.begin(), plus()); + nbHeterosInPop = pPop->countNbHeterozygotesEachLocus(); + // Add counts to community total + transform(nbHeterosInComm.begin(), nbHeterosInComm.end(), nbHeterosInPop.begin(), + nbHeterosInComm.begin(), plus()); } } } } - if (nbInds != 0) - for (double h : hetero) { - h /= nbInds; + perLocusHo = vector(nbrLoci, 0); + if (nbInds != 0) { + for (int i = 0; i < nbHeterosInComm.size(); i++) { + perLocusHo[i] = static_cast(nbHeterosInComm[i]) / nbInds; } - perLocusHo = hetero; + } } // ---------------------------------------------------------------------------------------- @@ -320,7 +318,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int for (int allele = 0; allele < nAlleles; ++allele) { s2 = hBar = 0; - pBar = commSNPTables[thisLocus].getFrequency(allele); + pBar = commSNPCountTables[thisLocus].getFrequency(allele); for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); @@ -347,21 +345,21 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int b *= nBar / nBarMinusOne; c *= 0.5; - FstWeirCockerham = a / (a + b + c); // theta hat in eq. 1 in WC 1984 - FitWeirCockerham = (a + b) / (a + b + c); // F hat - FisWeirCockerham = b / (b + c); // f hat + fst = a / (a + b + c); // theta hat in eq. 1 in WC 1984 + fis = (a + b) / (a + b + c); // F hat + fit = b / (b + c); // f hat } else { // zero or one sampled pops, cannot compute F stats - FstWeirCockerham = 0.0; - FitWeirCockerham = 0.0; - FisWeirCockerham = 0.0; + fst = 0.0; + fis = 0.0; + fit = 0.0; } } // ---------------------------------------------------------------------------------------- // Fstat Weir & Cockerham using Mean square approach. Similar to implementation in Hierfstat // ---------------------------------------------------------------------------------------- -void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const int nInds, const int nLoci, const int maxNbAllelesPerLocus, Species* pSpecies, Landscape* pLandscape) { +void NeutralStatsManager::calcPerLocusMeanSquaresFst(set const& patchList, const int nInds, const int nLoci, const int maxNbAllelesPerLocus, Species* pSpecies, Landscape* pLandscape) { double sumWeights = 0; unsigned int nbExtantPops = 0; @@ -381,12 +379,12 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i } // per locus stats, resize should only happen in first timestep of calculation: - if (perLocusFstWeirCockerham.size() == 0) - perLocusFstWeirCockerham.resize(nLoci); - if (perLocusFisWeirCockerham.size() == 0) - perLocusFisWeirCockerham.resize(nLoci); - if (perLocusFitWeirCockerham.size() == 0) - perLocusFitWeirCockerham.resize(nLoci); + if (perLocusFst.size() == 0) + perLocusFst.resize(nLoci); + if (perLocusFis.size() == 0) + perLocusFis.resize(nLoci); + if (perLocusFit.size() == 0) + perLocusFit.resize(nLoci); if (nbExtantPops > 1) { vector nbAllelesEachLocus(nLoci); @@ -440,7 +438,7 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i het = pPop->getHeteroTally(locus, allele); // ni * h_i pi = pPop->getAlleleFrequency(locus, allele); - pBar = commSNPTables[locus].getFrequency(allele); + pBar = commSNPCountTables[locus].getFrequency(allele); var = pi - pBar; //(p_liu - pbar_u)^2 var *= var; @@ -495,21 +493,21 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i locusSIGW += sigw[alleleCounter]; alleleCounter++; } - perLocusFstWeirCockerham[locus] = locusSIGA / (locusSIGA + locusSIGB + locusSIGW); - perLocusFisWeirCockerham[locus] = locusSIGB / (locusSIGB + locusSIGW); - perLocusFitWeirCockerham[locus] = (locusSIGA + locusSIGB) / (locusSIGA + locusSIGB + locusSIGW); + perLocusFst[locus] = locusSIGA / (locusSIGA + locusSIGB + locusSIGW); + perLocusFis[locus] = locusSIGB / (locusSIGB + locusSIGW); + perLocusFit[locus] = (locusSIGA + locusSIGB) / (locusSIGA + locusSIGB + locusSIGW); } // Total F-stats - FstWeirCockerham = SIGA / (SIGA + SIGB + SIGW); - FitWeirCockerham = (SIGA + SIGB) / (SIGA + SIGB + SIGW); - FisWeirCockerham = SIGB / (SIGB + SIGW); + fst = SIGA / (SIGA + SIGB + SIGW); + fis = (SIGA + SIGB) / (SIGA + SIGB + SIGW); + fit = SIGB / (SIGB + SIGW); } else { // no variation: only 1 allele (wildtype) at each locus // so don't calculate to avoid division by zero - FstWeirCockerham = 0; - FitWeirCockerham = 0; - FisWeirCockerham = 0; + fst = 0; + fis = 0; + fit = 0; } // Deallocate matrix @@ -519,13 +517,13 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i } else { // zero or one sampled pops, cannot calculate Fst for (int locus = 0; locus < nLoci; ++locus) { - perLocusFstWeirCockerham[locus] = 0.0; - perLocusFisWeirCockerham[locus] = 0.0; - perLocusFitWeirCockerham[locus] = 0.0; + perLocusFst[locus] = 0.0; + perLocusFis[locus] = 0.0; + perLocusFit[locus] = 0.0; } - FstWeirCockerham = 0; - FitWeirCockerham = 0; - FisWeirCockerham = 0; + fst = 0; + fis = 0; + fit = 0; } } @@ -535,7 +533,7 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i // The method used here is that of Weir& Hill 2002, Ann.Rev.Genet. 36:721 - 750. // The weighting is done for samples(patches) of unequal sizes. // ---------------------------------------------------------------------------------------- -void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape) { +void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape) { const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; const int ploidy = pSpecies->isDiploid() ? 2 : 1; @@ -594,7 +592,7 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd for (int u = 0; u < nAlleles; ++u) { p = pPop->getAlleleFrequency(l, u); //p_liu pq = p * (1 - p); - pBar = commSNPTables[l].getFrequency(u); + pBar = commSNPCountTables[l].getFrequency(u); sqDist = p - pBar; //(p_liu - pbar_u)^2 sqDist *= sqDist; @@ -654,10 +652,10 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd // Estimator of global Fst weighted by sample sizes (beta_W in eq. 9 in WH 2002) if (denominator != 0) { - weightedFstWeirHill = 1 - (numeratorWeightedFst * sumWeights) / (denominator * totSize); // beta_w in Eq. 9 in WH 2002 + weightedFst = 1 - (numeratorWeightedFst * sumWeights) / (denominator * totSize); // beta_w in Eq. 9 in WH 2002 } else { - weightedFstWeirHill = 0.0; + weightedFst = 0.0; } // Deallocate pairwise Fst matrix @@ -666,7 +664,7 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd } else { // zero or one pop, cannot calculate Fst // pairwiseFstMatrix keeps default values (0) - weightedFstWeirHill = 0.0; + weightedFst = 0.0; } } diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index 6b5f2ac..c520484 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -79,62 +79,84 @@ struct SNPCountsTable { vector alleleHeterozygoteTallies; // nb of times each allele is found in a heterozygous pair }; -class NeutralStatsManager { -private: - int nbExtantPops, totalNbSampledInds; - /** F-statistics */ - double _ho, _hs, _ht, _hsnei, _htnei, meanNbAllelesPerLocusPerPatch, meanNbAllelesPerLocus, - _fst, _fis, _fit, meanNbFixedAllelesPerPatch, nbGloballyFixedAlleles; - /** Weir & Hill (2002) F-stat estimates. */ - double weightedFstWeirHill; - /** Weir & Cockerham (1984) F-stat estimates. */ - double FstWeirCockerham, FisWeirCockerham, FitWeirCockerham; - /** Per-locus F-stats (Weir&Cockerham). */ - vector perLocusFstWeirCockerham, perLocusFisWeirCockerham, perLocusFitWeirCockerham, perLocusHo; //no need for pointers because shouldn't be copied or moved, resized - - /** Pairwise Fst matrix. */ - PatchMatrix pairwiseFstMatrix; - vector commSNPTables; //don't have to be pointers, not shared or moved +// Handles calculations of neutral statistics +class NeutralStatsManager { -public: +public: NeutralStatsManager(const int& nbSampledPatches, const int nLoci); + // Count alleles and their frequencies in all pops and community void updateAllSNPTables(Species* pSpecies, Landscape* pLandscape, set const& patchList); void resetCommSNPtables(); - void setLociDiversityCounter(set const& patchList, const int nInds, Species* pSpecies, Landscape* pLandscape); - void setFstMatrix(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape); + + void calcAllelicDiversityMetrics(set const& patchList, const int nInds, Species* pSpecies, Landscape* pLandscape); + + // Heterozygosity calculations void calculateHo(set const& patchList, const int totalNbSampledInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape); void calculateHs(set const& patchList, const int nbrLoci, Species* pSpecies, Landscape* pLandscape); void calculateHt(Species* pSpecies, Landscape* pLandscape, const int nLoci, const int nAlleles); - void calculateHo2(set const& patchList, const int totalNbSampledInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape); + void calculatePerLocusHo(set const& patchList, const int totalNbSampledInds, const int nbrLoci, Species* pSpecies, Landscape* pLandscape); + + // F-stats calculations void calculateFstatWC(set const& patchList, const int nInds, const int nLoci, const int nAlleles, Species* pSpecies, Landscape* pLandscape); - void calculateFstatWC_MS(set const& patchList, const int nInds, const int nLoci, const int nAlleles, Species* pSpecies, Landscape* pLandscape); - - double getHsnei() const { return _hsnei; } - double getHtnei() const { return _htnei; } - double getHo() const { return _ho; } - double getHs() const { return _hs; } - double getHt() const { return _ht; } - double getFst() const { return _fst; } - double getFis() const { return _fis; } - double getFit() const { return _fit; } - double getFstWC() const { return FstWeirCockerham; } - double getFisWC() const { return FisWeirCockerham; } - double getFitWC() const { return FitWeirCockerham; } - int getNbPopulatedSampledPatches() const { return nbExtantPops; } - int getTotalNbSampledInds() const { return totalNbSampledInds; } - double getWeightedFst() { return weightedFstWeirHill; } + void calcPerLocusMeanSquaresFst(set const& patchList, const int nInds, const int nLoci, const int nAlleles, Species* pSpecies, Landscape* pLandscape); + void calcPairwiseWeightedFst(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape); + + // Getters + int getNbPopulatedSampledPatches() const { return nbExtantPops; } + int getTotalNbSampledInds() const { return totalNbSampledInds; } + double getMeanNbAllPerLocusPerPatch() const { return meanNbAllelesPerLocusPerPatch; } double getMeanNbAllPerLocus() const { return meanNbAllelesPerLocus; } double getMeanFixdAllelesPerPatch() const { return meanNbFixedAllelesPerPatch; } double getTotalFixdAlleles() const { return nbGloballyFixedAlleles; } + + double getHo() const { return ho; } + double getHs() const { return hs; } + double getHt() const { return ht; } + + double getPerLocusHo(int i) const { return perLocusHo[i]; } + + double getFstWC() const { return fst; } + double getFisWC() const { return fis; } + double getFitWC() const { return fit; } + + double getWeightedFst() { return weightedFst; } + + double getPerLocusFst(int i) const { return perLocusFst[i]; } + double getPerLocusFis(int i) const { return perLocusFis[i]; } + double getPerLocusFit(int i) const { return perLocusFit[i]; } + double getPairwiseFst(int i, int j) { return pairwiseFstMatrix.get(i, j); } - double get_fst_WC_loc(int i) const { return perLocusFstWeirCockerham[i]; } - double get_fis_WC_loc(int i) const { return perLocusFisWeirCockerham[i]; } - double get_fit_WC_loc(int i) const { return perLocusFitWeirCockerham[i]; } - double get_ho_loc(int i) const { return perLocusHo[i]; } + +private: + + int nbExtantPops, totalNbSampledInds; + vector commSNPCountTables; // community-level tallies of allele counts and freqs + + double meanNbAllelesPerLocusPerPatch, meanNbAllelesPerLocus; + double meanNbFixedAllelesPerPatch, nbGloballyFixedAlleles; + + double ho; // observed heterozygosity + double hs; // expected population-level heterozygosity + double ht; // expected community-level heterozygosity + + vector perLocusHo; // Per-locus observed heterozygosity + + // F-statistics + // Weir & Cockerham (1984) F-stat estimates. + double fst, fis, fit; + + // Weir & Hill (2002) F-stat estimates + double weightedFst; + + // Per-locus F-stats (Weir & Cockerham). + vector perLocusFst, perLocusFis, perLocusFit; + + // Pairwise Fst matrix + PatchMatrix pairwiseFstMatrix; }; #endif diff --git a/Population.cpp b/Population.cpp index c14ae01..8d6a407 100644 --- a/Population.cpp +++ b/Population.cpp @@ -321,15 +321,15 @@ int Population::getNInds(void) { return (int)inds.size(); } // reset allele table // ---------------------------------------------------------------------------------------- void Population::resetPopSNPtables() { - for (auto& entry : popSNPtables) { + for (auto& entry : popSNPCountTables) { entry.reset(); } } // ---------------------------------------------------------------------------------------- -// allele frequency in population of sampled individuals +// Populate population-level SNP count tables +// Update allele occurrence and heterozygosity counts, and allele frequencies // ---------------------------------------------------------------------------------------- - void Population::updatePopSNPtables() { const int nLoci = pSpecies->getNPositionsForTrait(SNP); @@ -337,44 +337,46 @@ void Population::updatePopSNPtables() { const auto& positions = pSpecies->getSpTrait(SNP)->getGenePositions(); const int ploidy = pSpecies->isDiploid() ? 2 : 1; - if (popSNPtables.size() != 0) + // Create /reset empty tables + if (popSNPCountTables.size() != 0) resetPopSNPtables(); else { - popSNPtables.reserve(nLoci); + popSNPCountTables.reserve(nLoci); for (int l = 0; l < nLoci; l++) { - popSNPtables.push_back(SNPCountsTable(nAlleles)); + popSNPCountTables.push_back(SNPCountsTable(nAlleles)); } } + // Fill tallies for each locus for (Individual* individual : sampledInds) { const auto trait = individual->getTrait(SNP); - int whichLocus = 0; for (auto position : positions) { int alleleOnChromA = (int)trait->getAlleleValueAtLocus(0, position); - popSNPtables[whichLocus].incrementTally(alleleOnChromA); + popSNPCountTables[whichLocus].incrementTally(alleleOnChromA); - if (ploidy == 2) { + if (ploidy == 2) { // second allele and heterozygosity int alleleOnChromB = (int)trait->getAlleleValueAtLocus(1, position); - popSNPtables[whichLocus].incrementTally(alleleOnChromB); + popSNPCountTables[whichLocus].incrementTally(alleleOnChromB); bool isHetero = alleleOnChromA != alleleOnChromB; if (isHetero) { - popSNPtables[whichLocus].incrementHeteroTally(alleleOnChromA); - popSNPtables[whichLocus].incrementHeteroTally(alleleOnChromB); + popSNPCountTables[whichLocus].incrementHeteroTally(alleleOnChromA); + popSNPCountTables[whichLocus].incrementHeteroTally(alleleOnChromB); } } whichLocus++; } } + // Fill frequencies if (sampledInds.size() > 0) { std::for_each( - popSNPtables.begin(), - popSNPtables.end(), + popSNPCountTables.begin(), + popSNPCountTables.end(), [&](SNPCountsTable& thisLocus) -> void { thisLocus.setFrequencies(static_cast(sampledInds.size()) * ploidy); }); @@ -382,21 +384,20 @@ void Population::updatePopSNPtables() { } double Population::getAlleleFrequency(int thisLocus, int whichAllele) { - return popSNPtables[thisLocus].getFrequency(whichAllele); + return popSNPCountTables[thisLocus].getFrequency(whichAllele); } int Population::getAlleleTally(int thisLocus, int whichAllele) { - return popSNPtables[thisLocus].getTally(whichAllele); + return popSNPCountTables[thisLocus].getTally(whichAllele); } int Population::getHeteroTally(int thisLocus, int whichAllele) { - return popSNPtables[thisLocus].getHeteroTally(whichAllele); + return popSNPCountTables[thisLocus].getHeteroTally(whichAllele); } // ---------------------------------------------------------------------------------------- // Count number of heterozygotes loci in sampled individuals // ---------------------------------------------------------------------------------------- - int Population::countHeterozygoteLoci() { int nbHetero = 0; if (pSpecies->isDiploid()) { @@ -409,12 +410,11 @@ int Population::countHeterozygoteLoci() { } // ---------------------------------------------------------------------------------------- -// Count number of heterozygotes per loci loci in sampled individuals +// Count number of heterozygotes among sampled individuals for each locus // ---------------------------------------------------------------------------------------- - -vector Population::countLociHeterozyotes() { +vector Population::countNbHeterozygotesEachLocus() { const auto& positions = pSpecies->getSpTrait(SNP)->getGenePositions(); - vector hetero(positions.size(), 0); + vector hetero(positions.size(), 0); if (pSpecies->isDiploid()) { for (Individual* ind : sampledInds) { @@ -430,23 +430,21 @@ vector Population::countLociHeterozyotes() { } // ---------------------------------------------------------------------------------------- -// compute the expected heterozygosity for population +// Compute the expected heterozygosity for population // ---------------------------------------------------------------------------------------- - double Population::computeHs() { int nLoci = pSpecies->getNPositionsForTrait(SNP); int nAlleles = (int)pSpecies->getSpTrait(SNP)->getInitialParameters().find(MAX)->second; double hs = 0; double freq; - - vectorlocihet(nLoci, 1); + vector locihet(nLoci, 1); if (sampledInds.size() > 0) { for (int thisLocus = 0; thisLocus < nLoci; ++thisLocus) { for (int allele = 0; allele < nAlleles; ++allele) { freq = getAlleleFrequency(thisLocus, allele); freq *= freq; //squared frequencies (expected _homozygosity) - locihet[thisLocus] -= freq; //1 - sum of p2 = expected heterozygosity + locihet[thisLocus] -= freq; // 1 - sum of p2 = expected heterozygosity } hs += locihet[thisLocus]; } diff --git a/Population.h b/Population.h index 08d7378..7dd81ec 100644 --- a/Population.h +++ b/Population.h @@ -226,7 +226,7 @@ class Population { int getAlleleTally(int locus, int allele); int getHeteroTally(int locus, int allele); int countHeterozygoteLoci(); - vector countLociHeterozyotes(); + vector countNbHeterozygotesEachLocus(); double computeHs(); private: @@ -241,7 +241,7 @@ class Population { // has been completed std::set sampledInds; - vector popSNPtables; + vector popSNPCountTables; void resetPopSNPtables(); }; From 6a2547fcff7b14ef7a50dbda059d61a4d4f3911e Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 29 Apr 2024 17:18:26 +0100 Subject: [PATCH 108/332] removing some commented out lines --- Individual.cpp | 1 - Population.cpp | 75 +++----------------------------------------------- 2 files changed, 4 insertions(+), 72 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index e4f0c2e..6bc21f5 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -718,7 +718,6 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, yrand = (double)loc.y + pRandom->Random() * 0.999; r1 = 0.0000001 + pRandom->Random() * (1.0 - 0.0000001); - // dist = (-1.0*meandist)*std::log(r1); dist = (-1.0 * meandist) * log(r1); // for LINUX_CLUSTER rndangle = pRandom->Random() * 2.0 * PI; diff --git a/Population.cpp b/Population.cpp index 8d6a407..359c0d9 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1089,31 +1089,11 @@ int Population::transfer(Landscape* pLandscape, short landIx) // each individual takes one step // for dispersal by kernel, this should be the only step taken int ninds = (int)inds.size(); -#if RSDEBUG - //DEBUGLOG << "Population::transfer(): 0000: ninds = " << ninds - // << " ndispersers = " << ndispersers << endl; -#endif + for (int i = 0; i < ninds; i++) { -#if RSDEBUG - //DEBUGLOG << "Population::transfer(): 1111: i = " << i << " ID = " << inds[i]->getId() - // << endl; -#endif if (trfr.usesMovtProc) { -#if RSDEBUG - //pCell = inds[i]->getLocn(1); - //locn loc = pCell->getLocn(); - //DEBUGLOG << "Population::transfer(): 1112: i = " << i << " ID = " << inds[i]->getId() - // << " before:" << " x = " << loc.x << " y = " << loc.y - // << endl; -#endif + disperser = inds[i]->moveStep(pLandscape, pSpecies, landIx, sim.absorbing); -#if RSDEBUG - //pCell = inds[i]->getLocn(1); - //newloc = pCell->getLocn(); - //DEBUGLOG << "Population::transfer(): 1113: i = " << i << " ID = " << inds[i]->getId() - // << " after: " << " x = " << newloc.x << " y = " << newloc.y - // << endl; -#endif } else { disperser = inds[i]->moveKernel(pLandscape, pSpecies, reptype, sim.absorbing); @@ -1134,10 +1114,6 @@ int Population::transfer(Landscape* pLandscape, short landIx) } } } -#if RSDEBUG - //DEBUGLOG << "Population::transfer(): 5555: ninds=" << ninds - // << " ndispersers=" << ndispersers << endl; -#endif for (int i = 0; i < ninds; i++) { ind = inds[i]->getStats(); @@ -1162,28 +1138,11 @@ int Population::transfer(Landscape* pLandscape, short landIx) ind.status = 6; } else { - -#if RSDEBUG - //newloc = pCell->getLocn(); - //DEBUGLOG << "Population::transfer(): 6666: i=" << i << " ID=" << inds[i]->getId() - // << " sex=" << ind.sex << " status=" << ind.status - // << " pCell=" << pCell << " x=" << newloc.x << " y=" << newloc.y - // << " findMate=" << sett.findMate - //// << " wait=" << sett.wait - //// << " go2nbrLocn=" << sett.go2nbrLocn - // << endl; -#endif - mateOK = false; if (sett.findMate) { // determine whether at least one individual of the opposite sex is present in the // new population if (matePresent(pCell, othersex)) mateOK = true; -#if RSDEBUG - //DEBUGLOG << "Population::transfer(): 7777: othersex=" << othersex - // << " this=" << this << " pNewPopn=" << pNewPopn << " popsize=" << popsize << " mateOK=" << mateOK - // << endl; -#endif } else { // no requirement to find a mate mateOK = true; @@ -1193,10 +1152,6 @@ int Population::transfer(Landscape* pLandscape, short landIx) if (sett.densDep) { patch = pCell->getPatch(); -#if RSDEBUG - //DEBUGLOG << "Population::transfer(): 8880: i=" << i << " patch=" << patch - // << endl; -#endif if (patch != 0) { // not no-data area pPatch = (Patch*)patch; if (settle.settleStatus == 0 @@ -1204,14 +1159,10 @@ int Population::transfer(Landscape* pLandscape, short landIx) // note: second condition allows for having moved from one patch to another // adjacent one { - // inds[i]->resetPathOut(); // reset steps out of patch to zero - // determine whether settlement occurs in the (new) patch + // determine whether settlement occurs in the (new) patch localK = (double)pPatch->getK(); popn = pPatch->getPopn((intptr)pSpecies); -#if RSDEBUG - //DEBUGLOG << "Population::transfer(): 8881: i=" << i << " patchNum=" << pPatch->getPatchNum() - // << " localK=" << localK << " popn=" << popn << endl; -#endif + if (popn == 0) { // population has not been set up in the new patch popsize = 0.0; } @@ -1225,13 +1176,6 @@ int Population::transfer(Landscape* pLandscape, short landIx) else settDD = pSpecies->getSettTraits(ind.stage, ind.sex); settprob = settDD.s0 / (1.0 + exp(-(popsize / localK - (double)settDD.beta) * (double)settDD.alpha)); -#if RSDEBUG - //DEBUGLOG << "Population::transfer(): 8888: i=" << i << " ind.stage=" << ind.stage - // << " this=" << this << " pNewPopn=" << pNewPopn << " popsize=" << popsize - // << " localK=" << localK << " alpha=" << settDD.alpha << " beta=" << settDD.beta - // << " settprob=" << settprob - // << endl; -#endif if (pRandom->Bernoulli(settprob)) { // settlement allowed densdepOK = true; settle.settleStatus = 2; @@ -1300,11 +1244,6 @@ int Population::transfer(Landscape* pLandscape, short landIx) { // for kernel-based transfer only ... // determine whether recruitment to a neighbouring cell is possible -#if RSDEBUG -//DEBUGLOG << "Population::transfer(): neighbour cell search: sett.go2nbrLocn = " << sett.go2nbrLocn -// << " ind.status = " << ind.status -// << endl; -#endif pCell = inds[i]->getLocn(1); newloc = pCell->getLocn(); vector nbrlist; @@ -1351,12 +1290,6 @@ int Population::transfer(Landscape* pLandscape, short landIx) // else list empty - do nothing - individual retains its current location and status } } -#if RSDEBUG - //DEBUGLOG << "Population::transfer(): 9999: ninds = " << ninds - // << " ndispersers = " << ndispersers << endl; -#endif - - return ndispersers; } From 0abb3aafdf987ce6d0f39a89dcc0ae3bbae5749c Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 30 Apr 2024 17:16:31 +0100 Subject: [PATCH 109/332] keep trait values valid + ensure parameters correct --- GeneticLoad.cpp | 14 ++-- Parameters.cpp | 12 ---- Parameters.h | 2 +- QTLTrait.cpp | 16 +++-- SpeciesTrait.cpp | 171 +++++++++++++++++++++++++++++++++++++++++++---- SpeciesTrait.h | 3 + 6 files changed, 183 insertions(+), 35 deletions(-) diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index 5d48877..1431fdf 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -126,6 +126,8 @@ void GeneticLoad::mutate() const auto& genePositions = pSpeciesTrait->getGenePositions(); const short ploidy = pSpeciesTrait->getPloidy(); const float mutationRate = pSpeciesTrait->getMutationRate(); + float newSelectionCoef; + float newDominanceCoef; auto rng = pRandom->getRNG(); @@ -144,8 +146,12 @@ void GeneticLoad::mutate() auto it = genes.find(m); if (it == genes.end()) throw runtime_error("Locus sampled for mutation doesn't exist."); - float newSelectionCoef = drawSelectionCoef(); - float newDominanceCoef = drawDominance(newSelectionCoef); + do { + newSelectionCoef = drawSelectionCoef(); + } while (!pSpeciesTrait->isValidTraitVal(newSelectionCoef)); + do { + newDominanceCoef = drawDominance(newSelectionCoef); + } while (newDominanceCoef < 0.0); it->second[p] = make_shared(newSelectionCoef, newDominanceCoef); } } @@ -160,7 +166,7 @@ float GeneticLoad::drawDominance(float selCoef) { DistributionType dominanceDistribution = pSpeciesTrait->getDominanceDistribution(); map dominanceParameters = pSpeciesTrait->getDominanceParameters(); - float h = 1.0; //default dominance is 1 + float h; switch (dominanceDistribution) { case UNIFORM: { @@ -317,8 +323,6 @@ void GeneticLoad::inheritHaploid(const bool& fromMother, mapsecond[p].get()->getAlleleValue();//current - float newAlleleVal = pRandom->FRandom(minD, maxD) + currentAlleleVal; - it->second[p] = make_shared(newAlleleVal, 1.0); + do { + newAlleleVal = pRandom->FRandom(minD, maxD) + currentAlleleVal; + } while (!pSpeciesTrait->isValidTraitVal(newAlleleVal)); + it->second[p] = make_shared(newAlleleVal, QTLDominanceFactor); } } } @@ -166,6 +169,7 @@ void QTLTrait::mutateNormal() const map mutationParameters = pSpeciesTrait->getMutationParameters(); const float mean = mutationParameters.find(MEAN)->second; const float sd = mutationParameters.find(SD)->second; + float newAlleleVal; for (int p = 0; p < ploidy; p++) { @@ -181,9 +185,11 @@ void QTLTrait::mutateNormal() auto it = genes.find(m); if (it == genes.end()) throw runtime_error("Locus sampled for mutation doesn't exist."); - float currentAlleleVal = it->second[p].get()->getAlleleValue();//current - float newAlleleVal = pRandom->Normal(mean, sd) + currentAlleleVal; - it->second[p] = make_shared(newAlleleVal, 1.0); + float currentAlleleVal = it->second[p].get()->getAlleleValue(); //current + do { + newAlleleVal = pRandom->Normal(mean, sd) + currentAlleleVal; + } while (!pSpeciesTrait->isValidTraitVal(newAlleleVal)); + it->second[p] = make_shared(newAlleleVal, QTLDominanceFactor); } } } diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index b65587a..a5cffc2 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -3,25 +3,172 @@ // Species trait constructor SpeciesTrait::SpeciesTrait( - const TraitType& traitType, const sex_t& sx, + const TraitType& trType, const sex_t& sx, const set& pos, const ExpressionType& expr, const DistributionType& initDist, const map initParams, const DistributionType& dominanceDist, const map dominanceParams, bool isInherited, const float& mutRate, const DistributionType& mutationDist, const map mutationParams, Species* pSpecies) : - sex{sx}, - genePositions{pos}, - expressionType{expr}, - initialDistribution{initDist}, - initialParameters{initParams}, - dominanceDistribution{dominanceDist}, - dominanceParameters{dominanceParams}, - inherited{isInherited}, - mutationDistribution{mutationDist}, - mutationParameters{mutationParams}, - mutationRate{mutRate} + traitType{ trType }, + sex{ sx }, + genePositions{ pos }, + expressionType{ expr }, + initialDistribution{ initDist }, + initialParameters{ initParams }, + dominanceDistribution{ dominanceDist }, + dominanceParameters{ dominanceParams }, + inherited{ isInherited }, + mutationDistribution{ mutationDist }, + mutationParameters{ mutationParams }, + mutationRate{ mutRate } { // Initialise ploidy only once per species if (ploidy == NULL) this->ploidy = pSpecies->isDiploid() ? 2 : 1; + + // Check distribution parameters + // Initial distribution + for (auto [paramType, paramVal] : initParams) { + switch (paramType) + { + case MIN: case MAX: case MEAN: + if (!isValidTraitVal(paramVal)) + throw logic_error("Invalid parameter value: initial parameter " + to_string(paramType) + " must have a valid value for trait" + to_string(traitType) + "."); + break; + case SD: + if (paramVal <= 0.0) + throw logic_error("Invalid parameter value: initial parameter " + to_string(paramType) + " must be strictly positive"); + break; + default: + break; + } + } + + // Mutation distribution + for (auto [paramType, paramVal] : mutationParams) { + switch (paramType) + { + case MIN: case MAX: case MEAN: + if (!isValidTraitVal(paramVal)) + throw logic_error("Invalid parameter value: mutation parameter " + to_string(paramType) + " must have a valid value for trait" + to_string(traitType) + "."); + break; + case SD: case SHAPE: case SCALE: + if (paramVal <= 0.0) + throw logic_error("Invalid parameter value: mutation parameter " + to_string(paramType) + " must be strictly positive"); + break; + default: + break; + } + } + + // Dominance distribution + for (auto [paramType, paramVal] : dominanceParams) { + switch (paramType) + { + case MIN: case MAX: case MEAN: + if (paramVal < 0.0 || paramVal > 1.0) + throw logic_error("Invalid parameter value: dominance parameter " + to_string(paramType) + " must be between 0 and 1."); + break; + case SD: case SHAPE: case SCALE: + if (paramVal <= 0.0) + throw logic_error("Invalid parameter value: dominance parameter " + to_string(paramType) + " must be strictly positive"); + break; + default: + break; + } + } } + +bool SpeciesTrait::isValidTraitVal(const float& val) const { + switch (traitType) + { + // No need to check for SNPs - mutate functions are safe already + + // Genetic Load + case GENETIC_LOAD1: case GENETIC_LOAD2: case GENETIC_LOAD3: case GENETIC_LOAD4: case GENETIC_LOAD5: + { + return val >= 0.0 && val <= 1.0; // substracted from a probability + break; + } + // Quantitative trait loci + /// Emigration + case E_D0_F: case E_D0_M: { + return val >= 0.0 && val <= 1.0; // is a probability + break; + } + case E_ALPHA_F: case E_ALPHA_M: + { + return val > 0.0; + break; + } + case E_BETA_F: case E_BETA_M: + { + return true; // inflexion point can be any value + break; + } + /// Settlement + case S_S0_F: case S_S0_M: + { + return val >= 0.0 && val <= 1.0; + break; + } + case S_ALPHA_F: case S_ALPHA_M: + { + return val > 0.0; + break; + } + case S_BETA_F: case S_BETA_M: + { + return true; + break; + } + /// Transfer - Kernels + case KERNEL_MEANDIST_1_F: case KERNEL_MEANDIST_1_M: + case KERNEL_MEANDIST_2_F: case KERNEL_MEANDIST_2_M: + { + return val >= 0.0; // is a distance + break; + } + case KERNEL_PROBABILITY_F: case KERNEL_PROBABILITY_M: + { + return val >= 0.0 && val <= 1.0; + break; + } + /// Transfer - Correlated random walk + case CRW_STEPLENGTH: + { + return val >= 0.0; + break; + } + case CRW_STEPCORRELATION: + { + return val >= 0.0 && val <= 1.0; + break; + } + /// Transfer - Stochastic Movement Simulator + case SMS_DP: + { + return val >= 1.0; // according to parameter doc + break; + } + case SMS_GB: + { + return val >= 1.0; // according to parameter doc + break; + } + case SMS_ALPHADB: + { + return val > 0.0; + break; + } + case SMS_BETADB: + { + return true; + break; + } + default: + throw logic_error("Invalid trait type " + to_string(traitType) + " passed to isValidTraitVal()."); + break; + } +} + diff --git a/SpeciesTrait.h b/SpeciesTrait.h index a83904f..f5809bf 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -31,6 +31,8 @@ class SpeciesTrait { Species* pSpecies ); + bool isValidTraitVal(const float& val) const; + // Getters sex_t getSex() const { return sex; } float getMutationRate() const { return mutationRate; } @@ -51,6 +53,7 @@ class SpeciesTrait { inline static int ploidy = 0; float mutationRate; + TraitType traitType; sex_t sex; // Positions in the genome of all genes (loci) pertaining to this trait From ecdadb83f66243b80a50a1b22337bcc400b207e2 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 1 May 2024 11:33:45 +0100 Subject: [PATCH 110/332] fix invalid input parameter values --- SpeciesTrait.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index a5cffc2..d9f2cc1 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -82,10 +82,13 @@ SpeciesTrait::SpeciesTrait( bool SpeciesTrait::isValidTraitVal(const float& val) const { switch (traitType) { - // No need to check for SNPs - mutate functions are safe already - + // Neutral trait + case SNP: // only need to check for input parameters + { + return val >= 0.0 && val <= 255.0; + } // Genetic Load - case GENETIC_LOAD1: case GENETIC_LOAD2: case GENETIC_LOAD3: case GENETIC_LOAD4: case GENETIC_LOAD5: + case GENETIC_LOAD: case GENETIC_LOAD1: case GENETIC_LOAD2: case GENETIC_LOAD3: case GENETIC_LOAD4: case GENETIC_LOAD5: { return val >= 0.0 && val <= 1.0; // substracted from a probability break; From e4fd08936d8c51b4700002e42fce7b9d26809d76 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 1 May 2024 13:51:04 +0100 Subject: [PATCH 111/332] forbid GenomeSize = 0; clarify recombination --- QTLTrait.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/QTLTrait.cpp b/QTLTrait.cpp index 2ca74af..6d6c2e5 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -215,8 +215,9 @@ void QTLTrait::inheritDiploid(const bool& fromMother, mapfirst); int nextBreakpoint = *it; + // Is the first parent gene position already recombinant? auto distance = std::distance(recomPositions.begin(), it); - if (distance % 2 != 0) + if (distance % 2 != 0) // odd positions = switch, even = switch back parentChromosome = 1 - parentChromosome; //switch chromosome for (auto const& [locus, allelePair] : parentGenes) { From 6fd3c1e64921cf5076a572ab5c86746b6a83a73f Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 8 May 2024 15:48:34 +0100 Subject: [PATCH 112/332] rename GeneticFitness into GeneticLoad --- CMakeLists.txt | 4 ++-- GeneticLoad.cpp => GeneticFitness.cpp | 32 +++++++++++++-------------- GeneticLoad.h => GeneticFitness.h | 18 +++++++-------- Species.cpp | 8 +++---- Species.h | 2 +- TraitFactory.h | 4 ++-- 6 files changed, 34 insertions(+), 34 deletions(-) rename GeneticLoad.cpp => GeneticFitness.cpp (91%) rename GeneticLoad.h => GeneticFitness.h (85%) diff --git a/CMakeLists.txt b/CMakeLists.txt index c0bfd0f..530a778 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,9 +7,9 @@ if (NOT batchmode) # that is, RScore as a standalone # specify the C++ standard set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) - add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticLoad.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) + add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitness.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) else() # that is, RScore compiled as library within RangeShifter_batch - add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticLoad.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) + add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitness.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) endif() # pass config definitions to compiler diff --git a/GeneticLoad.cpp b/GeneticFitness.cpp similarity index 91% rename from GeneticLoad.cpp rename to GeneticFitness.cpp index 1431fdf..8fbfcc4 100644 --- a/GeneticLoad.cpp +++ b/GeneticFitness.cpp @@ -1,4 +1,4 @@ -#include "GeneticLoad.h" +#include "GeneticFitness.h" // ---------------------------------------------------------------------------------------- // Initialisation constructor @@ -6,14 +6,14 @@ // Sets up initial values, and immutable attributes (distributions and parameters) // that are defined at the species-level // ---------------------------------------------------------------------------------------- -GeneticLoad::GeneticLoad(SpeciesTrait* P) +GeneticFitness::GeneticFitness(SpeciesTrait* P) { pSpeciesTrait = P; ExpressionType expressionType = pSpeciesTrait->getExpressionType(); initialise(); - _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &GeneticLoad::inheritHaploid : &GeneticLoad::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance + _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &GeneticFitness::inheritHaploid : &GeneticFitness::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); map mutationParameters = pSpeciesTrait->getMutationParameters(); @@ -104,10 +104,10 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) // Copies immutable features from a parent trait // Only called via clone() // ---------------------------------------------------------------------------------------- -GeneticLoad::GeneticLoad(const GeneticLoad& T) : pSpeciesTrait(T.pSpeciesTrait), _inherit_func_ptr(T._inherit_func_ptr) +GeneticFitness::GeneticFitness(const GeneticFitness& T) : pSpeciesTrait(T.pSpeciesTrait), _inherit_func_ptr(T._inherit_func_ptr) {} -void GeneticLoad::initialise() { +void GeneticFitness::initialise() { // All positions start at wild type, mutations accumulate through simulation const set genePositions = pSpeciesTrait->getGenePositions(); short ploidy = pSpeciesTrait->getPloidy(); @@ -120,7 +120,7 @@ void GeneticLoad::initialise() { // ---------------------------------------------------------------------------------------- // Mutate uniform // ---------------------------------------------------------------------------------------- -void GeneticLoad::mutate() +void GeneticFitness::mutate() { const int positionsSize = pSpeciesTrait->getPositionsSize(); const auto& genePositions = pSpeciesTrait->getGenePositions(); @@ -161,7 +161,7 @@ void GeneticLoad::mutate() // ---------------------------------------------------------------------------------------- // get dominance value for new mutation // ---------------------------------------------------------------------------------------- -float GeneticLoad::drawDominance(float selCoef) { +float GeneticFitness::drawDominance(float selCoef) { DistributionType dominanceDistribution = pSpeciesTrait->getDominanceDistribution(); map dominanceParameters = pSpeciesTrait->getDominanceParameters(); @@ -215,7 +215,7 @@ float GeneticLoad::drawDominance(float selCoef) { // ---------------------------------------------------------------------------------------- // Get selection coefficient for new mutation // ---------------------------------------------------------------------------------------- -float GeneticLoad::drawSelectionCoef() { +float GeneticFitness::drawSelectionCoef() { DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); map mutationParameters = pSpeciesTrait->getMutationParameters(); @@ -263,9 +263,9 @@ float GeneticLoad::drawSelectionCoef() { // ---------------------------------------------------------------------------------------- // Wrapper to inheritance function // ---------------------------------------------------------------------------------------- -void GeneticLoad::inheritGenes(const bool& fromMother, TTrait* parentTrait, set const& recomPositions, int startingChromosome) +void GeneticFitness::inheritGenes(const bool& fromMother, TTrait* parentTrait, set const& recomPositions, int startingChromosome) { - auto parentCast = dynamic_cast (parentTrait); // must convert TTrait to GeneticLoadTrait + auto parentCast = dynamic_cast (parentTrait); // must convert TTrait to GeneticFitness const auto& parent_seq = parentCast->getGenes(); (this->*_inherit_func_ptr) (fromMother, parent_seq, recomPositions, startingChromosome); } @@ -276,7 +276,7 @@ void GeneticLoad::inheritGenes(const bool& fromMother, TTrait* parentTrait, set< // populates offspring genes with appropriate parent alleles // Assumes mother genes are inherited first // ---------------------------------------------------------------------------------------- -void GeneticLoad::inheritDiploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { +void GeneticFitness::inheritDiploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { auto it = recomPositions.lower_bound(parentGenes.begin()->first); int nextBreakpoint = *it; @@ -316,7 +316,7 @@ void GeneticLoad::inheritDiploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) +void GeneticFitness::inheritHaploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { genes = parentGenes; } @@ -324,7 +324,7 @@ void GeneticLoad::inheritHaploid(const bool& fromMother, map #include @@ -17,22 +17,22 @@ using namespace std; // offspring viability. Alleles start with value // zero but increase through simulation via mutations. // There can be up to five genetic load traits. -class GeneticLoad : public TTrait { +class GeneticFitness : public TTrait { public: // Initialisation constructor, set initial values and immutable features - GeneticLoad(SpeciesTrait* P); + GeneticFitness(SpeciesTrait* P); // Inheritance constructor, copies pointers to immutable features when cloning from parent - GeneticLoad(const GeneticLoad& T); + GeneticFitness(const GeneticFitness& T); // Make a shallow copy to pass to offspring trait // Return new pointer to new trait created by inheritance c'tor // This avoids copying shared attributes: distributions and parameters - virtual unique_ptr clone() const override { return std::make_unique(*this); } + virtual unique_ptr clone() const override { return std::make_unique(*this); } - virtual ~GeneticLoad() { } + virtual ~GeneticFitness() { } // Getters virtual int getNLoci() const override { return pSpeciesTrait->getPositionsSize(); } @@ -69,7 +69,7 @@ class GeneticLoad : public TTrait { //// Species-level trait attributes, invariant across individuals SpeciesTrait* pSpeciesTrait; //// Species-level trait functions - void (GeneticLoad::* _inherit_func_ptr) (const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); + void (GeneticFitness::* _inherit_func_ptr) (const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); // Possible values for immutable functions //// Inheritance @@ -77,4 +77,4 @@ class GeneticLoad : public TTrait { void inheritHaploid(const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); }; -#endif // GENETICLOADH +#endif // GENETICFITNESSH diff --git a/Species.cpp b/Species.cpp index 427b09f..9098438 100644 --- a/Species.cpp +++ b/Species.cpp @@ -378,7 +378,7 @@ bool Species::areMutationsOn(void) { void Species::resetGeneticParameters() { mutationsOn = true; - nbGeneticLoadTraits = 0; + nbGeneticFitnessTraits = 0; genomeSize = -9999; recombinationRate = -9999; nPatchesToSample = 0; @@ -393,13 +393,13 @@ bool Species::isDiploid() const { int Species::incrNbGenLoadTraits() { - nbGeneticLoadTraits++; - return nbGeneticLoadTraits; + nbGeneticFitnessTraits++; + return nbGeneticFitnessTraits; } int Species::getNbGenLoadTraits() const { - return nbGeneticLoadTraits; + return nbGeneticFitnessTraits; } void Species::addTrait(TraitType traitType, const SpeciesTrait& trait) { diff --git a/Species.h b/Species.h index 827f127..a545978 100644 --- a/Species.h +++ b/Species.h @@ -489,7 +489,7 @@ class Species { int genomeSize; bool diploid; bool mutationsOn; - int nbGeneticLoadTraits; + int nbGeneticFitnessTraits; float recombinationRate; std::set samplePatchList; int nPatchesToSample; //for cell based landscape diff --git a/TraitFactory.h b/TraitFactory.h index 25b10a5..dbe07b0 100644 --- a/TraitFactory.h +++ b/TraitFactory.h @@ -6,7 +6,7 @@ #include "SpeciesTrait.h" #include "SNPTrait.h" #include "QTLTrait.h" -#include "GeneticLoad.h" +#include "GeneticFitness.h" // Create handled pointers to a new trait class TraitFactory @@ -24,7 +24,7 @@ class TraitFactory || traitType == GENETIC_LOAD3 || traitType == GENETIC_LOAD4 || traitType == GENETIC_LOAD5) { - return make_unique(protoTrait); + return make_unique(protoTrait); } else { return make_unique(protoTrait); From a4ab79125efe1d0061023b3a78880927af3f41c8 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 8 May 2024 16:09:12 +0100 Subject: [PATCH 113/332] switch sampledInds to vector - sets really don't like to be empty --- Population.cpp | 22 +++++++++++----------- Population.h | 8 ++++---- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Population.cpp b/Population.cpp index 359c0d9..3f75b8a 100644 --- a/Population.cpp +++ b/Population.cpp @@ -818,14 +818,15 @@ Individual* Population::sampleInd() const { void Population::sampleIndsWithoutReplacement(string strNbToSample, const set& sampleStages) { - sampledInds.clear(); + if (sampledInds.size() > 0) { + sampledInds.clear(); + } auto rng = pRandom->getRNG(); - set stagedInds; + vector stagedInds; // Stage individuals in eligible stages for (int stage : sampleStages) { - auto sInds = getIndividualsInStage(stage); - stagedInds.insert(sInds.begin(), sInds.end()); + stagedInds = getIndividualsInStage(stage); } if (strNbToSample == "all") { @@ -839,12 +840,11 @@ void Population::sampleIndsWithoutReplacement(string strNbToSample, const set tempSampledInds; + //vector tempSampledInds; // Sample n individuals across selected stages - sample(stagedInds.begin(), stagedInds.end(), std::back_inserter(tempSampledInds), nbToSample, rng); + sample(stagedInds.begin(), stagedInds.end(), std::back_inserter(sampledInds), nbToSample, rng); // Copy from vector to set - std::copy(tempSampledInds.begin(), tempSampledInds.end(), std::inserter(sampledInds, sampledInds.end())); - assert(sampledInds.size() == nbToSample); + //std::copy(tempSampledInds.begin(), tempSampledInds.end(), std::inserter(sampledInds, sampledInds.end())); } } } @@ -853,11 +853,11 @@ int Population::sampleSize() const { return static_cast(sampledInds.size()); } -set Population::getIndividualsInStage(int stage) { - set indsInStage; +vector Population::getIndividualsInStage(int stage) { + vector indsInStage; for (auto ind : inds) { if (ind->getStats().stage == stage) - indsInStage.insert(ind); + indsInStage.push_back(ind); } return indsInStage; } diff --git a/Population.h b/Population.h index 7dd81ec..4258007 100644 --- a/Population.h +++ b/Population.h @@ -154,7 +154,7 @@ class Population { Individual* sampleInd() const; void sampleIndsWithoutReplacement(string n, const set& sampleStages); int sampleSize() const; - set getIndividualsInStage(int stage); + vector getIndividualsInStage(int stage); #if RS_RCPP int transfer( // Executed for the Population(s) in the matrix only Landscape*, // pointer to Landscape @@ -236,11 +236,11 @@ class Population { Patch* pPatch; // pointer to the patch int nInds[maxNbStages][maxNbSexes]; // no. of individuals in each stage/sex - std::vector inds; // all individuals in population except ... - std::vector juvs; // ... juveniles until reproduction of ALL species + vector inds; // all individuals in population except ... + vector juvs; // ... juveniles until reproduction of ALL species // has been completed - std::set sampledInds; + vector sampledInds; vector popSNPCountTables; void resetPopSNPtables(); }; From 31a3d8db584d6ca38b6d7e37314a99a55448a40b Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 10 May 2024 14:06:20 +0100 Subject: [PATCH 114/332] bug fix; prevent the matrix from being sampled --- Community.cpp | 2 +- Landscape.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Community.cpp b/Community.cpp index d9ad95d..e558b61 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1628,7 +1628,7 @@ void Community::sampleIndividuals(Species* pSpecies) { for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); if (patch == 0) { - throw runtime_error("Sampled patch doesn't exist."); + throw runtime_error("Can't sample individuals: patch" + to_string(patchId) + "doesn't exist."); } auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop != 0) { diff --git a/Landscape.cpp b/Landscape.cpp index fedfed8..b1c9311 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -876,6 +876,7 @@ set Landscape::samplePatches(const string& samplingOption, int nbToSample, // Get list of viable patches where the species is present for (auto p : patches) { + if (p->getPatchNum() == 0) continue; // skip patch 0, the matrix if (p->speciesIsPresent(pSpecies)) occupiedPatches.push_back(p->getPatchNum()); } From 591ad9492dbc91821aecc8d1efe8accf6cdbf15d Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 10 May 2024 15:13:25 +0100 Subject: [PATCH 115/332] adding option to randomly sample once per sim or once per gen --- Landscape.cpp | 22 +++++++++++----------- Model.cpp | 16 +++++++++++++++- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index b1c9311..b000498 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -868,31 +868,31 @@ Patch* Landscape::findPatch(int num) { return 0; } - set Landscape::samplePatches(const string& samplingOption, int nbToSample, Species* pSpecies) { vector sampledPatches; - vector occupiedPatches; + vector eligiblePatches; // Get list of viable patches where the species is present for (auto p : patches) { if (p->getPatchNum() == 0) continue; // skip patch 0, the matrix - if (p->speciesIsPresent(pSpecies)) - occupiedPatches.push_back(p->getPatchNum()); + if (samplingOption == "random" // then all patches are eligible + || p->speciesIsPresent(pSpecies)) // otherwise only patches with at least 1 ind + eligiblePatches.push_back(p->getPatchNum()); } - + if (samplingOption == "all") { - sampledPatches = occupiedPatches; + sampledPatches = eligiblePatches; } - else if (samplingOption == "random") { - if (nbToSample > occupiedPatches.size()) - nbToSample = occupiedPatches.size(); + else if (samplingOption == "random_occupied" || samplingOption == "random") { + if (nbToSample > eligiblePatches.size()) + nbToSample = eligiblePatches.size(); auto rng = pRandom->getRNG(); - sample(occupiedPatches.begin(), occupiedPatches.end(), std::back_inserter(sampledPatches), + sample(eligiblePatches.begin(), eligiblePatches.end(), std::back_inserter(sampledPatches), nbToSample, rng); } else { - throw logic_error("Sampling option should be random or all when sampling patches."); + throw logic_error("Sampling option should be random, rnadom_occupied or all when sampling patches."); } set patchIds; diff --git a/Model.cpp b/Model.cpp index 487b57e..3848bbb 100644 --- a/Model.cpp +++ b/Model.cpp @@ -83,6 +83,13 @@ int RunModel(Landscape* pLandscape, int seqsim) else { pLandscape->resetLandLimits(); } + + // Random patches are sampled once per landscape + if (sim.patchSamplingOption == "random") { + int nbToSample = pSpecies->getNbPatchesToSample(); + auto patchesToSample = pLandscape->samplePatches(sim.patchSamplingOption, nbToSample, pSpecies); + pSpecies->setSamplePatchList(patchesToSample); + } } #if RS_RCPP && !R_CMD @@ -91,6 +98,7 @@ int RunModel(Landscape* pLandscape, int seqsim) // Loop through replicates for (int rep = 0; rep < sim.reps; rep++) { + #if RS_RCPP && !R_CMD Rcpp::Rcout << endl << "starting replicate " << rep << endl; #endif @@ -138,6 +146,12 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES #endif } + if (sim.patchSamplingOption == "random") { + // Then patches must be resampled for new landscape + int nbToSample = pSpecies->getNbPatchesToSample(); + auto patchesToSample = pLandscape->samplePatches(sim.patchSamplingOption, nbToSample, pSpecies); + pSpecies->setSamplePatchList(patchesToSample); + } } if (init.seedType == 0 && init.freeType < 2 && init.initFrzYr > 0) { // restrict available landscape to initialised region @@ -478,7 +492,7 @@ int RunModel(Landscape* pLandscape, int seqsim) && yr % sim.outputGeneticInterval == 0) { simParams sim = paramsSim->getSim(); - if (sim.patchSamplingOption != "list") { + if (sim.patchSamplingOption != "list" && sim.patchSamplingOption != "random") { // then patches must be re-sampled every gen int nbToSample = pSpecies->getNbPatchesToSample(); auto patchesToSample = pLandscape->samplePatches(sim.patchSamplingOption, nbToSample, pSpecies); From 5c47e6ad7b0f383d575a7fe6de99cc42715c4d10 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 10 May 2024 17:33:20 +0100 Subject: [PATCH 116/332] allow negative genetic loads --- CMakeLists.txt | 4 +- Community.cpp | 16 +++--- GeneticFitness.cpp => GeneticFitnessTrait.cpp | 56 +++++++++++-------- GeneticFitness.h => GeneticFitnessTrait.h | 12 ++-- Individual.cpp | 8 +-- Individual.h | 4 +- Population.cpp | 16 ++++-- Population.h | 4 +- SpeciesTrait.cpp | 7 ++- SubCommunity.cpp | 10 ++-- TraitFactory.h | 4 +- 11 files changed, 79 insertions(+), 62 deletions(-) rename GeneticFitness.cpp => GeneticFitnessTrait.cpp (85%) rename GeneticFitness.h => GeneticFitnessTrait.h (86%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 530a778..b7d6cd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,9 +7,9 @@ if (NOT batchmode) # that is, RScore as a standalone # specify the C++ standard set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) - add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitness.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) + add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) else() # that is, RScore compiled as library within RangeShifter_batch - add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitness.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) + add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) endif() # pass config definitions to compiler diff --git a/Community.cpp b/Community.cpp index e558b61..02bd9d1 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1205,7 +1205,7 @@ void Community::outTraits(traitCanvas tcanv, Species* pSpecies, ts[y].sumS0[i] = ts[y].ssqS0[i] = 0.0; ts[y].sumAlphaS[i] = ts[y].ssqAlphaS[i] = 0.0; ts[y].sumBetaS[i] = ts[y].ssqBetaS[i] = 0.0; - ts[y].sumProbViability[i] = ts[y].ssqProbViability[i] = 0.0; + ts[y].sumGeneticFitness[i] = ts[y].ssqGeneticFitness[i] = 0.0; } } } @@ -1234,7 +1234,7 @@ void Community::outTraits(traitCanvas tcanv, Species* pSpecies, ts[y].sumS0[s] += sctraits.sumS0[s]; ts[y].ssqS0[s] += sctraits.ssqS0[s]; ts[y].sumAlphaS[s] += sctraits.sumAlphaS[s]; ts[y].ssqAlphaS[s] += sctraits.ssqAlphaS[s]; ts[y].sumBetaS[s] += sctraits.sumBetaS[s]; ts[y].ssqBetaS[s] += sctraits.ssqBetaS[s]; - ts[y].sumProbViability[s] += sctraits.sumProbViability[s]; ts[y].ssqProbViability[s] += sctraits.ssqProbViability[s]; + ts[y].sumGeneticFitness[s] += sctraits.sumGeneticFitness[s]; ts[y].ssqGeneticFitness[s] += sctraits.ssqGeneticFitness[s]; } } } @@ -1397,18 +1397,18 @@ void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int if (pSpecies->getNbGenLoadTraits() > 0) { if (maxNbSexes > 1) { - if (ts.ninds[0] > 0) mn = ts.sumProbViability[0] / (double)ts.ninds[0]; else mn = 0.0; - if (ts.ninds[0] > 1) sd = ts.ssqProbViability[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; + if (ts.ninds[0] > 0) mn = ts.sumGeneticFitness[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqGeneticFitness[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[1] > 0) mn = ts.sumProbViability[1] / (double)ts.ninds[1]; else mn = 0.0; - if (ts.ninds[1] > 1) sd = ts.ssqProbViability[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; + if (ts.ninds[1] > 0) mn = ts.sumGeneticFitness[1] / (double)ts.ninds[1]; else mn = 0.0; + if (ts.ninds[1] > 1) sd = ts.ssqGeneticFitness[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; } else { - if (ts.ninds[0] > 0) mn = ts.sumProbViability[0] / (double)ts.ninds[0]; else mn = 0.0; - if (ts.ninds[0] > 1) sd = ts.ssqProbViability[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; + if (ts.ninds[0] > 0) mn = ts.sumGeneticFitness[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqGeneticFitness[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; } diff --git a/GeneticFitness.cpp b/GeneticFitnessTrait.cpp similarity index 85% rename from GeneticFitness.cpp rename to GeneticFitnessTrait.cpp index 5552670..17e8630 100644 --- a/GeneticFitness.cpp +++ b/GeneticFitnessTrait.cpp @@ -1,4 +1,4 @@ -#include "GeneticFitness.h" +#include "GeneticFitnessTrait.h" // ---------------------------------------------------------------------------------------- // Initialisation constructor @@ -6,14 +6,14 @@ // Sets up initial values, and immutable attributes (distributions and parameters) // that are defined at the species-level // ---------------------------------------------------------------------------------------- -GeneticFitness::GeneticFitness(SpeciesTrait* P) +GeneticFitnessTrait::GeneticFitnessTrait(SpeciesTrait* P) { pSpeciesTrait = P; ExpressionType expressionType = pSpeciesTrait->getExpressionType(); initialise(); - _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &GeneticFitness::inheritHaploid : &GeneticFitness::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance + _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &GeneticFitnessTrait::inheritHaploid : &GeneticFitnessTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); map mutationParameters = pSpeciesTrait->getMutationParameters(); @@ -104,10 +104,10 @@ GeneticFitness::GeneticFitness(SpeciesTrait* P) // Copies immutable features from a parent trait // Only called via clone() // ---------------------------------------------------------------------------------------- -GeneticFitness::GeneticFitness(const GeneticFitness& T) : pSpeciesTrait(T.pSpeciesTrait), _inherit_func_ptr(T._inherit_func_ptr) +GeneticFitnessTrait::GeneticFitnessTrait(const GeneticFitnessTrait& T) : pSpeciesTrait(T.pSpeciesTrait), _inherit_func_ptr(T._inherit_func_ptr) {} -void GeneticFitness::initialise() { +void GeneticFitnessTrait::initialise() { // All positions start at wild type, mutations accumulate through simulation const set genePositions = pSpeciesTrait->getGenePositions(); short ploidy = pSpeciesTrait->getPloidy(); @@ -120,7 +120,7 @@ void GeneticFitness::initialise() { // ---------------------------------------------------------------------------------------- // Mutate uniform // ---------------------------------------------------------------------------------------- -void GeneticFitness::mutate() +void GeneticFitnessTrait::mutate() { const int positionsSize = pSpeciesTrait->getPositionsSize(); const auto& genePositions = pSpeciesTrait->getGenePositions(); @@ -161,7 +161,7 @@ void GeneticFitness::mutate() // ---------------------------------------------------------------------------------------- // get dominance value for new mutation // ---------------------------------------------------------------------------------------- -float GeneticFitness::drawDominance(float selCoef) { +float GeneticFitnessTrait::drawDominance(float selCoef) { DistributionType dominanceDistribution = pSpeciesTrait->getDominanceDistribution(); map dominanceParameters = pSpeciesTrait->getDominanceParameters(); @@ -179,7 +179,9 @@ float GeneticFitness::drawDominance(float selCoef) { { const float mean = dominanceParameters.find(MEAN)->second; const float sd = dominanceParameters.find(SD)->second; - h = static_cast(pRandom->Normal(mean, sd)); + do { + h = static_cast(pRandom->Normal(mean, sd)); + } while (h <= 0.0); break; } case GAMMA: @@ -214,40 +216,50 @@ float GeneticFitness::drawDominance(float selCoef) { // ---------------------------------------------------------------------------------------- // Get selection coefficient for new mutation +// +// Selection coefficients will usually be between 0 and 1, but may, +// if the mutation distribution enable it, take a negative value +// down to -1 representing the effect of beneficial mutations // ---------------------------------------------------------------------------------------- -float GeneticFitness::drawSelectionCoef() { +float GeneticFitnessTrait::drawSelectionCoef() { DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); map mutationParameters = pSpeciesTrait->getMutationParameters(); - float s = 0.0; //default selection coefficient is 0 + float s = 0.0; // default selection coefficient is 0 switch (mutationDistribution) { case UNIFORM: { float maxD = mutationParameters.find(MAX)->second; float minD = mutationParameters.find(MIN)->second; - s = pRandom->FRandom(minD, maxD); + s = pRandom->FRandom(minD, maxD); // no check here, min and max should already be constrained to valid values break; } case NORMAL: { const float mean = mutationParameters.find(MEAN)->second; const float sd = mutationParameters.find(SD)->second; - s = static_cast(pRandom->Normal(mean, sd)); + do { + s = static_cast(pRandom->Normal(mean, sd)); + } while (!pSpeciesTrait->isValidTraitVal(s)); break; } case GAMMA: { const float shape = mutationParameters.find(SHAPE)->second; const float scale = mutationParameters.find(SCALE)->second; - s = static_cast(pRandom->Gamma(shape, scale)); + do { + s = static_cast(pRandom->Gamma(shape, scale)); + } while (!pSpeciesTrait->isValidTraitVal(s)); break; } case NEGEXP: { const float mean = mutationParameters.find(MEAN)->second; - s = static_cast(pRandom->NegExp(mean)); + do { + s = static_cast(pRandom->NegExp(mean)); + } while (!pSpeciesTrait->isValidTraitVal(s)); break; } default: @@ -263,9 +275,9 @@ float GeneticFitness::drawSelectionCoef() { // ---------------------------------------------------------------------------------------- // Wrapper to inheritance function // ---------------------------------------------------------------------------------------- -void GeneticFitness::inheritGenes(const bool& fromMother, TTrait* parentTrait, set const& recomPositions, int startingChromosome) +void GeneticFitnessTrait::inheritGenes(const bool& fromMother, TTrait* parentTrait, set const& recomPositions, int startingChromosome) { - auto parentCast = dynamic_cast (parentTrait); // must convert TTrait to GeneticFitness + auto parentCast = dynamic_cast (parentTrait); // must convert TTrait to GeneticFitnessTrait const auto& parent_seq = parentCast->getGenes(); (this->*_inherit_func_ptr) (fromMother, parent_seq, recomPositions, startingChromosome); } @@ -276,7 +288,7 @@ void GeneticFitness::inheritGenes(const bool& fromMother, TTrait* parentTrait, s // populates offspring genes with appropriate parent alleles // Assumes mother genes are inherited first // ---------------------------------------------------------------------------------------- -void GeneticFitness::inheritDiploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { +void GeneticFitnessTrait::inheritDiploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { auto it = recomPositions.lower_bound(parentGenes.begin()->first); int nextBreakpoint = *it; @@ -316,7 +328,7 @@ void GeneticFitness::inheritDiploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) +void GeneticFitnessTrait::inheritHaploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { genes = parentGenes; } @@ -324,7 +336,7 @@ void GeneticFitness::inheritHaploid(const bool& fromMother, map clone() const override { return std::make_unique(*this); } + virtual unique_ptr clone() const override { return std::make_unique(*this); } - virtual ~GeneticFitness() { } + virtual ~GeneticFitnessTrait() { } // Getters virtual int getNLoci() const override { return pSpeciesTrait->getPositionsSize(); } @@ -69,7 +69,7 @@ class GeneticFitness : public TTrait { //// Species-level trait attributes, invariant across individuals SpeciesTrait* pSpeciesTrait; //// Species-level trait functions - void (GeneticFitness::* _inherit_func_ptr) (const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); + void (GeneticFitnessTrait::* _inherit_func_ptr) (const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); // Possible values for immutable functions //// Inheritance diff --git a/Individual.cpp b/Individual.cpp index 6bc21f5..603cba9 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -35,7 +35,7 @@ Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short rep float probmale, bool movt, short moveType) { indId = indCounter; indCounter++; // unique identifier for each individual - probViability = 1.0; + geneticFitness = 1.0; stage = stg; if (probmale <= 0.0) sex = FEM; else sex = pRandom->Bernoulli(probmale) ? FEM : MAL; @@ -178,7 +178,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi newTrait->mutate(); } if (trait == GENETIC_LOAD1 || trait == GENETIC_LOAD2 || trait == GENETIC_LOAD3 || trait == GENETIC_LOAD4 || trait == GENETIC_LOAD5) - probViability *= newTrait->express(); + geneticFitness *= newTrait->express(); // Add the inherited trait and genes to the newborn's list spTraitTable.insert(make_pair(trait, move(newTrait))); @@ -205,7 +205,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother) { newTrait->mutate(); } if (trait == GENETIC_LOAD1 || trait == GENETIC_LOAD2 || trait == GENETIC_LOAD3 || trait == GENETIC_LOAD4 || trait == GENETIC_LOAD5) - probViability *= newTrait->express(); + geneticFitness *= newTrait->express(); // Add the inherited trait and genes to the newborn's list spTraitTable.insert(make_pair(trait, move(newTrait))); @@ -309,7 +309,7 @@ sex_t Individual::getSex(void) { return sex; } int Individual::getStatus(void) { return status; } -float Individual::getProbViability(void) { return probViability; } +float Individual::getGeneticFitness(void) { return geneticFitness; } indStats Individual::getStats(void) { indStats s; diff --git a/Individual.h b/Individual.h index 91c4888..a84b397 100644 --- a/Individual.h +++ b/Individual.h @@ -293,7 +293,7 @@ class Individual { int getId(void); sex_t getSex(void); int getStatus(void); - float getProbViability(void); + float getGeneticFitness(void); indStats getStats(void); Cell* getLocn( // Return location (as pointer to Cell) const short // option: 0 = get natal locn, 1 = get current locn @@ -372,7 +372,7 @@ class Individual { private: int indId; - float probViability; + float geneticFitness; short stage; sex_t sex; short age; diff --git a/Population.cpp b/Population.cpp index 5a2302c..ea4c5f7 100644 --- a/Population.cpp +++ b/Population.cpp @@ -224,7 +224,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { ts.sumS0[sex] = ts.ssqS0[sex] = 0.0; ts.sumAlphaS[sex] = ts.ssqAlphaS[sex] = 0.0; ts.sumBetaS[sex] = ts.ssqBetaS[sex] = 0.0; - ts.sumProbViability[sex] = ts.ssqProbViability[sex] = 0.0; + ts.sumGeneticFitness[sex] = ts.ssqGeneticFitness[sex] = 0.0; } emigRules emig = pSpecies->getEmigRules(); @@ -309,8 +309,8 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { if (maxNbSexes > 1) g = sex; else g = 0; - ts.sumProbViability[g] += inds[iInd]->getProbViability(); - ts.ssqProbViability[g] += inds[iInd]->getProbViability() * inds[iInd]->getProbViability(); + ts.sumGeneticFitness[g] += inds[iInd]->getGeneticFitness(); + ts.ssqGeneticFitness[g] += inds[iInd]->getGeneticFitness() * inds[iInd]->getGeneticFitness(); } return ts; } @@ -685,7 +685,9 @@ void Population::reproduction(const float localK, const float envval, const int newJuv->inheritTraits(pSpecies, inds[i], father, resol); } - if (newJuv->getProbViability() < pRandom->Random()) { + float probViability = newJuv->getGeneticFitness(); + if (probViability > 1.0) probViability = 1.0; + if (probViability < pRandom->Random()) { delete newJuv; } else { @@ -765,7 +767,9 @@ void Population::reproduction(const float localK, const float envval, const int if (pSpecies->getNTraits() > 0) { newJuv->inheritTraits(pSpecies, inds[i], father, resol); } - if (newJuv->getProbViability() < pRandom->Random()) { + float probViability = newJuv->getGeneticFitness(); + if (probViability > 1.0) probViability = 1.0; + if (probViability < pRandom->Random()) { delete newJuv; } else { @@ -1862,7 +1866,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, if (dem.repType != 0) outInds << "\t" << ind.sex; if (dem.stageStruct) outInds << "\t" << ind.age << "\t" << ind.stage; - if (pSpecies->getNbGenLoadTraits() > 0) outInds << "\t" << inds[i]->getProbViability(); + if (pSpecies->getNbGenLoadTraits() > 0) outInds << "\t" << inds[i]->getGeneticFitness(); if (emig.indVar) { emigTraits e = inds[i]->getEmigTraits(); diff --git a/Population.h b/Population.h index 4258007..642e623 100644 --- a/Population.h +++ b/Population.h @@ -103,8 +103,8 @@ struct traitsums { // sums of trait genes for dispersal double ssqAlphaS[maxNbSexes]; // sum of squares of slope of settlement den-dep reaction norm double sumBetaS[maxNbSexes]; // sum of inflection point of settlement reaction norm double ssqBetaS[maxNbSexes]; // sum of squares of inflection point of settlement reaction norm - double sumProbViability[maxNbSexes]; - double ssqProbViability[maxNbSexes]; + double sumGeneticFitness[maxNbSexes]; + double ssqGeneticFitness[maxNbSexes]; }; class Population { diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index d9f2cc1..68897e7 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -66,8 +66,8 @@ SpeciesTrait::SpeciesTrait( switch (paramType) { case MIN: case MAX: case MEAN: - if (paramVal < 0.0 || paramVal > 1.0) - throw logic_error("Invalid parameter value: dominance parameter " + to_string(paramType) + " must be between 0 and 1."); + if (paramVal < 0.0) + throw logic_error("Invalid parameter value: dominance parameter " + to_string(paramType) + " must not be negative."); break; case SD: case SHAPE: case SCALE: if (paramVal <= 0.0) @@ -90,7 +90,8 @@ bool SpeciesTrait::isValidTraitVal(const float& val) const { // Genetic Load case GENETIC_LOAD: case GENETIC_LOAD1: case GENETIC_LOAD2: case GENETIC_LOAD3: case GENETIC_LOAD4: case GENETIC_LOAD5: { - return val >= 0.0 && val <= 1.0; // substracted from a probability + return val >= -1.0 // genetic fitness traits can be beneficial + && val <= 1.0; break; } // Quantitative trait loci diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 7439c1a..eb8b11a 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -753,7 +753,7 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; ts.sumS0[i] = ts.ssqS0[i] = 0.0; ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; - ts.sumProbViability[i] = ts.ssqProbViability[i] = 0.0; + ts.sumGeneticFitness[i] = ts.ssqGeneticFitness[i] = 0.0; } // generate output for each population within the sub-community (patch) @@ -999,9 +999,9 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, if (ngenes == 2) popsize = indTraitsSums.ninds[iGene]; else popsize = indTraitsSums.ninds[0] + indTraitsSums.ninds[1]; if (popsize > 0) { - mnProbViable[iGene] = indTraitsSums.sumProbViability[iGene] / (double)popsize; + mnProbViable[iGene] = indTraitsSums.sumGeneticFitness[iGene] / (double)popsize; if (popsize > 1) { - sdProbViable[iGene] = indTraitsSums.ssqProbViability[iGene] / (double)popsize - mnProbViable[iGene] * mnProbViable[iGene]; + sdProbViable[iGene] = indTraitsSums.ssqGeneticFitness[iGene] / (double)popsize - mnProbViable[iGene] * mnProbViable[iGene]; if (sdProbViable[iGene] > 0.0) sdProbViable[iGene] = sqrt(sdProbViable[iGene]); else sdProbViable[iGene] = 0.0; } else { @@ -1055,8 +1055,8 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, ts.ssqAlphaS[iSex] += indTraitsSums.ssqAlphaS[iSex]; ts.sumBetaS[iSex] += indTraitsSums.sumBetaS[iSex]; ts.ssqBetaS[iSex] += indTraitsSums.ssqBetaS[iSex]; - ts.sumProbViability[iSex] += indTraitsSums.sumProbViability[iSex]; - ts.ssqProbViability[iSex] += indTraitsSums.ssqProbViability[iSex]; + ts.sumGeneticFitness[iSex] += indTraitsSums.sumGeneticFitness[iSex]; + ts.ssqGeneticFitness[iSex] += indTraitsSums.ssqGeneticFitness[iSex]; } } } diff --git a/TraitFactory.h b/TraitFactory.h index dbe07b0..889eeae 100644 --- a/TraitFactory.h +++ b/TraitFactory.h @@ -6,7 +6,7 @@ #include "SpeciesTrait.h" #include "SNPTrait.h" #include "QTLTrait.h" -#include "GeneticFitness.h" +#include "GeneticFitnessTrait.h" // Create handled pointers to a new trait class TraitFactory @@ -24,7 +24,7 @@ class TraitFactory || traitType == GENETIC_LOAD3 || traitType == GENETIC_LOAD4 || traitType == GENETIC_LOAD5) { - return make_unique(protoTrait); + return make_unique(protoTrait); } else { return make_unique(protoTrait); From 5ff12d15f7fbeb14b5c33bcad9c94637a8d93e20 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Mon, 13 May 2024 08:05:49 +0200 Subject: [PATCH 117/332] Manually copying changes for translocation to RScore as git subtree push led to a cache error --- Community.cpp | 1 - Community.h | 26 ++++--- Genome.cpp | 2 + Genome.h | 9 ++- Individual.cpp | 24 +++--- Landscape.cpp | 7 ++ Landscape.h | 30 ++++---- Model.cpp | 50 ++++++++++++ Model.h | 24 +++--- Parameters.cpp | 2 - Parameters.h | 28 +++---- Population.cpp | 205 ++++++++++++++++++++++++++++++++++++++++++++++--- Population.h | 59 +++++++++++--- 13 files changed, 380 insertions(+), 87 deletions(-) diff --git a/Community.cpp b/Community.cpp index 286dc6a..a3004b9 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1556,7 +1556,6 @@ Rcpp::IntegerMatrix Community::addYearToPopList(int rep, int yr) { // TODO: def return pop_map_year; } #endif - //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- diff --git a/Community.h b/Community.h index c55b333..9020b3a 100644 --- a/Community.h +++ b/Community.h @@ -1,25 +1,25 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - + + /*------------------------------------------------------------------------------ RangeShifter v2.0 Community @@ -35,9 +35,9 @@ Optionally, the Community maintains a record of the occupancy of suitable cells or patches during the course of simulation of multiple replicates. For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. +Bocedi G., Palmer S.C.F., Pe?er G., Heikkinen R.K., Matsinos Y.G., Watts K. and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. +eco-evolutionary dynamics and species? responses to environmental changes. Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 Authors: Greta Bocedi & Steve Palmer, University of Aberdeen @@ -59,6 +59,8 @@ using namespace std; #include "Cell.h" #include "Species.h" +// #include "Management.h" + //--------------------------------------------------------------------------- struct commStats { int ninds,nnonjuvs,suitable,occupied; @@ -180,7 +182,7 @@ class Community { int // Landscape number (-999 to close the file) ); void outTraits( // Write records to traits file - traitCanvas,// pointers to canvases for drawing variable traits + traitCanvas,// pointers to canvases for drawing variable traits // see SubCommunity.h // in the batch version, these are replaced by integers set to zero Species*, // pointer to Species diff --git a/Genome.cpp b/Genome.cpp index 59a68b1..4550e5b 100644 --- a/Genome.cpp +++ b/Genome.cpp @@ -124,12 +124,14 @@ void Chromosome::inherit(const Chromosome* parentChr, const short posn, const sh for (int i = 0; i < nloc; i++) { if (diploid) { pLoci[i].allele[posn] = parentChr->pLoci[i].allele[ix]; + if (probcross >1) Rcpp::Rcout << "Crossover probability: " << probcross << std::endl; if (pRandom->Bernoulli(probcross)) { // crossover occurs if (ix == 0) ix = 1; else ix = 0; } } else pLoci[i].allele[posn] = parentChr->pLoci[i].allele[0]; + if (probmutn >1) Rcpp::Rcout << "Mutation probability: " << probmutn << std::endl; if (pRandom->Bernoulli(probmutn)) { // mutation occurs double intbase = INTBASE; #if RSDEBUG diff --git a/Genome.h b/Genome.h index 4f01ede..79b163d 100644 --- a/Genome.h +++ b/Genome.h @@ -24,6 +24,7 @@ #include #include +#include #include "Parameters.h" #include "Species.h" @@ -55,7 +56,7 @@ class Chromosome { const int // position of locus on chromosome ); void initialise( // Set up chromosome at simulation initialisation - const double, // normalised phenotypic trait value + const double, // normalised phenotypic trait value const double, // s.d. of allelic variance (genetic scale) const bool // diploid ); @@ -95,13 +96,13 @@ class Genome { void setGene( // Set up new gene at initialisation for 1 chromosome per trait const short, // chromosome number const short, // expression type (NOT CURRENTLY USED) - const double, // normalised trait value + const double, // normalised trait value const double // s.d. of allelic variance ); void setTrait( // Set up trait at initialisation for trait mapping Species*, // pointer to Species - const int, // trait number - const double, // normalised trait value + const int, // trait number + const double, // normalised trait value const double // s.d. of allelic variance ); void setNeutralLoci( // Set up neutral loci at initialisation diff --git a/Individual.cpp b/Individual.cpp index cb6c5f8..e1ab257 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -37,6 +37,7 @@ Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short rep indCounter++; // unique identifier for each individual stage = stg; + if (probmale > 1) Rcpp::Rcout << "probmale = " << probmale << std::endl; if (probmale <= 0.0) sex = 0; else sex = pRandom->Bernoulli(probmale); age = a; @@ -62,9 +63,9 @@ Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short rep smsData = new smsdata; smsData->dp = smsData->gb = smsData->alphaDB = 1.0; smsData->betaDB = 1; - smsData->prev.x = loc.x; + smsData->prev.x = loc.x; smsData->prev.y = loc.y; // previous location - smsData->goal.x = loc.x; + smsData->goal.x = loc.x; smsData->goal.y = loc.y; // goal location - initialised for dispersal bias } else smsData = 0; @@ -406,7 +407,7 @@ void Individual::setGenes(Species* pSpecies, Individual* mother, Individual* fat // if so, return her stage, otherwise return 0 int Individual::breedingFem(void) { if (sex == 0) { - if (status == 0 || status == 4 || status == 5) return stage; + if (status == 0 || status == 4 || status == 5 || status == 10) return stage; else return 0; } else return 0; @@ -818,7 +819,7 @@ settleTraits Individual::getSettTraits(void) { void Individual::setStatus(short s) { - if (s >= 0 && s <= 9) status = s; + if (s >= 0 && s <= 10) status = s; status = s; } @@ -831,7 +832,7 @@ void Individual::develop(void) { } void Individual::ageIncrement(short maxage) { - if (status < 6) { // alive + if (status < 6 || status == 10) { // alive age++; if (age > maxage) status = 9; // exceeds max. age - dies else { @@ -855,7 +856,7 @@ void Individual::moveto(Cell* newCell) { double d = sqrt(((double)currloc.x - (double)newloc.x) * ((double)currloc.x - (double)newloc.x) + ((double)currloc.y - (double)newloc.y) * ((double)currloc.y - (double)newloc.y)); if (d >= 1.0 && d < 1.5) { // ok - pCurrCell = newCell; + pCurrCell = newCell; status = 5; } } @@ -921,6 +922,7 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, // scale the appropriate kernel mean to the cell size if (trfr.twinKern) { + if (kern.probKern1 > 1) Rcpp::Rcout << "probKern1 = " << kern.probKern1<< std::endl; if (pRandom->Bernoulli(kern.probKern1)) meandist = kern.meanDist1 / (float)land.resol; else @@ -1040,7 +1042,7 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, // apply dispersal-related mortality, which may be distance-dependent dist *= (float)land.resol; // re-scale distance moved to landscape scale - if (status < 7) { + if (status < 7 || status == 10) { double dispmort; trfrMortParams mort = pSpecies->getMortParams(); if (trfr.distMort) { @@ -1049,6 +1051,7 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, else { dispmort = mort.fixedMort; } + if(dispmort > 1) Rcpp::Rcout << "dispmort = " << dispmort << std::endl; if (pRandom->Bernoulli(dispmort)) { status = 7; // dies dispersing = 0; @@ -1110,6 +1113,7 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, if (pPatch == pNatalPatch && path->out == 0 && path->year == path->total) { mortprob = 0.0; } + if (mortprob > 1) Rcpp::Rcout << "mortprob = " << mortprob << std::endl; if (pRandom->Bernoulli(mortprob)) { // individual dies status = 7; dispersing = 0; @@ -1758,7 +1762,7 @@ void Individual::outMovePath(const int year) << endl; } // if not anymore dispersing... - if (status > 1 && status < 10) { + if (status > 1 && status <= 10) { prev_loc = pPrevCell->getLocn(); // record only if this is the first step as non-disperser if (path->pathoutput) { @@ -1835,10 +1839,10 @@ void testIndividual() { //ind.moveto(); // Gets its sex drawn from pmale - + // Can age or develop - // + // // Reproduces // depending on whether it is sexual or not diff --git a/Landscape.cpp b/Landscape.cpp index 916b6ef..2fc8b0f 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -894,6 +894,13 @@ Cell* Landscape::findCell(int x, int y) { else return 0; } +bool Landscape::checkDataCell(int x, int y) { + Cell* pCell; + pCell = findCell(x, y); + return true; +} + + int Landscape::patchCount(void) { return (int)patches.size(); } diff --git a/Landscape.h b/Landscape.h index 2a414cc..e4e0c01 100644 --- a/Landscape.h +++ b/Landscape.h @@ -1,25 +1,25 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - + + /*------------------------------------------------------------------------------ RangeShifter v2.0 Landscape @@ -58,9 +58,9 @@ to be intialised, which are specified by the user in FormSeeding. This option is available in the GUI version only. For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. +Bocedi G., Palmer S.C.F., Pe?er G., Heikkinen R.K., Matsinos Y.G., Watts K. and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. +eco-evolutionary dynamics and species? responses to environmental changes. Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 Authors: Greta Bocedi & Steve Palmer, University of Aberdeen @@ -142,7 +142,7 @@ class InitDist{ //--------------------------------------------------------------------------- -struct landParams { +struct landParams { bool patchModel; bool spDist; bool generated; bool dynamic; int landNum; int resol; int spResol; int nHab; int nHabMax; @@ -300,6 +300,10 @@ class Landscape{ int, // x co-ordinate int // y co-ordinate ); + bool checkDataCell( + int, // x co-ordinate + int // y co-ordinate + ); int patchCount(void); void updateHabitatIndices(void); void setEnvGradient( @@ -525,7 +529,7 @@ class Landscape{ int **connectMatrix; // global environmental stochasticity (epsilon) - float *epsGlobal; // pointer to time-series + float *epsGlobal; // pointer to time-series // patch and costs change matrices (temporary - used when reading dynamic landscape) // indexed by [descending y][x][period] diff --git a/Model.cpp b/Model.cpp index 3134f8d..a1654e6 100644 --- a/Model.cpp +++ b/Model.cpp @@ -43,6 +43,8 @@ int RunModel(Landscape* pLandscape, int seqsim) demogrParams dem = pSpecies->getDemogr(); stageParams sstruct = pSpecies->getStage(); trfrRules trfr = pSpecies->getTrfr(); + managementParams manage = pManagement->getManagementParams(); + translocationParams transloc = pManagement->getTranslocationParams(); initParams init = paramsInit->getInit(); simParams sim = paramsSim->getSim(); simView v = paramsSim->getViews(); @@ -486,6 +488,14 @@ int RunModel(Landscape* pLandscape, int seqsim) } #endif + // TODO move translocation before dispersal? + if (manage.translocation && std::find(transloc.translocation_years.begin(), transloc.translocation_years.end(), yr) != transloc.translocation_years.end()) { + pManagement->translocate(yr + , pLandscape + , pSpecies + ); + } + if (v.viewPop || (sim.saveMaps && yr % sim.mapInt == 0)) { if (updateland && gen == 0) { pLandscape->drawLandscape(rep, landIx, ppLand.landNum); @@ -559,6 +569,7 @@ int RunModel(Landscape* pLandscape, int seqsim) else { // non-structured population pComm->survival(0, 1, 1); } + #if RSDEBUG DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed survival part 0" << endl; #endif @@ -1928,6 +1939,45 @@ void OutParameters(Landscape* pLandscape) } } + // Management + managementParams manage = pManagement->getManagementParams(); + translocationParams transloc = pManagement->getTranslocationParams(); + if(manage.translocation){ + outPar << endl << "MANAGEMENT - TRANSLOCATION: \t"; + // loop over translocation_years and print them + outPar << endl; + outPar << "Catching rate: " << transloc.catching_rate << endl; + for( int i = 0; i < transloc.translocation_years.size(); i++ ) { + auto yr = transloc.translocation_years[i]; + auto it = transloc.nb.find(yr); + auto nb_it = transloc.nb.find(yr); + auto source_it = transloc.source.find(yr); + auto target_it = transloc.target.find(yr); + auto min_age_it = transloc.min_age.find(yr); + auto max_age_it = transloc.max_age.find(yr); + auto stage_it = transloc.stage.find(yr); + auto sex_it = transloc.sex.find(yr); + outPar << " Translocation events in year: " << yr << endl; + for( int j = 0; j < it->second.size(); j++ ){ + outPar << " Event Nr. " << j+1 << " :" << endl; + // if it is a cell based model + if(ppLand.patchModel){ + outPar << " Source patch ID: " << source_it->second[j].x << endl; + outPar << " Target patch ID: " << target_it->second[j].x << endl; + } else{ + outPar << " Source cell: X " << source_it->second[j].x << " Y " << source_it->second[j].y << endl; + outPar << " Target cell: X " << target_it->second[j].x << " Y " << target_it->second[j].y << endl; + } + outPar << " Min age: " << min_age_it->second[j] << endl; + outPar << " Max age: " << max_age_it->second[j] << endl; + outPar << " Stage: " << stage_it->second[j] << endl; + outPar << " Sex: " << sex_it->second[j] << endl; + outPar << " Number of individuals: " << nb_it->second[j] << endl; + + } + } + } + // Initialisation initParams init = paramsInit->getInit(); diff --git a/Model.h b/Model.h index f48d155..cf47aba 100644 --- a/Model.h +++ b/Model.h @@ -1,25 +1,25 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - + + /*------------------------------------------------------------------------------ RangeShifter v2.0 Model @@ -33,9 +33,9 @@ Further functions are declared here, but defined differently in main function of GUI and batch versions. For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. +Bocedi G., Palmer S.C.F., Pe?er G., Heikkinen R.K., Matsinos Y.G., Watts K. and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. +eco-evolutionary dynamics and species? responses to environmental changes. Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 Authors: Greta Bocedi & Steve Palmer, University of Aberdeen @@ -54,6 +54,7 @@ Last updated: 26 October 2021 by Steve Palmer #include "Community.h" #include "SubCommunity.h" #include "Species.h" +#include "Management.h" #if !RS_EMBARCADERO && !LINUX_CLUSTER && !RS_RCPP #include @@ -113,6 +114,7 @@ extern Species *pSpecies; extern paramSim *paramsSim; extern paramInit *paramsInit; extern Community *pComm; +extern Management *pManagement; const bool batchMode = true; extern string landFile; diff --git a/Parameters.cpp b/Parameters.cpp index 5cfb3d7..ca25381 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -377,6 +377,4 @@ bool paramSim::getCreatePopFile(void) { return CreatePopFile; } #endif //--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- diff --git a/Parameters.h b/Parameters.h index 9cc51d2..ba76ab0 100644 --- a/Parameters.h +++ b/Parameters.h @@ -1,25 +1,25 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - + + /*------------------------------------------------------------------------------ RangeShifter v2.0 Parameters @@ -34,9 +34,9 @@ paramStoch - Environmental stochasticity parameters Also declares some structures and functions used throughout the program. For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. +Bocedi G., Palmer S.C.F., Pe?er G., Heikkinen R.K., Matsinos Y.G., Watts K. and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. +eco-evolutionary dynamics and species? responses to environmental changes. Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 Authors: Greta Bocedi & Steve Palmer, University of Aberdeen @@ -59,6 +59,7 @@ Last updated: 25 June 2021 by Steve Palmer #include #include #include +#include using namespace std; #include "RSrandom.h" @@ -167,7 +168,7 @@ class paramGrad { struct envStochParams { bool stoch; bool local; bool inK; bool localExt; - float ac; float std; + float ac; float std; float locExtProb; }; @@ -185,7 +186,7 @@ class paramStoch { bool local; // applied locally (if not, application is global) bool inK; // in carrying capacity (if not, in growth rate) bool localExt; // local extinction applied - float ac; // temporal autocorrelation coefficient + float ac; // temporal autocorrelation coefficient float std; // amplitude of fluctuations: sampled from N(0,std) float locExtProb; // local extinction probability }; @@ -377,6 +378,7 @@ class paramSim { }; +//--------------------------------------------------------------------------- #if RSDEBUG extern ofstream DEBUGLOG; void DebugGUI(string); diff --git a/Population.cpp b/Population.cpp index 3dbb6a2..9960075 100644 --- a/Population.cpp +++ b/Population.cpp @@ -204,6 +204,11 @@ Population::~Population(void) { if (juvs[i] != NULL) delete juvs[i]; } juvs.clear(); + int nsampledInds = (int)sampledInds.size(); + for (int i = 0; i < nsampledInds; i++) { + if (sampledInds[i] != NULL) sampledInds[i]=NULL; + } + sampledInds.clear(); } traitsums Population::getTraits(Species* pSpecies) { @@ -411,7 +416,7 @@ void Population::reproduction(const float localK, const float envval, const int if (sstruct.fecDens) { // apply density dependence float effect = 0.0; if (sstruct.fecStageDens) { // stage-specific density dependence - // NOTE: matrix entries represent effect of ROW on COLUMN + // NOTE: matrix entries represent effect of ROW on COLUMN // AND males precede females float weight = 0.0; for (int effstg = 0; effstg < nStages; effstg++) { @@ -470,6 +475,7 @@ void Population::reproduction(const float localK, const float envval, const int // determine whether she must miss current breeding attempt ind = inds[i]->getStats(); if (ind.fallow >= sstruct.repInterval) { + if(sstruct.probRep > 1) Rcpp::Rcout << "probRep: " << sstruct.probRep << std::endl; if (pRandom->Bernoulli(sstruct.probRep)) skipbreeding = false; else skipbreeding = true; } @@ -534,6 +540,7 @@ void Population::reproduction(const float localK, const float envval, const int // determine whether she must miss current breeding attempt ind = inds[i]->getStats(); if (ind.fallow >= sstruct.repInterval) { + if(sstruct.probRep > 1) Rcpp::Rcout << "probRep: " << sstruct.probRep << std::endl; if (pRandom->Bernoulli(sstruct.probRep)) skipbreeding = false; else skipbreeding = true; } @@ -547,6 +554,7 @@ void Population::reproduction(const float localK, const float envval, const int inds[i]->resetFallow(); // NOTE: FOR COMPLEX SEXUAL MODEL, NO. OF FEMALES *ACTUALLY* BREEDING DOES NOT // NECESSARILY EQUAL THE EXPECTED NO. FROM EQN. 7 IN THE MANUAL... + if(propBreed > 1) Rcpp::Rcout << "propBreed: " << propBreed << std::endl; if (pRandom->Bernoulli(propBreed)) { expected = fec[stage][0]; // breeds } @@ -685,7 +693,7 @@ void Population::emigration(float localK) for (int i = 0; i < ninds; i++) { ind = inds[i]->getStats(); - if (ind.status < 1) + if (ind.status < 1) // ToDo: Maybe allow dispersal after translocation? If so, we need to update the pPrevCell and pCurrCell variables of the translocated individuals! { if (emig.indVar) { // individual variability in emigration if (dem.stageStruct && ind.stage != emig.emigStage) { @@ -749,7 +757,7 @@ void Population::emigration(float localK) } // end of no individual variability - + if (disp > 1) Rcpp::Rcout << "disp: " << disp << std::endl; disp = pRandom->Bernoulli(Pdisp); if (disp == 1) { // emigrant @@ -886,7 +894,7 @@ int Population::transfer(Landscape* pLandscape, short landIx) // this condition can occur in a patch-based model at the time of a dynamic landscape // change when there is a range restriction in place, since a patch can straddle the // range restriction and an individual forced to disperse upon patch removal could - // start its trajectory beyond the boundary of the restrictyed range - such a model is + // start its trajectory beyond the boundary of the restrictyed range - such a model is // not good practice, but the condition must be handled by killing the individual conceerned ind.status = 6; } @@ -947,6 +955,8 @@ int Population::transfer(Landscape* pLandscape, short landIx) settprob = settDD.s0 / (1.0 + exp(-(popsize / localK - (double)settDD.beta) * (double)settDD.alpha)); + if (settprob > 1) Rcpp::Rcout << "settprob: " << settprob << std::endl; + if (pRandom->Bernoulli(settprob)) { // settlement allowed densdepOK = true; settle.settleStatus = 2; @@ -1167,7 +1177,7 @@ void Population::survival0(float localK, short option0, short option1) // which must develop to stage 1 if they survive float effect = 0.0; if (sstruct.devStageDens) { // stage-specific density dependence - // NOTE: matrix entries represent effect of ROW on COLUMN + // NOTE: matrix entries represent effect of ROW on COLUMN // AND males precede females float weight = 0.0; for (int effstg = 0; effstg < nStages; effstg++) { @@ -1193,7 +1203,7 @@ void Population::survival0(float localK, short option0, short option1) if (option1 != 0 && sstruct.survDens) { float effect = 0.0; if (sstruct.survStageDens) { // stage-specific density dependence - // NOTE: matrix entries represent effect of ROW on COLUMN + // NOTE: matrix entries represent effect of ROW on COLUMN // AND males precede females float weight = 0.0; for (int effstg = 0; effstg < nStages; effstg++) { @@ -1225,14 +1235,16 @@ void Population::survival0(float localK, short option0, short option1) indStats ind = inds[i]->getStats(); if ((ind.stage == 0 && option0 < 2) || (ind.stage > 0 && option0 > 0)) { // condition for processing the stage is met... - if (ind.status < 6) { // not already doomed + if (ind.status < 6 || ind.status == 10) { // not already doomed double probsurv = surv[ind.stage][ind.sex]; // does the individual survive? + if (probsurv > 1) Rcpp::Rcout << "probsurv at stage: " << ind.stage << " and sex " << ind.sex << " : " << probsurv << std::endl; if (pRandom->Bernoulli(probsurv)) { // survives // does the individual develop? double probdev = dev[ind.stage][ind.sex]; if (ind.stage < nStages - 1) { // not final stage if (ind.age >= minAge[ind.stage + 1][ind.sex]) { // old enough to enter next stage + if (probdev > 1) Rcpp::Rcout << "probdev: " << probdev << std::endl; if (pRandom->Bernoulli(probdev)) { inds[i]->developing(); } @@ -1254,7 +1266,7 @@ void Population::survival1(void) int ninds = (int)inds.size(); for (int i = 0; i < ninds; i++) { indStats ind = inds[i]->getStats(); - if (ind.status > 5) { // doomed to die + if (ind.status > 5 && ind.status != 10) { // doomed to die 10 is translocated delete inds[i]; inds[i] = NULL; nInds[ind.stage][ind.sex]--; @@ -1666,8 +1678,181 @@ void Population::outGenetics(const int rep, const int year, const int landNr) } -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// Extract all individuals of a population with certain characteristics based on age, stage and sex +// returns a set of pointers to the individuals +// --------------------------------------------------------------------------- +std::vector Population::getIndsWithCharacteristics( // Select a set of individuals with specified characteristics + int min_age, // min age (0 if not set) + int max_age, // max age (max age if not set) + int stage, // stage + int sex //sex +){ + // get all suitable individuals based on settings + std::vector filteredInds; + int ninds = (int)inds.size(); + Rcpp::Rcout << "Number individuals in cell: " << ninds << endl; + + if (ninds > 0) { + // copy ALL individuals to filteredInds + for (int i = 0; i < ninds; i++) { + filteredInds.push_back(inds[i]); + } + + // check status of inividuals + for (int i = 0; i < ninds; i++) { + if (inds[i] != NULL && inds[i]->getStats().status != 0 && inds[i]->getStats().status != 4 && inds[i]->getStats().status != 5){ // only accept individuals with status 0, 4 or 5 (not in transfer phase + not dead + not already translocated) + // Rcpp::Rcout << "Status: " << inds[i]->getStats().status << endl; + filteredInds[i] = NULL; // set it to NULL + } + } + + // Check minimal age + if (min_age!=-9){ + // loop over all number of individuals in cell + for (int i = 0; i < ninds; i++) { + if (filteredInds[i] != NULL && inds[i]->getStats().age < min_age){ // if not already NULL + age too young + filteredInds[i] = NULL; // set it to NULL + } + } + } + // check max age + if (max_age!=-9){ + // loop over all number of individuals in cell + for (int i = 0; i < ninds; i++) { + if (filteredInds[i] != NULL && inds[i]->getStats().age < max_age){// if not already NULL + age too old + if (filteredInds[i] != NULL) filteredInds[i] = NULL; // set it to NULL if not already NULL + } + } + } + // check stage + if (stage!=-9){ + // loop over all number of individuals in cell + for (int i = 0; i < ninds; i++) { + if (filteredInds[i] != NULL && inds[i]->getStats().stage != stage){// if not already NULL + stage not correct + if (filteredInds[i] != NULL) filteredInds[i] = NULL; // set it to NULL if not already NULL + } + } + } + // check sex + if (sex!=-9){ + // loop over all number of individuals in cell + for (int i = 0; i < ninds; i++) { + if (filteredInds[i] != NULL && inds[i]->getStats().sex != sex){// if not already NULL + sex not correct + if (filteredInds[i] != NULL) filteredInds[i] = NULL; // set it to NULL if not already NULL + } + } + } + } else { + Rcpp::Rcout << "No individuals in source patch" << endl; + return filteredInds; + } + int nfiltered = 0; + for ( auto filtered : filteredInds){ + if (filtered != NULL) nfiltered++; + } + + // loop over iterator of filteredInds and remove NULL values + filteredInds.erase(std::remove(filteredInds.begin(), filteredInds.end(), nullptr), filteredInds.end()); + + return filteredInds; +}; +// --------------------------------------------------------------------------- +// Clean the sampled individuals +// --------------------------------------------------------------------------- +void Population::cleanSampledInds(Individual* pInd // Return a set of individuals with specified characteristics +){ + // find inds[j] and remove it from sampledInds + sampledInds.erase(std::remove(sampledInds.begin(), sampledInds.end(), pInd), sampledInds.end()); +}; +// --------------------------------------------------------------------------- +// Sample N individuals from the population with a given set of characteristics +// --------------------------------------------------------------------------- +int Population::sampleIndividuals( // Select a set of individuals with specified characteristics +// void Population::sampleIndividuals( // Select a set of individuals with specified characteristics + int nb, // number of individuals to sample + int min_age, // min age (0 if not set) + int max_age, // max age (max age if not set) + int stage, // stage + int sex //sex + ){ + if(sampledInds.size() > 0) sampledInds.clear(); // clear old vector + auto rng = pRandom->getRNG(); // random number for sampling from suitable individuals + + // get individuals with the characteristics + std::vector filtered; + filtered = getIndsWithCharacteristics(min_age, max_age, stage, sex); + + Rcpp::Rcout << "Number of individuals with fitting characteristics: " << filtered.size() << endl; + + if (filtered.size() <= nb) + // Sample all individuals in selected stages + sampledInds = filtered; + else { + vector out; + // Sample n individuals across filtered individuals + std::sample(filtered.begin(), filtered.end(), std::back_inserter(out), nb, rng); + std::copy(out.begin(), out.end(), std::inserter(sampledInds, sampledInds.end())); + } + + int nb_sampled = 0; + if (sampledInds.size() > 0) { + for (int i = 0; i < (int)sampledInds.size(); i++) { + if (sampledInds[i] != NULL) nb_sampled++; + } + } + return nb_sampled; +} +// --------------------------------------------------------------------------- +// catch individuals according to catching rate +// --------------------------------------------------------------------------- +Individual* Population::catchIndividual( // Translocate a set of individuals with specified characteristics + double catching_rate, + int j +){ + Individual* catched; + int id = inds[j]->getId(); + // If individual is part of the sampledInds vector: + if (std::find(sampledInds.begin(), sampledInds.end(), inds[j]) != std::end(sampledInds)){ + // try to catch individual + if(catching_rate > 1) Rcpp::Rcout << "Catching rate: " << catching_rate << std::endl; + if (pRandom->Bernoulli(catching_rate)){ + indStats indstat = inds[j]->getStats(); + catched = inds[j]; + // remove individual from source patch + inds[j] = 0; + nInds[indstat.stage][indstat.sex]--; + cleanSampledInds(catched); // clean vector of sampled individuals after the event + return catched; + }else { + cleanSampledInds(inds[j]); // clean vector of sampled individuals after the event + return NULL; + } + } else { + return NULL; + } +} + +// --------------------------------------------------------------------------- +// // Add a specified individual to the new or current population of a patch +// void Population::recruitTranslocated(Individual* catched_individual) { +// Rcpp::Rcout << "Recruit translocated individual" << endl; +// Rcpp::Rcout << "Individual ID: " << catched_individual->getId() << endl; +// Rcpp::Rcout << "Size of population" << getNInds() << endl; +// inds.push_back(catched_individual); +// Rcpp::Rcout << "Size of population after translocation" << getNInds() << endl; +// indStats ind = catched_individual->getStats(); +// nInds[ind.stage][ind.sex]++; +// } + +// --------------------------------------------------------------------------- +bool Population::getSizeSampledInds( +){ + bool size = false; + if (sampledInds.size() > 0) size = true; + return size; +}; + //--------------------------------------------------------------------------- diff --git a/Population.h b/Population.h index fd1fa66..fef1a54 100644 --- a/Population.h +++ b/Population.h @@ -1,25 +1,25 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - + + /*------------------------------------------------------------------------------ RangeShifter v2.0 Population @@ -34,9 +34,9 @@ The matrix Population(s) hold(s) Individuals which are currently in the process of transfer through the matrix. For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. +Bocedi G., Palmer S.C.F., Pe?er G., Heikkinen R.K., Matsinos Y.G., Watts K. and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. +eco-evolutionary dynamics and species? responses to environmental changes. Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 Authors: Greta Bocedi & Steve Palmer, University of Aberdeen @@ -215,6 +215,41 @@ class Population { ); void clean(void); // Remove zero pointers to dead or dispersed individuals + std::vector getIndsWithCharacteristics( // Return a set of individuals with specified characteristics + int, // min age + int, // max age + int, // stage + int //sex + ); + void cleanSampledInds( + Individual* // individual to remove from sampled individuals vector + ); // clean sampled individuals vector + + int sampleIndividuals( // Select a set of individuals with specified characteristics; return the number of individuals with those characteristics + // void sampleIndividuals( // Select a set of individuals with specified characteristics; return the number of individuals with those characteristics + int, //number of individuals to sample + int, // min age (0 if not set) + int, // max age (max age if not set) + int, // stage + int //sex + ); + + Individual* catchIndividual( + double, // catching rate + int + ); + + // void completeTranslocation( + // std::vector // catched individuals + // ); + + // void recruitTranslocated( + // Individual* + // ); + + bool getSizeSampledInds( + ); + private: short nStages; short nSexes; @@ -226,6 +261,8 @@ class Population { std::vector juvs; // ... juveniles until reproduction of ALL species // has been completed + std::vector sampledInds; // individuals with specified characteristics + }; //--------------------------------------------------------------------------- From 16e207884fbf7db0ed8a01c505b25c027b6ad23f Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Mon, 13 May 2024 08:06:40 +0200 Subject: [PATCH 118/332] manually updating RScore --- Management.cpp | 239 +++++++++++++++++++++++++++++++++++++++++++++++++ Management.h | 143 +++++++++++++++++++++++++++++ 2 files changed, 382 insertions(+) create mode 100644 Management.cpp create mode 100644 Management.h diff --git a/Management.cpp b/Management.cpp new file mode 100644 index 0000000..c0a273b --- /dev/null +++ b/Management.cpp @@ -0,0 +1,239 @@ +/*---------------------------------------------------------------------------- + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * + * This file is part of RangeShifter. + * + * RangeShifter 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 3 of the License, or + * (at your option) any later version. + * + * RangeShifter is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RangeShifter. If not, see . + * + --------------------------------------------------------------------------*/ + + +//--------------------------------------------------------------------------- + +#include "Management.h" + +//--------------------------------------------------------------------------- +/* + * Initialize management class + */ + +Management::Management(void) { + translocation = false; + catching_rate = 1.0; // Catching rate + non_dispersed = false; // do not consider non-dispersed individuals + std::vector translocation_years; // Number of years of translocation + std::map< int, std::vector > source; // Source patch or cell: should be a vector of arrays + std::map< int, std::vector > target; // Target patch or cell + std::map< int, std::vector > nb; // number of ttanslocated individuals + std::map< int, std::vector > min_age; // Minimum age of translocated individuals + std::map< int, std::vector > max_age; // Maximum age of translocated individuals + std::map< int, std::vector > stage; // Stage of translocated individuals + std::map< int, std::vector > sex; // Sex of translocated individuals + +} + +Management::~Management(void) { + translocation_years.clear(); + source.clear(); + target.clear(); + nb.clear(); + min_age.clear(); + max_age.clear(); + stage.clear(); +} + +managementParams Management::getManagementParams(void) { + managementParams m; + m.translocation = translocation; + return m; +} + +void Management::setManagementParams(const managementParams m){ + translocation = m.translocation; +}; + +translocationParams Management::getTranslocationParams(void) { + translocationParams t; + t.catching_rate = catching_rate; + t.translocation_years = translocation_years; + t.source = source; + t.target = target; + t.nb = nb; + t.min_age = min_age; + t.max_age = max_age; + t.stage = stage; + t.sex = sex; + return t; +} + +// not sure if this is a good way, so won't use it for now +void Management::setTranslocationParams(const translocationParams t){ + catching_rate = t.catching_rate; + translocation_years = t.translocation_years; + source = t.source; + target = t.target; + nb = t.nb; + min_age = t.min_age; + max_age = t.max_age; + stage = t.stage; + sex = t.sex; + +}; + +void Management::translocate(int yr + , Landscape* pLandscape + , Species* pSpecies + ){ + Rcpp::Rcout << "Start translocation events in year " << yr << endl; + landParams ppLand = pLandscape->getLandParams(); + auto it = nb.find(yr); // the number of translocation events is determined by the number of elements of the maps at year yr + auto nb_it = nb.find(yr); + auto source_it = source.find(yr); + auto target_it = target.find(yr); + auto min_age_it = min_age.find(yr); + auto max_age_it = max_age.find(yr); + auto stage_it = stage.find(yr); + auto sex_it = sex.find(yr); + // iterate over the number of events + for (int e = 0; e < it->second.size(); e++) { + Rcpp::Rcout << "Translocation event " << e << " in year " << yr << endl; + // find the source patch + Patch* s_patch; + Population* s_pPop; + if(ppLand.patchModel){ + if(pLandscape->existsPatch(source_it->second[e].x)){ + Rcpp::Rcout << "Source patch exist." << endl; + s_patch = pLandscape->findPatch(source_it->second[e].x); + if (s_patch != 0) { + // test if population in patch is not zero + s_pPop = (Population*)s_patch->getPopn((intptr)pSpecies); // returns the population of the species in that cell + if (s_pPop != 0 && s_pPop->getNInds() > 0){ + } else { + Rcpp::Rcout << "Population does not exist in source patch or is 0! skipping translocation event." << endl; + return; + } + } else { + Rcpp::Rcout << "Source patch was found but NULL! skipping translocation event." << endl; // not sure if this ever happens + return; + } + // + } else{ + Rcpp::Rcout << "Source patch was not found in landscape! skipping translocation event." << endl; + return; + } + } else{ + Cell* pCell; + pCell = pLandscape->findCell(source_it->second[e].x, source_it->second[e].y); + if (pCell != 0) { + Rcpp::Rcout << "Source cell was found" << endl; + intptr s_ppatch = pCell->getPatch(); + if (s_ppatch != 0) { + s_patch = (Patch*)s_ppatch; + // test if population in patch is not zero + s_pPop = (Population*)s_patch->getPopn((intptr)pSpecies); // returns the population of the species in that cell + if (s_pPop != 0 && s_pPop->getNInds() > 0){ + } else { + Rcpp::Rcout << "Population does not exist in source cell or is 0! skipping translocation event." << endl; + return; + } + } else { + Rcpp::Rcout << "Source cell does not exist! skipping translocation event." << endl; + return; + } + } else { + Rcpp::Rcout << "Cell does not belong to landscape! skipping translocation event." << endl; + return; + } + } + // find the target patch and check for existence + Patch* t_patch; + Population* t_pPop; + if(ppLand.patchModel){ + if(pLandscape->existsPatch(target_it->second[e].x)){ + Rcpp::Rcout << "Target patch exist." << endl; + t_patch = pLandscape->findPatch(target_it->second[e].x); + } else{ + Rcpp::Rcout << "Target patch was not found in landscape! skipping translocation event." << endl; + return; + } + } else{ + Cell* pCell; + pCell = pLandscape->findCell(target_it->second[e].x, target_it->second[e].y); + if (pCell != 0) { + Rcpp::Rcout << "Target cell was found" << endl; + intptr t_ppatch = pCell->getPatch(); + if (t_ppatch != 0) { + t_patch = (Patch*)t_ppatch; + } else { + Rcpp::Rcout << "Target cell does not exist! skipping translocation event." << endl; + return; + } + } else { + Rcpp::Rcout << "Target cell does not belong to landscape! skipping translocation event." << endl; + return; + } + } + + // only if source and target cell/patch exist, we can translocate individuals: + // get individuals with the given characteristics in that population + int min_age = min_age_it->second[e]; + int max_age = max_age_it->second[e]; + int stage = stage_it->second[e]; + int sex = sex_it->second[e]; + int nb = nb_it->second[e]; + int nbSampledInds = 0; + // We made already sure by now that in s_pPop at least some individuals exist + nbSampledInds = s_pPop->sampleIndividuals(nb, min_age, max_age, stage, sex); // checking values was done when reading in the parameters + popStats s_stats = s_pPop->getStats(); + Individual* catched_individual; + int translocated = 0; + // loop over all indsividuals, extract sampled individuals, try to catch individual + translocate them to new patch + for (int j = 0; j < s_stats.nInds; j++) { + // if there are individuals to catch + if(s_pPop->getSizeSampledInds()){ + // if this individual is matching one of the sampled individuals + catched_individual = s_pPop->catchIndividual(catching_rate, j); // catch individual in the source patch + if (catched_individual !=NULL) { // translocated individual - has already been removed from natal population + // Check if a population of this species already exists in target patch t_patch + t_pPop = (Population*)t_patch->getPopn((intptr)pSpecies); + if (t_pPop == 0) { // translocated individual is the first in a previously uninhabited patch + Rcpp::Rcout << "Population does not exist in target patch. Creating new population." << endl; + // create a new population in the corresponding sub-community + SubCommunity* pSubComm = (SubCommunity*)t_patch->getSubComm(); + t_pPop = pSubComm->newPopn(pLandscape, pSpecies, t_patch, 0); + } + catched_individual->setStatus(10); // make sure individual is not dispersing after the translocation + t_pPop->recruit(catched_individual); // recruit individual to target population TODO: maybe use a specified function which also updates pCurrCell + pPrevCell to a random cell in target patch? + translocated ++; + // NOTE: + // the variables pCurrCell and pPrevCell are not updated! These are important for the dispersal process! + // currently, translocated individuals are not considered as potential emigrants, thus there is no problem in changing that + // however, if we want to consider dispersal events after translocation, we need to adapt that; but that would also mean, that we might loose the information + // about the natal patch of an individual? + simParams sim = paramsSim->getSim(); + if (sim.outConnect) { // increment connectivity totals + int newpatch = t_patch->getSeqNum(); + int prevpatch = s_patch->getSeqNum(); + pLandscape->incrConnectMatrix(prevpatch, newpatch); + } + + } + } + } + Rcpp::Rcout << "Successfully translocated " << translocated << " out of " << nb_it->second[e] << " individuals in translocation event " << e <<"." << endl; + // remove pointers to sampled individuals + s_pPop->clean(); + } +}; \ No newline at end of file diff --git a/Management.h b/Management.h new file mode 100644 index 0000000..5148ade --- /dev/null +++ b/Management.h @@ -0,0 +1,143 @@ +/*---------------------------------------------------------------------------- + * + * Copyright (C) 2024 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell, Jette Reeg + * + * This file is part of RangeShifter. + * + * RangeShifter 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 3 of the License, or + * (at your option) any later version. + * + * RangeShifter is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RangeShifter. If not, see . + * + --------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------------ + + RangeShifter v2.0 Parameters + + Implements the following classes: + + paramManagement - Management parameters + paramTranslocation - Translocation parameters + + + Last updated: 12 March 2024 by Jette Reeg + + ------------------------------------------------------------------------------*/ + + +#ifndef ManagementH +#define ManagementH + +//#if LINUX_CLUSTER +//#include +//#else +#include +//#endif +#include +#include +//#include +#include +#include +#include +#include +using namespace std; + +#include // for Rcpp::Rcout +#include "Parameters.h" +#include "Species.h" +#include "Cell.h" +#include "Landscape.h" + +#include "SubCommunity.h" +#include "Population.h" + + +#if RS_RCPP +typedef intptr_t intptr; +#else +#if RSWIN64 +typedef unsigned long long intptr; +#else +typedef unsigned int intptr; +#endif +#endif + + + +//--------------------------------------------------------------------------- + +/* + * Management settings + */ + +// Structure for management parameters +struct managementParams { + bool translocation; // Translocation +}; + +// Structure for translocation parameters +struct translocationParams { + double catching_rate; // Catching rate + std::vector translocation_years; // Number of years of translocation -> will be increased at the beginning of a simulation + std::map< int, std::vector > source; // Source patch or cell: should be a vector of arrays + std::map< int, std::vector > target; // Target patch or cell + std::map< int, std::vector > nb; // number of ttanslocated individuals + std::map< int, std::vector > min_age; // Minimum age of translocated individuals + std::map< int, std::vector > max_age; // Maximum age of translocated individuals + std::map< int, std::vector > stage; // Stage of translocated individuals + std::map< int, std::vector > sex; // Sex of translocated individuals +}; + + +//--------------------------------------------------------------------------- + +class Management{ +public: + Management(void); + ~Management(void); + void setManagementParams( // function to set management parameters + const managementParams // structure holding general management parameters + ); + managementParams getManagementParams(void); // get management parameters + void setTranslocationParams( // function to set translocation parameters + const translocationParams // structure holding translocation parameters + ); + translocationParams getTranslocationParams(void); + void translocate( // Translocation + int , // year of translocation + Landscape* , // pointer to the landscape + // Community*, // pointer to the community + Species* // pointer to the species + ); + + // + bool translocation; // Translocation + double catching_rate; // Catching rate + bool non_dispersed; // whether non-dispersed individuals should be translocated + std::vector translocation_years; // Number of years of translocation -> should be a dynamic vector + std::map< int, std::vector > source; // Source patch or cell: should be a vector of arrays + std::map< int, std::vector > target; // Target patch or cell + std::map< int, std::vector > nb; // number of ttanslocated individuals + std::map< int, std::vector > min_age; // Minimum age of translocated individuals + std::map< int, std::vector > max_age; // Maximum age of translocated individuals + std::map< int, std::vector > stage; // Stage of translocated individuals + std::map< int, std::vector > sex; // Sex of translocated individuals + +}; + +//--------------------------------------------------------------------------- + +extern paramSim *paramsSim; + +//--------------------------------------------------------------------------- +#endif From 62ae3e1dcbd5da0b8f88b96c8f7f190ef152325d Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 14 May 2024 13:45:55 +0100 Subject: [PATCH 119/332] replace poisson with binomial --- GeneticFitnessTrait.cpp | 3 +-- Individual.cpp | 4 ++-- QTLTrait.cpp | 6 ++---- RSrandom.cpp | 10 ++++++++++ RSrandom.h | 2 ++ SNPTrait.cpp | 6 ++---- 6 files changed, 19 insertions(+), 12 deletions(-) diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index 17e8630..b5e0cec 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -133,8 +133,7 @@ void GeneticFitnessTrait::mutate() for (int p = 0; p < ploidy; p++) { // Determine nb of mutations - unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); - if (NbMut > positionsSize) NbMut = positionsSize; + unsigned int NbMut = pRandom->Binomial(positionsSize, mutationRate); if (NbMut > 0) { vector mutationPositions; diff --git a/Individual.cpp b/Individual.cpp index 603cba9..4be6cc3 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -135,7 +135,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi // Draw recombination events for maternal genome if (pSpecies->getRecombinationRate() > 0.0) - events = pRandom->Poisson(genomeSize * pSpecies->getRecombinationRate()); + events = pRandom->Binomial(genomeSize, pSpecies->getRecombinationRate()); // if poisson exceeds genomeSize, bound to genomeSize int nbrCrossOvers = events + maternalRecomPositions.size(); if (nbrCrossOvers > genomeSize) { @@ -148,7 +148,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi // Draw recombination events for paternal genome if (pSpecies->getRecombinationRate() > 0.0) - events = pRandom->Poisson(genomeSize * pSpecies->getRecombinationRate()); + events = pRandom->Binomial(genomeSize, pSpecies->getRecombinationRate()); nbrCrossOvers = events + paternalRecomPositions.size(); if (nbrCrossOvers > genomeSize) { nbrCrossOvers = genomeSize; diff --git a/QTLTrait.cpp b/QTLTrait.cpp index 6d6c2e5..0c116f6 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -130,8 +130,7 @@ void QTLTrait::mutateUniform() for (int p = 0; p < ploidy; p++) { - unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); - if (NbMut > positionsSize) NbMut = positionsSize; + unsigned int NbMut = pRandom->Binomial(positionsSize, mutationRate); if (NbMut > 0) { vector mutationPositions; @@ -173,8 +172,7 @@ void QTLTrait::mutateNormal() for (int p = 0; p < ploidy; p++) { - unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); - if (NbMut > positionsSize) NbMut = positionsSize; + unsigned int NbMut = pRandom->Binomial(positionsSize, mutationRate); if (NbMut > 0) { vector mutationPositions; diff --git a/RSrandom.cpp b/RSrandom.cpp index 16ae964..14758cc 100644 --- a/RSrandom.cpp +++ b/RSrandom.cpp @@ -103,6 +103,11 @@ int RSrandom::Bernoulli(double p) { return Random() < p; } +int RSrandom::Binomial(const int& n, const double& p) { + binomial_distribution binom(n, p); + return binom(*gen); +} + double RSrandom::Normal(double mean, double sd) { return mean + sd * pNormal->operator()(*gen); } @@ -228,6 +233,11 @@ float RSrandom::FRandom(float min, float max) { return Random() < p; } + int RSrandom::Binomial(const int& n, const double& p) { + binomial_distribution binom(n, p); + return binom(*gen); + } + double RSrandom::Normal(double mean, double sd) { return mean + sd * pNormal->operator()(*gen); } diff --git a/RSrandom.h b/RSrandom.h index 6349520..0991483 100644 --- a/RSrandom.h +++ b/RSrandom.h @@ -68,6 +68,7 @@ class RSrandom int IRandom(int, int); float FRandom(float, float); int Bernoulli(double); + int Binomial(const int& n, const double& p); double Normal(double, double); double Gamma(double, double); double NegExp(double); @@ -110,6 +111,7 @@ class RSrandom { int IRandom(int, int); float FRandom(float, float); int Bernoulli(double); + int Binomial(const int& n, const double& p); double Normal(double, double); double Gamma(double, double); double NegExp(double); diff --git a/SNPTrait.cpp b/SNPTrait.cpp index 6ff9d03..18b8d1a 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -98,8 +98,7 @@ void SNPTrait::mutate_KAM() for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { - unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); - if (NbMut > positionsSize) NbMut = positionsSize; + unsigned int NbMut = pRandom->Binomial(positionsSize, mutationRate); if (NbMut > 0) { vector mutationPositions; sample(genePositions.begin(), genePositions.end(), std::back_inserter(mutationPositions), @@ -146,8 +145,7 @@ void SNPTrait::mutate_SSM() for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { - unsigned int NbMut = pRandom->Poisson(positionsSize * mutationRate); - if (NbMut > positionsSize) NbMut = positionsSize; + unsigned int NbMut = pRandom->Binomial(positionsSize, mutationRate); if (NbMut > 0) { vector mutationPositions; sample(genePositions.begin(), genePositions.end(), std::back_inserter(mutationPositions), From 42156c527be74e37a4904c2b3b2508275ae198cf Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 14 May 2024 16:22:49 +0100 Subject: [PATCH 120/332] bound QTL phenotypes --- GeneticFitnessTrait.cpp | 8 ++---- QTLTrait.cpp | 59 ++++++++++++++++++++++++++++++++++++----- QTLTrait.h | 1 + SpeciesTrait.h | 1 + 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index b5e0cec..1a28664 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -145,12 +145,8 @@ void GeneticFitnessTrait::mutate() auto it = genes.find(m); if (it == genes.end()) throw runtime_error("Locus sampled for mutation doesn't exist."); - do { - newSelectionCoef = drawSelectionCoef(); - } while (!pSpeciesTrait->isValidTraitVal(newSelectionCoef)); - do { - newDominanceCoef = drawDominance(newSelectionCoef); - } while (newDominanceCoef < 0.0); + newSelectionCoef = drawSelectionCoef(); + newDominanceCoef = drawDominance(newSelectionCoef); it->second[p] = make_shared(newSelectionCoef, newDominanceCoef); } } diff --git a/QTLTrait.cpp b/QTLTrait.cpp index 0c116f6..e5589c2 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -142,9 +142,7 @@ void QTLTrait::mutateUniform() if (it == genes.end()) throw runtime_error("Locus sampled for mutation doesn't exist."); float currentAlleleVal = it->second[p].get()->getAlleleValue();//current - do { - newAlleleVal = pRandom->FRandom(minD, maxD) + currentAlleleVal; - } while (!pSpeciesTrait->isValidTraitVal(newAlleleVal)); + newAlleleVal = pRandom->FRandom(minD, maxD) + currentAlleleVal; it->second[p] = make_shared(newAlleleVal, QTLDominanceFactor); } } @@ -184,9 +182,7 @@ void QTLTrait::mutateNormal() if (it == genes.end()) throw runtime_error("Locus sampled for mutation doesn't exist."); float currentAlleleVal = it->second[p].get()->getAlleleValue(); //current - do { - newAlleleVal = pRandom->Normal(mean, sd) + currentAlleleVal; - } while (!pSpeciesTrait->isValidTraitVal(newAlleleVal)); + newAlleleVal = pRandom->Normal(mean, sd) + currentAlleleVal; it->second[p] = make_shared(newAlleleVal, QTLDominanceFactor); } } @@ -342,6 +338,7 @@ float QTLTrait::expressAdditive() { for (const std::shared_ptr m : allelePair) phenotype += m->getAlleleValue(); } + trimQTLPhenotype(phenotype); return phenotype; } @@ -357,9 +354,59 @@ float QTLTrait::expressAverage() { phenotype += m->getAlleleValue(); } phenotype /= positionsSize * ploidy; + trimQTLPhenotype(phenotype); return phenotype; } +void QTLTrait::trimQTLPhenotype(float& val) { + const float minPositiveVal = 1e-06; + switch (pSpeciesTrait->getTraitType()) + { + // Values bound between 0 and 1 + case E_D0_F: case E_D0_M: + case S_S0_F: case S_S0_M: + case KERNEL_PROBABILITY_F: case KERNEL_PROBABILITY_M: + case CRW_STEPCORRELATION: + { + if (val < 0.0) val = 0; + else if (val > 1.0) val = 1.0; + break; + } + // Positive values + case KERNEL_MEANDIST_1_F: case KERNEL_MEANDIST_1_M: + case KERNEL_MEANDIST_2_F: case KERNEL_MEANDIST_2_M: + case CRW_STEPLENGTH: + { + if (val < 0.0) val = 0; + break; + } + // Strictly positive values + case E_ALPHA_F: case E_ALPHA_M: + case S_ALPHA_F: case S_ALPHA_M: + case SMS_ALPHADB: + { + if (val <= 0.0) val = minPositiveVal; + break; + } + // Minimum 1 + case SMS_DP: + case SMS_GB: + { + if (val <= 1.0) val = 1.0; + break; + } + // Not bound + case E_BETA_F: case E_BETA_M: + case S_BETA_F: case S_BETA_M: + case SMS_BETADB: + { + break; + } + default: + break; + } +} + // ---------------------------------------------------------------------------------------- // Check if specific locus is heterozygote // ---------------------------------------------------------------------------------------- diff --git a/QTLTrait.h b/QTLTrait.h index 3248c7e..d12561e 100644 --- a/QTLTrait.h +++ b/QTLTrait.h @@ -75,6 +75,7 @@ class QTLTrait : public TTrait { //// Mutation void mutateUniform(); void mutateNormal(); + void trimQTLPhenotype(float& phenotype); //// Gene expression float expressAverage(); float expressAdditive(); diff --git a/SpeciesTrait.h b/SpeciesTrait.h index f5809bf..ef68e9a 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -32,6 +32,7 @@ class SpeciesTrait { ); bool isValidTraitVal(const float& val) const; + TraitType getTraitType() const { return traitType; } // Getters sex_t getSex() const { return sex; } From a4157d2de6ee476e0b8f938112eb360b7de9c043 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 17 May 2024 17:01:56 +0100 Subject: [PATCH 121/332] enable scaled dominance distribution --- GeneticFitnessTrait.cpp | 27 +++++++++++++++++++++++++-- GeneticFitnessTrait.h | 3 ++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index 1a28664..e7715db 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -89,7 +89,28 @@ GeneticFitnessTrait::GeneticFitnessTrait(SpeciesTrait* P) } case SCALED: { - break; // no parameter + if (dominanceParameters.count(MEAN) != 1) + throw logic_error("Error:: genetic load dominance distribution set to scaled, so parameters must contain mean dominance value (e.g. mean= ) \n"); + + // Calculate mean selection coeff s_d for calculation of k + switch (mutationDistribution) + { + case UNIFORM: + scaledDomMeanSelCoeff = (mutationParameters.find(MIN)->second + mutationParameters.find(MAX)->second) / 2; + break; + case NORMAL: + scaledDomMeanSelCoeff = mutationParameters.find(MEAN)->second; + break; + case GAMMA: + scaledDomMeanSelCoeff = mutationParameters.find(SHAPE)->second * mutationParameters.find(SCALE)->second; + break; + case NEGEXP: + scaledDomMeanSelCoeff = 1 / mutationParameters.find(MEAN)->second; + break; + default: + break; + } + break; } default: { @@ -195,7 +216,9 @@ float GeneticFitnessTrait::drawDominance(float selCoef) { case SCALED: { const float min = 0; - const float max = static_cast(exp((-log(2 * 0.36) / 0.05) * selCoef)); + const float h_d = dominanceParameters.find(MEAN)->second; + const float k = -log(2 * h_d) / scaledDomMeanSelCoeff; + const float max = static_cast(exp(-k * selCoef)); h = static_cast(pRandom->FRandom(min, max)); break; } diff --git a/GeneticFitnessTrait.h b/GeneticFitnessTrait.h index aaa0328..2563ea4 100644 --- a/GeneticFitnessTrait.h +++ b/GeneticFitnessTrait.h @@ -41,7 +41,7 @@ class GeneticFitnessTrait : public TTrait { map>>& getGenes() { return genes; } // returning reference, reciever must be const - virtual void mutate() override; + virtual void mutate() override; virtual float express(); virtual void inheritGenes(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; @@ -61,6 +61,7 @@ class GeneticFitnessTrait : public TTrait { void initialise(); // Mutation + float scaledDomMeanSelCoeff; // s_d, only for scaled dominance distribution float drawDominance(float); float drawSelectionCoef(); From 54758db4cbc1526fe312634e99b8303d4c9e5fba Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 22 May 2024 13:18:34 +0100 Subject: [PATCH 122/332] rename QTL into dispersal trait --- CMakeLists.txt | 4 +- QTLTrait.cpp => DispersalTrait.cpp | 100 ++++++++++++++--------------- QTLTrait.h => DispersalTrait.h | 32 +++++---- Individual.cpp | 8 +-- Individual.h | 2 +- Landscape.cpp | 2 +- Landscape.h | 2 +- SpeciesTrait.cpp | 2 +- TraitFactory.h | 4 +- 9 files changed, 77 insertions(+), 79 deletions(-) rename QTLTrait.cpp => DispersalTrait.cpp (74%) rename QTLTrait.h => DispersalTrait.h (76%) diff --git a/CMakeLists.txt b/CMakeLists.txt index b7d6cd8..e98ad1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,9 +7,9 @@ if (NOT batchmode) # that is, RScore as a standalone # specify the C++ standard set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) - add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) + add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) else() # that is, RScore compiled as library within RangeShifter_batch - add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) + add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) endif() # pass config definitions to compiler diff --git a/QTLTrait.cpp b/DispersalTrait.cpp similarity index 74% rename from QTLTrait.cpp rename to DispersalTrait.cpp index e5589c2..81931ad 100644 --- a/QTLTrait.cpp +++ b/DispersalTrait.cpp @@ -1,4 +1,4 @@ -#include "QTLTrait.h" +#include "DispersalTrait.h" // ---------------------------------------------------------------------------------------- // Initialisation constructor @@ -6,15 +6,15 @@ // Sets up initial values, and immutable attributes (distributions and parameters) // that are defined at the species-level // ---------------------------------------------------------------------------------------- -QTLTrait::QTLTrait(SpeciesTrait* P) +DispersalTrait::DispersalTrait(SpeciesTrait* P) { pSpeciesTrait = P; ExpressionType expressionType = pSpeciesTrait->getExpressionType(); if (!pSpeciesTrait->isInherited()) // there is a trait for individual variation but this isn't inherited variation it's sampled from initial distribution - _inherit_func_ptr = &QTLTrait::reInitialiseGenes; + _inherit_func_ptr = &DispersalTrait::reInitialiseGenes; else { - _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &QTLTrait::inheritHaploid : &QTLTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance + _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &DispersalTrait::inheritHaploid : &DispersalTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); map mutationParameters = pSpeciesTrait->getMutationParameters(); @@ -24,24 +24,24 @@ QTLTrait::QTLTrait(SpeciesTrait* P) case UNIFORM: { if (mutationParameters.count(MAX) != 1) - throw logic_error("Error:: mutation uniform qtl distribution parameter must contain max value (e.g. max= ) \n"); + throw logic_error("Error: mutation uniform distribution parameter must contain max value (e.g. max= ) \n"); if (mutationParameters.count(MIN) != 1) - throw logic_error("Error:: mutation uniform qtl distribution parameter must contain min value (e.g. min= ) \n"); - _mutate_func_ptr = &QTLTrait::mutateUniform; + throw logic_error("Error: mutation uniform distribution parameter must contain min value (e.g. min= ) \n"); + _mutate_func_ptr = &DispersalTrait::mutateUniform; break; } case NORMAL: { if (mutationParameters.count(MEAN) != 1) - throw logic_error("Error:: qtl mutation distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); + throw logic_error("Error: mutation distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); if (mutationParameters.count(SD) != 1) - throw logic_error("Error::qtl mutation distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); - _mutate_func_ptr = &QTLTrait::mutateNormal; + throw logic_error("Error: mutation distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); + _mutate_func_ptr = &DispersalTrait::mutateNormal; break; } default: { - throw logic_error("Error:: wrong parameter value for qtl mutation model, must be uniform/normal \n"); //unless want to add gamma or negative exp + throw logic_error("Error: wrong parameter value for mutation model, must be uniform/normal \n"); //unless want to add gamma or negative exp break; } } @@ -54,9 +54,9 @@ QTLTrait::QTLTrait(SpeciesTrait* P) case UNIFORM: { if (initialParameters.count(MAX) != 1) - throw logic_error("Error:: initial uniform qtl distribution parameter must contain max value (e.g. max= ) \n"); + throw logic_error("Error: initial uniform distribution parameter must contain max value (e.g. max= ) \n"); if (initialParameters.count(MIN) != 1) - throw logic_error("Error:: initial uniform qtl distribution parameter must contain min value (e.g. min= ) \n"); + throw logic_error("Error: initial uniform distribution parameter must contain min value (e.g. min= ) \n"); float maxD = initialParameters.find(MAX)->second; float minD = initialParameters.find(MIN)->second; initialiseUniform(minD, maxD); @@ -65,9 +65,9 @@ QTLTrait::QTLTrait(SpeciesTrait* P) case NORMAL: { if (initialParameters.count(MEAN) != 1) - throw logic_error("Error:: initial normal qtl distribution parameter must contain mean value (e.g. mean= ) \n"); + throw logic_error("Error: initial normal distribution parameter must contain mean value (e.g. mean= ) \n"); if (initialParameters.count(SD) != 1) - throw logic_error("Error:: initial normal qtl distribution parameter must contain sdev value (e.g. sdev= ) \n"); + throw logic_error("Error: initial normal distribution parameter must contain sdev value (e.g. sdev= ) \n"); float mean = initialParameters.find(MEAN)->second; float sd = initialParameters.find(SD)->second; initialiseNormal(mean, sd); @@ -75,7 +75,7 @@ QTLTrait::QTLTrait(SpeciesTrait* P) } default: { - throw logic_error("wrong parameter value for parameter \"initialisation of qtl\", must be uniform/normal \n"); + throw logic_error("wrong parameter value for parameter \"initialisation of dispersal traits\", must be uniform/normal \n"); break; } } @@ -84,17 +84,17 @@ QTLTrait::QTLTrait(SpeciesTrait* P) switch (expressionType) { case AVERAGE: { - _express_func_ptr = &QTLTrait::expressAverage; + _express_func_ptr = &DispersalTrait::expressAverage; break; } case ADDITIVE: { - _express_func_ptr = &QTLTrait::expressAdditive; + _express_func_ptr = &DispersalTrait::expressAdditive; break; } default: { - throw logic_error("wrong parameter value for parameter \"expression of qtl\", must be average/additive \n"); + throw logic_error("wrong parameter value for parameter \"expression of dispersal trait\", must be average/additive \n"); break; } } @@ -105,7 +105,7 @@ QTLTrait::QTLTrait(SpeciesTrait* P) // Copies immutable features from a parent trait // Only called via clone() // ---------------------------------------------------------------------------------------- -QTLTrait::QTLTrait(const QTLTrait& T) : pSpeciesTrait(T.pSpeciesTrait), _mutate_func_ptr(T._mutate_func_ptr), _inherit_func_ptr(T._inherit_func_ptr), _express_func_ptr(T._express_func_ptr) +DispersalTrait::DispersalTrait(const DispersalTrait& T) : pSpeciesTrait(T.pSpeciesTrait), _mutate_func_ptr(T._mutate_func_ptr), _inherit_func_ptr(T._inherit_func_ptr), _express_func_ptr(T._express_func_ptr) {} // ---------------------------------------------------------------------------------------- @@ -114,7 +114,7 @@ QTLTrait::QTLTrait(const QTLTrait& T) : pSpeciesTrait(T.pSpeciesTrait), _mutate_ // Mutations drawn only for existing positions, // that is no new genes are created during simulation // ---------------------------------------------------------------------------------------- -void QTLTrait::mutateUniform() +void DispersalTrait::mutateUniform() { const int positionsSize = pSpeciesTrait->getPositionsSize(); const auto& genePositions = pSpeciesTrait->getGenePositions(); @@ -143,7 +143,7 @@ void QTLTrait::mutateUniform() throw runtime_error("Locus sampled for mutation doesn't exist."); float currentAlleleVal = it->second[p].get()->getAlleleValue();//current newAlleleVal = pRandom->FRandom(minD, maxD) + currentAlleleVal; - it->second[p] = make_shared(newAlleleVal, QTLDominanceFactor); + it->second[p] = make_shared(newAlleleVal, dispDominanceFactor); } } } @@ -154,7 +154,7 @@ void QTLTrait::mutateUniform() // Mutations drawn only for existing positions, // that is no new genes are created during simulation // ---------------------------------------------------------------------------------------- -void QTLTrait::mutateNormal() +void DispersalTrait::mutateNormal() { const int positionsSize = pSpeciesTrait->getPositionsSize(); const auto& genePositions = pSpeciesTrait->getGenePositions(); @@ -183,7 +183,7 @@ void QTLTrait::mutateNormal() throw runtime_error("Locus sampled for mutation doesn't exist."); float currentAlleleVal = it->second[p].get()->getAlleleValue(); //current newAlleleVal = pRandom->Normal(mean, sd) + currentAlleleVal; - it->second[p] = make_shared(newAlleleVal, QTLDominanceFactor); + it->second[p] = make_shared(newAlleleVal, dispDominanceFactor); } } } @@ -192,9 +192,9 @@ void QTLTrait::mutateNormal() // ---------------------------------------------------------------------------------------- // Wrapper to inheritance function // ---------------------------------------------------------------------------------------- -void QTLTrait::inheritGenes(const bool& fromMother, TTrait* parentTrait, set const& recomPositions, int startingChromosome) +void DispersalTrait::inheritGenes(const bool& fromMother, TTrait* parentTrait, set const& recomPositions, int startingChromosome) { - auto parentCast = dynamic_cast(parentTrait); // must convert TTrait to QTLTrait + auto parentCast = dynamic_cast(parentTrait); // must convert TTrait to DispersalTrait const auto& parent_seq = parentCast->getGenes(); (this->*_inherit_func_ptr)(fromMother, parent_seq, recomPositions, startingChromosome); } @@ -205,7 +205,7 @@ void QTLTrait::inheritGenes(const bool& fromMother, TTrait* parentTrait, set>> const& parentGenes, set const& recomPositions, int parentChromosome) { +void DispersalTrait::inheritDiploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { auto it = recomPositions.lower_bound(parentGenes.begin()->first); int nextBreakpoint = *it; @@ -246,7 +246,7 @@ void QTLTrait::inheritDiploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) +void DispersalTrait::inheritHaploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { genes = parentGenes; } @@ -257,7 +257,7 @@ void QTLTrait::inheritHaploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) +void DispersalTrait::reInitialiseGenes(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); map initialParameters = pSpeciesTrait->getInitialParameters(); @@ -266,9 +266,9 @@ void QTLTrait::reInitialiseGenes(const bool& fromMother, mapsecond; float minD = initialParameters.find(MIN)->second; initialiseUniform(minD, maxD); @@ -277,9 +277,9 @@ void QTLTrait::reInitialiseGenes(const bool& fromMother, mapsecond; float sd = initialParameters.find(SD)->second; initialiseNormal(mean, sd); @@ -287,16 +287,16 @@ void QTLTrait::reInitialiseGenes(const bool& fromMother, map genePositions = pSpeciesTrait->getGenePositions(); short ploidy = pSpeciesTrait->getPloidy(); @@ -305,13 +305,13 @@ void QTLTrait::initialiseNormal(float mean, float sd) { vector> newAllelePair; for (int i = 0; i < ploidy; i++) { float alleleVal = pRandom->Normal(mean, sd); - newAllelePair.emplace_back(make_shared(alleleVal, QTLDominanceFactor)); + newAllelePair.emplace_back(make_shared(alleleVal, dispDominanceFactor)); } genes.insert(make_pair(position, newAllelePair)); } } -void QTLTrait::initialiseUniform(float min, float max) { +void DispersalTrait::initialiseUniform(float min, float max) { const set genePositions = pSpeciesTrait->getGenePositions(); short ploidy = pSpeciesTrait->getPloidy(); @@ -320,16 +320,16 @@ void QTLTrait::initialiseUniform(float min, float max) { vector> newAllelePair; for (int i = 0; i < ploidy; i++) { float alleleVal = pRandom->FRandom(min, max); - newAllelePair.emplace_back(make_shared(alleleVal, QTLDominanceFactor)); + newAllelePair.emplace_back(make_shared(alleleVal, dispDominanceFactor)); } genes.insert(make_pair(position, newAllelePair)); } } // ---------------------------------------------------------------------------------------- -// QTL gene expression options +// Dispersal gene expression options // ---------------------------------------------------------------------------------------- -float QTLTrait::expressAdditive() { +float DispersalTrait::expressAdditive() { float phenotype = 0.0; @@ -338,11 +338,11 @@ float QTLTrait::expressAdditive() { for (const std::shared_ptr m : allelePair) phenotype += m->getAlleleValue(); } - trimQTLPhenotype(phenotype); + trimPhenotype(phenotype); return phenotype; } -float QTLTrait::expressAverage() { +float DispersalTrait::expressAverage() { int positionsSize = pSpeciesTrait->getPositionsSize(); short ploidy = pSpeciesTrait->getPloidy(); @@ -354,11 +354,11 @@ float QTLTrait::expressAverage() { phenotype += m->getAlleleValue(); } phenotype /= positionsSize * ploidy; - trimQTLPhenotype(phenotype); + trimPhenotype(phenotype); return phenotype; } -void QTLTrait::trimQTLPhenotype(float& val) { +void DispersalTrait::trimPhenotype(float& val) { const float minPositiveVal = 1e-06; switch (pSpeciesTrait->getTraitType()) { @@ -410,11 +410,11 @@ void QTLTrait::trimQTLPhenotype(float& val) { // ---------------------------------------------------------------------------------------- // Check if specific locus is heterozygote // ---------------------------------------------------------------------------------------- -bool QTLTrait::isHeterozygoteAtLocus(int locus) const { +bool DispersalTrait::isHeterozygoteAtLocus(int locus) const { // assumes diploidy auto it = genes.find(locus); if (it == genes.end()) //not found - throw runtime_error("QTL gene queried for heterozygosity does not exist."); + throw runtime_error("Dispersal gene queried for heterozygosity does not exist."); else return(it->second[0].get()->getId() != it->second[1].get()->getId()); } @@ -422,7 +422,7 @@ bool QTLTrait::isHeterozygoteAtLocus(int locus) const { // ---------------------------------------------------------------------------------------- // Count heterozygote loci in genome // ---------------------------------------------------------------------------------------- -int QTLTrait::countHeterozygoteLoci() const { +int DispersalTrait::countHeterozygoteLoci() const { // assumes diploidy int count = 0; for (auto const& [locus, allelePair] : genes) { @@ -435,10 +435,10 @@ int QTLTrait::countHeterozygoteLoci() const { // ---------------------------------------------------------------------------------------- // Get allele value at locus // ---------------------------------------------------------------------------------------- -float QTLTrait::getAlleleValueAtLocus(short whichChromosome, int position) const { +float DispersalTrait::getAlleleValueAtLocus(short whichChromosome, int position) const { auto it = genes.find(position); if (it == genes.end()) - throw runtime_error("The QTL locus queried for its allele value does not exist."); + throw runtime_error("The Dispersal locus queried for its allele value does not exist."); return it->second[whichChromosome].get()->getAlleleValue(); } \ No newline at end of file diff --git a/QTLTrait.h b/DispersalTrait.h similarity index 76% rename from QTLTrait.h rename to DispersalTrait.h index d12561e..bf47613 100644 --- a/QTLTrait.h +++ b/DispersalTrait.h @@ -1,5 +1,5 @@ -#ifndef QTLTRAITH -#define QTLTRAITH +#ifndef DISPTRAITH +#define DISPTRAITH #include #include @@ -10,27 +10,25 @@ using namespace std; -// Quantitative-trait-loci (QTL) trait +// Dispersal trait // -// That is, all dispersal traits in RangeShifter, -// which individual phenotype is determined by small contributions -// from (potentially) many quantitative loci -class QTLTrait : public TTrait { +// That is, all evolvable that control emigration, transfer and settlement +class DispersalTrait : public TTrait { public: // Initialisation constructor, set initial values and immutable features - QTLTrait(SpeciesTrait* P); + DispersalTrait(SpeciesTrait* P); // Inheritance constructor, copies pointers to immutable features when cloning from parent - QTLTrait(const QTLTrait& T); + DispersalTrait(const DispersalTrait& T); // Make a shallow copy to pass to offspring trait // Return new pointer to new trait created by inheritance c'tor // This avoids copying shared attributes: distributions and parameters - virtual unique_ptr clone() const override { return std::make_unique(*this); } + virtual unique_ptr clone() const override { return std::make_unique(*this); } - virtual ~QTLTrait() { } + virtual ~DispersalTrait() { } // Getters int getNLoci() const override { return pSpeciesTrait->getPositionsSize(); } @@ -49,7 +47,7 @@ class QTLTrait : public TTrait { private: - const double QTLDominanceFactor = 1.0; // no dominance for QTL traits (yet?) + const double dispDominanceFactor = 1.0; // no dominance for Dispersal traits (yet?) // > map>> genes; @@ -63,9 +61,9 @@ class QTLTrait : public TTrait { //// Species-level trait attributes, invariant across individuals SpeciesTrait* pSpeciesTrait; //// Species-level trait functions - void (QTLTrait::* _mutate_func_ptr) (void); - void (QTLTrait::* _inherit_func_ptr) (const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); - float (QTLTrait::* _express_func_ptr) (void); + void (DispersalTrait::* _mutate_func_ptr) (void); + void (DispersalTrait::* _inherit_func_ptr) (const bool& fromMother, map>> const& parent, set const& recomPositions, int parentChromosome); + float (DispersalTrait::* _express_func_ptr) (void); // Possible values for immutable functions //// Inheritance @@ -75,10 +73,10 @@ class QTLTrait : public TTrait { //// Mutation void mutateUniform(); void mutateNormal(); - void trimQTLPhenotype(float& phenotype); + void trimPhenotype(float& phenotype); //// Gene expression float expressAverage(); float expressAdditive(); }; -#endif \ No newline at end of file +#endif // DISPTRAITH \ No newline at end of file diff --git a/Individual.cpp b/Individual.cpp index 4be6cc3..e7bc108 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -223,10 +223,10 @@ void Individual::setUpGenes(Species* pSpecies, int resol) { const auto spTrait = pSpecies->getSpTrait(traitType); this->spTraitTable.emplace(traitType, traitFactory.Create(traitType, spTrait)); } - setQTLPhenotypes(pSpecies, resol); + setDispersalPhenotypes(pSpecies, resol); } -void Individual::setQTLPhenotypes(Species* pSpecies, int resol) { +void Individual::setDispersalPhenotypes(Species* pSpecies, int resol) { const emigRules emig = pSpecies->getEmigRules(); const transferRules trfr = pSpecies->getTransferRules(); @@ -281,14 +281,14 @@ void Individual::setSettlementTraits(Species* pSpecies, bool sexDep) { void Individual::inheritTraits(Species* pSpecies, Individual* mother, Individual* father, int resol) { inherit(pSpecies, mother, father); - setQTLPhenotypes(pSpecies, resol); + setDispersalPhenotypes(pSpecies, resol); } // Inherit genome from mother, haploid void Individual::inheritTraits(Species* pSpecies, Individual* mother, int resol) { inherit(pSpecies, mother); - setQTLPhenotypes(pSpecies, resol); + setDispersalPhenotypes(pSpecies, resol); } //--------------------------------------------------------------------------- diff --git a/Individual.h b/Individual.h index a84b397..0fed752 100644 --- a/Individual.h +++ b/Individual.h @@ -249,7 +249,7 @@ class Individual { void inheritTraits(Species* pSpecies, Individual* mother, int resol); //haploid - void setQTLPhenotypes(Species* pSpecies, int resol); + void setDispersalPhenotypes(Species* pSpecies, int resol); TTrait* getTrait(TraitType trait) const; diff --git a/Landscape.cpp b/Landscape.cpp index 711d5b9..569e7a0 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -547,7 +547,7 @@ void Landscape::addPatchNum(int p) { /* Create an artificial landscape (random or fractal), which can be either binary (habitat index 0 is the matrix, 1 is suitable habitat) or continuous (0 is the matrix, >0 is suitable habitat) */ -void Landscape::generatePatches(Species* pSpecies) +void Landscape::generatePatches() { int x, y, ncells; double p; diff --git a/Landscape.h b/Landscape.h index f154f6e..1d0bf92 100644 --- a/Landscape.h +++ b/Landscape.h @@ -235,7 +235,7 @@ class Landscape { void setCellArray(void); void addPatchNum(int); std::vector getPatchNums() const { return patchnums; } - void generatePatches(Species*); // create an artificial landscape + void generatePatches(); // create an artificial landscape void allocatePatches(Species*); // create patches for a cell-based landscape Patch* newPatch( int // patch sequential no. (id no. is set to equal sequential no.) diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 68897e7..f8cc187 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -94,7 +94,7 @@ bool SpeciesTrait::isValidTraitVal(const float& val) const { && val <= 1.0; break; } - // Quantitative trait loci + // Dispersal traits /// Emigration case E_D0_F: case E_D0_M: { return val >= 0.0 && val <= 1.0; // is a probability diff --git a/TraitFactory.h b/TraitFactory.h index 889eeae..c29b2c3 100644 --- a/TraitFactory.h +++ b/TraitFactory.h @@ -5,7 +5,7 @@ #include "SpeciesTrait.h" #include "SNPTrait.h" -#include "QTLTrait.h" +#include "DispersalTrait.h" #include "GeneticFitnessTrait.h" // Create handled pointers to a new trait @@ -27,7 +27,7 @@ class TraitFactory return make_unique(protoTrait); } else { - return make_unique(protoTrait); + return make_unique(protoTrait); } } }; From f2c39da63b252071c8fc8f6a80d790b8c147e220 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 22 May 2024 13:26:33 +0100 Subject: [PATCH 123/332] rename SNP into Neutral trait --- CMakeLists.txt | 4 +- Community.cpp | 8 ++-- NeutralStatsManager.cpp | 54 +++++++++++++------------- NeutralStatsManager.h | 12 +++--- SNPTrait.cpp => NeutralTrait.cpp | 66 ++++++++++++++++---------------- SNPTrait.h => NeutralTrait.h | 27 +++++++------ Parameters.h | 4 +- Population.cpp | 54 +++++++++++++------------- Population.h | 6 +-- SpeciesTrait.cpp | 2 +- TraitFactory.h | 6 +-- 11 files changed, 121 insertions(+), 122 deletions(-) rename SNPTrait.cpp => NeutralTrait.cpp (78%) rename SNPTrait.h => NeutralTrait.h (78%) diff --git a/CMakeLists.txt b/CMakeLists.txt index e98ad1b..a20ab8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,9 +7,9 @@ if (NOT batchmode) # that is, RScore as a standalone # specify the C++ standard set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) - add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) + add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) else() # that is, RScore compiled as library within RangeShifter_batch - add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) + add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) endif() # pass config definitions to compiler diff --git a/Community.cpp b/Community.cpp index 4e4b3dc..89fa5a6 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1766,7 +1766,7 @@ void Community::writeWCFstatFile(int rep, int yr, int gen) { void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList) { - const set positions = pSpecies->getSpTrait(SNP)->getGenePositions(); + const set positions = pSpecies->getSpTrait(NEUTRAL)->getGenePositions(); int thisLocus = 0; for (int position : positions) { @@ -1845,8 +1845,8 @@ void Community::writePairwiseFSTFile(Species* pSpecies, const int yr, const int void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool fstat, bool perLocus, bool pairwise) { - const int nAlleles = (int)(pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second); - const int nLoci = (int)pSpecies->getNPositionsForTrait(SNP); + const int nAlleles = (int)(pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second); + const int nLoci = (int)pSpecies->getNPositionsForTrait(NEUTRAL); const set patchList = pSpecies->getSamplePatches(); int nInds = 0; @@ -1864,7 +1864,7 @@ void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, if (pNeutralStatistics == 0) pNeutralStatistics = make_unique(patchList.size(), nLoci); - pNeutralStatistics->updateAllSNPTables(pSpecies, pLandscape, patchList); + pNeutralStatistics->updateAllNeutralTables(pSpecies, pLandscape, patchList); if (fstat) { pNeutralStatistics->calculateHo(patchList, nInds, nLoci, pSpecies, pLandscape); diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index ca46a56..307bce3 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -29,27 +29,27 @@ // ---------------------------------------------------------------------------------------- NeutralStatsManager::NeutralStatsManager(const int& nbSampledPatches, const int nLoci) { this->pairwiseFstMatrix = PatchMatrix(nbSampledPatches, nbSampledPatches); - commSNPCountTables.reserve(nLoci); //don't have to be pointers, not shared or moved + commNeutralCountTables.reserve(nLoci); //don't have to be pointers, not shared or moved } // ---------------------------------------------------------------------------------------- -// Populate population and community-level SNP count tables +// Populate population and community-level NEUTRAL count tables // Update allele occurrence and heterozygosity counts, and allele frequencies // ---------------------------------------------------------------------------------------- -void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLandscape, set const& patchList) { +void NeutralStatsManager::updateAllNeutralTables(Species* pSpecies, Landscape* pLandscape, set const& patchList) { - const int nLoci = pSpecies->getNPositionsForTrait(SNP); - const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; + const int nLoci = pSpecies->getNPositionsForTrait(NEUTRAL); + const int nAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second; const int ploidy = pSpecies->isDiploid() ? 2 : 1; - // Create / Update community-level SNP counts table - if (!commSNPCountTables.empty()) { - resetCommSNPtables(); + // Create / Update community-level NEUTRAL counts table + if (!commNeutralCountTables.empty()) { + resetCommNeutralTables(); } else { // populate the tables with default values for (int thisLocus = 0; thisLocus < nLoci; thisLocus++) { - SNPCountsTable newSNPtbl = SNPCountsTable(nAlleles); - commSNPCountTables.push_back(newSNPtbl); + NeutralCountsTable newNeutralTbl = NeutralCountsTable(nAlleles); + commNeutralCountTables.push_back(newNeutralTbl); } } @@ -61,8 +61,8 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop != 0) { - // Update this population's SNP counts tables - pPop->updatePopSNPtables(); + // Update this population's NEUTRAL counts tables + pPop->updatePopNeutralTables(); nbSampledInds += pPop->sampleSize(); } // Add population-level counts to community-level counts @@ -75,24 +75,24 @@ void NeutralStatsManager::updateAllSNPTables(Species* pSpecies, Landscape* pLand else { patchAlleleCount = 0; } - commSNPCountTables[thisLocus].incrementTallyBy(patchAlleleCount, allele); + commNeutralCountTables[thisLocus].incrementTallyBy(patchAlleleCount, allele); } } } // Update community-level frequencies - std::for_each(commSNPCountTables.begin(), - commSNPCountTables.end(), - [&](SNPCountsTable& v) -> void { + std::for_each(commNeutralCountTables.begin(), + commNeutralCountTables.end(), + [&](NeutralCountsTable& v) -> void { v.setFrequencies(nbSampledInds * ploidy); }); } // ---------------------------------------------------------------------------------------- -// Reset allele tables in SNPtable structs +// Reset allele tables in NeutralTable structs // ---------------------------------------------------------------------------------------- -void NeutralStatsManager::resetCommSNPtables() { - for (auto& entry : commSNPCountTables) { +void NeutralStatsManager::resetCommNeutralTables() { + for (auto& entry : commNeutralCountTables) { entry.reset(); } } @@ -103,8 +103,8 @@ void NeutralStatsManager::resetCommSNPtables() { void NeutralStatsManager::calcAllelicDiversityMetrics(set const& patchList, const int nInds, Species* pSpecies, Landscape* pLandscape) { int i, j; - const int nLoci = pSpecies->getNPositionsForTrait(SNP); - const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; + const int nLoci = pSpecies->getNPositionsForTrait(NEUTRAL); + const int nAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second; const int ploidy = pSpecies->isDiploid() ? 2 : 1; unsigned int nbPopulatedPatches = 0; int nbAllelesInPatch = 0; @@ -171,7 +171,7 @@ void NeutralStatsManager::calcAllelicDiversityMetrics(set const& patchList, nbGloballyFixedAlleles = 0; for (i = 0; i < nLoci; ++i) for (j = 0; j < nAlleles; ++j) - nbGloballyFixedAlleles += commSNPCountTables[i].getFrequency(j) == 1; + nbGloballyFixedAlleles += commNeutralCountTables[i].getFrequency(j) == 1; } // ---------------------------------------------------------------------------------------- @@ -229,7 +229,7 @@ void NeutralStatsManager::calculateHt(Species* pSpecies, Landscape* pLandscape, for (int thisLocus = 0; thisLocus < nLoci; ++thisLocus) { for (int allele = 0; allele < nAlleles; ++allele) { - freq = commSNPCountTables[thisLocus].getFrequency(allele); + freq = commNeutralCountTables[thisLocus].getFrequency(allele); freq *= freq; //squared frequencies locihet[thisLocus] -= freq; //1 - sum of p2 = expected heterozygosity } @@ -318,7 +318,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int for (int allele = 0; allele < nAlleles; ++allele) { s2 = hBar = 0; - pBar = commSNPCountTables[thisLocus].getFrequency(allele); + pBar = commNeutralCountTables[thisLocus].getFrequency(allele); for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); @@ -438,7 +438,7 @@ void NeutralStatsManager::calcPerLocusMeanSquaresFst(set const& patchList, het = pPop->getHeteroTally(locus, allele); // ni * h_i pi = pPop->getAlleleFrequency(locus, allele); - pBar = commSNPCountTables[locus].getFrequency(allele); + pBar = commNeutralCountTables[locus].getFrequency(allele); var = pi - pBar; //(p_liu - pbar_u)^2 var *= var; @@ -535,7 +535,7 @@ void NeutralStatsManager::calcPerLocusMeanSquaresFst(set const& patchList, // ---------------------------------------------------------------------------------------- void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape) { - const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; + const int nAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second; const int ploidy = pSpecies->isDiploid() ? 2 : 1; // Needs to be in vector to iterate over, copy preserves order @@ -592,7 +592,7 @@ void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, con for (int u = 0; u < nAlleles; ++u) { p = pPop->getAlleleFrequency(l, u); //p_liu pq = p * (1 - p); - pBar = commSNPCountTables[l].getFrequency(u); + pBar = commNeutralCountTables[l].getFrequency(u); sqDist = p - pBar; //(p_liu - pbar_u)^2 sqDist *= sqDist; diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index c520484..ee0fdf4 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -45,12 +45,12 @@ struct PatchMatrix vector value; }; -// Counts of SNP allele occurrences in populations +// Counts of NEUTRAL allele occurrences in populations // for neutral statistics calculations -struct SNPCountsTable { +struct NeutralCountsTable { public: - SNPCountsTable(int nAllele) : alleleTallies(nAllele), alleleFrequencies(nAllele), alleleHeterozygoteTallies(nAllele) {}; + NeutralCountsTable(int nAllele) : alleleTallies(nAllele), alleleFrequencies(nAllele), alleleHeterozygoteTallies(nAllele) {}; void reset() { fill(alleleTallies.begin(), alleleTallies.end(), 0); fill(alleleFrequencies.begin(), alleleFrequencies.end(), 0); @@ -88,8 +88,8 @@ class NeutralStatsManager { NeutralStatsManager(const int& nbSampledPatches, const int nLoci); // Count alleles and their frequencies in all pops and community - void updateAllSNPTables(Species* pSpecies, Landscape* pLandscape, set const& patchList); - void resetCommSNPtables(); + void updateAllNeutralTables(Species* pSpecies, Landscape* pLandscape, set const& patchList); + void resetCommNeutralTables(); void calcAllelicDiversityMetrics(set const& patchList, const int nInds, Species* pSpecies, Landscape* pLandscape); @@ -134,7 +134,7 @@ class NeutralStatsManager { private: int nbExtantPops, totalNbSampledInds; - vector commSNPCountTables; // community-level tallies of allele counts and freqs + vector commNeutralCountTables; // community-level tallies of allele counts and freqs double meanNbAllelesPerLocusPerPatch, meanNbAllelesPerLocus; double meanNbFixedAllelesPerPatch, nbGloballyFixedAlleles; diff --git a/SNPTrait.cpp b/NeutralTrait.cpp similarity index 78% rename from SNPTrait.cpp rename to NeutralTrait.cpp index 18b8d1a..7b4240d 100644 --- a/SNPTrait.cpp +++ b/NeutralTrait.cpp @@ -1,4 +1,4 @@ -#include "SNPTrait.h" +#include "NeutralTrait.h" // ---------------------------------------------------------------------------------------- // Initialisation constructor @@ -6,7 +6,7 @@ // Sets up initial values, and immutable attributes (distributions and parameters) // that are defined at the species-level // ---------------------------------------------------------------------------------------- -SNPTrait::SNPTrait(SpeciesTrait* P) +NeutralTrait::NeutralTrait(SpeciesTrait* P) { pSpeciesTrait = P; @@ -15,16 +15,16 @@ SNPTrait::SNPTrait(SpeciesTrait* P) // Set default value to user-specified max wildType = (int)mutationParameters.find(MAX)->second - 1; - if (wildType > SNPvalUpperBound) - throw logic_error("Error:: max number of alleles cannot exceed " + to_string(SNPvalUpperBound) + ".\n"); + if (wildType > NeutralValUpperBound) + throw logic_error("Error:: max number of alleles cannot exceed " + to_string(NeutralValUpperBound) + ".\n"); - _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &SNPTrait::inheritHaploid : &SNPTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance + _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &NeutralTrait::inheritHaploid : &NeutralTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance if (mutationDistribution == SSM) - _mutate_func_ptr = &SNPTrait::mutate_SSM; + _mutate_func_ptr = &NeutralTrait::mutate_SSM; if (mutationDistribution == KAM) - _mutate_func_ptr = &SNPTrait::mutate_KAM; + _mutate_func_ptr = &NeutralTrait::mutate_KAM; if (mutationDistribution != SSM && mutationDistribution != KAM) throw logic_error("Error:: wrong mutation distribution for neutral markers, must be KAM or SSM \n"); @@ -42,21 +42,21 @@ SNPTrait::SNPTrait(SpeciesTrait* P) case UNIFORM: { if (initialParameters.count(MAX) != 1) - throw logic_error("Error:: initial SNP/Microsat distribution parameter must contain one max value if set to UNIFORM (e.g. max= ), max cannot exceed " + to_string(SNPvalUpperBound) + "\n"); + throw logic_error("Error:: initial distribution parameter must contain one max value if set to UNIFORM (e.g. max= ), max cannot exceed " + to_string(NeutralValUpperBound) + "\n"); - float maxSNPval = initialParameters.find(MAX)->second; - if (maxSNPval > SNPvalUpperBound) { - throw logic_error("Warning:: initial SNP/Microsat distribution parameter max cannot exceed " + to_string(SNPvalUpperBound) + ", resetting to " + to_string(SNPvalUpperBound) + "\n"); - maxSNPval = SNPvalUpperBound; //reserve 255 for wildtype + float maxNeutralVal = initialParameters.find(MAX)->second; + if (maxNeutralVal > NeutralValUpperBound) { + throw logic_error("Warning:: initial distribution parameter max cannot exceed " + to_string(NeutralValUpperBound) + ", resetting to " + to_string(NeutralValUpperBound) + "\n"); + maxNeutralVal = NeutralValUpperBound; //reserve 255 for wildtype } - initialiseUniform(maxSNPval); + initialiseUniform(maxNeutralVal); break; } case NONE: break; default: { - throw logic_error("wrong parameter value for parameter \"initialisation of snp/microsat\", must be left as default (#) or uniform \n"); + throw logic_error("wrong parameter value for parameter \"initialisation of neutral trait\", must be left as default (#) or uniform \n"); break; //should return false } } @@ -67,7 +67,7 @@ SNPTrait::SNPTrait(SpeciesTrait* P) // Copies immutable features from a parent trait // Only called via clone() // ---------------------------------------------------------------------------------------- -SNPTrait::SNPTrait(const SNPTrait& T) : +NeutralTrait::NeutralTrait(const NeutralTrait& T) : pSpeciesTrait(T.pSpeciesTrait), _mutate_func_ptr(T._mutate_func_ptr), _inherit_func_ptr(T._inherit_func_ptr) { } @@ -82,7 +82,7 @@ SNPTrait::SNPTrait(const SNPTrait& T) : // that is no new genes are created during simulation // KAM = randomly drawn value in 0-MAX, differs from previous value // ---------------------------------------------------------------------------------------- -void SNPTrait::mutate_KAM() +void NeutralTrait::mutate_KAM() { const int positionsSize = pSpeciesTrait->getPositionsSize(); const auto& genePositions = pSpeciesTrait->getGenePositions(); @@ -93,8 +93,8 @@ void SNPTrait::mutate_KAM() map mutationParameters = pSpeciesTrait->getMutationParameters(); - int maxSNPval = (int)mutationParameters.find(MAX)->second; - if (maxSNPval > SNPvalUpperBound) maxSNPval = SNPvalUpperBound; //reserve max value for wildtype + int maxNeutralVal = (int)mutationParameters.find(MAX)->second; + if (maxNeutralVal > NeutralValUpperBound) maxNeutralVal = NeutralValUpperBound; //reserve max value for wildtype for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { @@ -105,14 +105,14 @@ void SNPTrait::mutate_KAM() NbMut, rng); // without replacement for (int m : mutationPositions) { - mut = (unsigned char)pRandom->IRandom(0, maxSNPval); // draw new mutation, could draw wildtype + mut = (unsigned char)pRandom->IRandom(0, maxNeutralVal); // draw new mutation, could draw wildtype auto it = genes.find(m); if (it == genes.end()) throw runtime_error("Locus selected for mutation doesn't exist."); auto currentChar = it->second[whichChromosome]; // current allele do { - mut = (unsigned char)pRandom->IRandom(0, maxSNPval); + mut = (unsigned char)pRandom->IRandom(0, maxNeutralVal); } while (mut == currentChar); // new allele value is different it->second[whichChromosome] = mut; //overwrite with new value @@ -130,7 +130,7 @@ void SNPTrait::mutate_KAM() // Increment previous value by 1 or -1, // unless already 0 (then always +1) or MAX (then always -1) // ---------------------------------------------------------------------------------------- -void SNPTrait::mutate_SSM() +void NeutralTrait::mutate_SSM() { const int positionsSize = pSpeciesTrait->getPositionsSize(); const auto& genePositions = pSpeciesTrait->getGenePositions(); @@ -140,8 +140,8 @@ void SNPTrait::mutate_SSM() map mutationParameters = pSpeciesTrait->getMutationParameters(); - int maxSNPval = (int)mutationParameters.find(MAX)->second; - if (maxSNPval > SNPvalUpperBound) maxSNPval = SNPvalUpperBound; //reserved max value for wildtype + int maxNeutralVal = (int)mutationParameters.find(MAX)->second; + if (maxNeutralVal > NeutralValUpperBound) maxNeutralVal = NeutralValUpperBound; //reserved max value for wildtype for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { @@ -157,7 +157,7 @@ void SNPTrait::mutate_SSM() if (it == genes.end()) throw runtime_error("Locus selected for mutation doesn't exist."); auto currentAllele = it->second[whichChromosome]; - if (mutateUp == 1 && currentAllele < maxSNPval) + if (mutateUp == 1 && currentAllele < maxNeutralVal) it->second[whichChromosome] += 1; // one step up else if (currentAllele > 0) // step down or already max it->second[whichChromosome] -= 1; // one step down @@ -171,9 +171,9 @@ void SNPTrait::mutate_SSM() // ---------------------------------------------------------------------------------------- // Wrapper to inheritance function // ---------------------------------------------------------------------------------------- -void SNPTrait::inheritGenes(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) +void NeutralTrait::inheritGenes(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) { - auto parentCast = dynamic_cast (parent); // must convert TTrait to SNPTrait + auto parentCast = dynamic_cast (parent); // must convert TTrait to NeutralTrait const auto& parent_seq = parentCast->getGenes(); (this->*_inherit_func_ptr) (fromMother, parent_seq, recomPositions, startingChromosome); } @@ -184,7 +184,7 @@ void SNPTrait::inheritGenes(const bool& fromMother, TTrait* parent, set> const& parentGenes, set const& recomPositions, int parentChromosome) { +void NeutralTrait::inheritDiploid(const bool& fromMother, map> const& parentGenes, set const& recomPositions, int parentChromosome) { auto it = recomPositions.lower_bound(parentGenes.begin()->first); unsigned int nextBreakpoint = *it; @@ -224,7 +224,7 @@ void SNPTrait::inheritDiploid(const bool& fromMother, map> const& parentGenes, set const& recomPositions, int parentChromosome) +void NeutralTrait::inheritHaploid(const bool& fromMother, map> const& parentGenes, set const& recomPositions, int parentChromosome) { genes = parentGenes; } @@ -232,7 +232,7 @@ void SNPTrait::inheritHaploid(const bool& fromMother, mapgetGenePositions(); short ploidy = pSpeciesTrait->getPloidy(); @@ -253,11 +253,11 @@ void SNPTrait::initialiseUniform(int maxAlleleVal) // ---------------------------------------------------------------------------------------- // Check if particular loci is heterozygote // ---------------------------------------------------------------------------------------- -bool SNPTrait::isHeterozygoteAtLocus(int locus) const { +bool NeutralTrait::isHeterozygoteAtLocus(int locus) const { // assumes diploidy auto it = genes.find(locus); if (it == genes.end()) - throw runtime_error("SNP gene queried for heterozygosity does not exist."); + throw runtime_error("Neutral gene queried for heterozygosity does not exist."); else return(it->second[0] != it->second[1]); } @@ -265,7 +265,7 @@ bool SNPTrait::isHeterozygoteAtLocus(int locus) const { // ---------------------------------------------------------------------------------------- // Count heterozygote loci in genome // ---------------------------------------------------------------------------------------- -int SNPTrait::countHeterozygoteLoci() const { +int NeutralTrait::countHeterozygoteLoci() const { // assumes diploidy int count = 0; for (auto const& [locus, allelePair] : genes) { @@ -277,7 +277,7 @@ int SNPTrait::countHeterozygoteLoci() const { // ---------------------------------------------------------------------------------------- // Get allele value at loci // ---------------------------------------------------------------------------------------- -float SNPTrait::getAlleleValueAtLocus(short whichChromosome, int position) const { +float NeutralTrait::getAlleleValueAtLocus(short whichChromosome, int position) const { auto it = genes.find(position); if (it == genes.end()) //no mutations there diff --git a/SNPTrait.h b/NeutralTrait.h similarity index 78% rename from SNPTrait.h rename to NeutralTrait.h index 2e258c0..7c1ac96 100644 --- a/SNPTrait.h +++ b/NeutralTrait.h @@ -1,5 +1,5 @@ -#ifndef SNPTRAITH -#define SNPTRAITH +#ifndef NeutralTRAITH +#define NeutralTRAITH #include #include @@ -10,29 +10,28 @@ using namespace std; -// Single-nucleotide polymorphism (SNP) traits +// Neutral traits // -// That is, neutral genetic variation - SNP traits -// do not express and are only used to compute neutral statistics +// Not expressed and are only used to compute neutral statistics // e.g. the Fst. // To save on mem usage, allele values are represented by character types, // taking a value between 0 and a user-specified max >= 255 -class SNPTrait : public TTrait { +class NeutralTrait : public TTrait { public: // Initialisation constructor, set initial values and immutable features - SNPTrait(SpeciesTrait* P); + NeutralTrait(SpeciesTrait* P); // Inheritance constructor, copies pointers to immutable features when cloning from parent - SNPTrait(const SNPTrait& T); + NeutralTrait(const NeutralTrait& T); // Make a shallow copy to pass to offspring trait // Return new pointer to new trait created by inheritance c'tor // This avoids copying shared attributes: distributions and parameters - virtual unique_ptr clone() const override { return std::make_unique(*this); } + virtual unique_ptr clone() const override { return std::make_unique(*this); } - virtual ~SNPTrait() { } + virtual ~NeutralTrait() { } // Getters virtual int getNLoci() const override { return pSpeciesTrait->getPositionsSize(); } @@ -43,7 +42,7 @@ class SNPTrait : public TTrait { virtual void mutate() override { (this->*_mutate_func_ptr) (); } virtual void inheritGenes(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; virtual float express() { - throw runtime_error("SNP trait shouldn't be expressed."); + throw runtime_error("Neutral trait shouldn't be expressed."); return -9999; } @@ -54,7 +53,7 @@ class SNPTrait : public TTrait { private: inline static int wildType; // default allele value, value set at construction - const int SNPvalUpperBound = UCHAR_MAX; // alleles are char, can take value 0-255 + const int NeutralValUpperBound = UCHAR_MAX; // alleles are char, can take value 0-255 // > map> genes; @@ -67,8 +66,8 @@ class SNPTrait : public TTrait { //// Species-level trait attributes, invariant across individuals SpeciesTrait* pSpeciesTrait; //// Species-level trait functions - void (SNPTrait::* _mutate_func_ptr) (void); - void (SNPTrait::* _inherit_func_ptr) (const bool& fromMother, map> const& parent, set const& recomPositions, int parentChromosome); + void (NeutralTrait::* _mutate_func_ptr) (void); + void (NeutralTrait::* _inherit_func_ptr) (const bool& fromMother, map> const& parent, set const& recomPositions, int parentChromosome); // Possible values for immutable functions //// Inheritance diff --git a/Parameters.h b/Parameters.h index 90fb677..cfd81de 100644 --- a/Parameters.h +++ b/Parameters.h @@ -116,7 +116,7 @@ const rgb draw_wheel(int); /** Trait types **/ enum TraitType { - SNP, + NEUTRAL, GENETIC_LOAD, GENETIC_LOAD1, GENETIC_LOAD2, GENETIC_LOAD3, GENETIC_LOAD4, GENETIC_LOAD5, E_D0, E_ALPHA, E_BETA, @@ -149,7 +149,7 @@ typedef enum { KERNEL, SMS, CRW} movement_t; //sex types typedef enum { FEM = 0, MAL = 1, - NA, // not applicable. e.g. for SNP or genetic load trait + NA, // not applicable. e.g. for NEUTRAL or genetic load trait INVALID_SEX // error } sex_t; diff --git a/Population.cpp b/Population.cpp index ea4c5f7..90f3dca 100644 --- a/Population.cpp +++ b/Population.cpp @@ -320,52 +320,52 @@ int Population::getNInds(void) { return (int)inds.size(); } // ---------------------------------------------------------------------------------------- // reset allele table // ---------------------------------------------------------------------------------------- -void Population::resetPopSNPtables() { - for (auto& entry : popSNPCountTables) { +void Population::resetPopNeutralTables() { + for (auto& entry : popNeutralCountTables) { entry.reset(); } } // ---------------------------------------------------------------------------------------- -// Populate population-level SNP count tables +// Populate population-level NEUTRAL count tables // Update allele occurrence and heterozygosity counts, and allele frequencies // ---------------------------------------------------------------------------------------- -void Population::updatePopSNPtables() { +void Population::updatePopNeutralTables() { - const int nLoci = pSpecies->getNPositionsForTrait(SNP); - const int nAlleles = (int)pSpecies->getSpTrait(SNP)->getMutationParameters().find(MAX)->second; - const auto& positions = pSpecies->getSpTrait(SNP)->getGenePositions(); + const int nLoci = pSpecies->getNPositionsForTrait(NEUTRAL); + const int nAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second; + const auto& positions = pSpecies->getSpTrait(NEUTRAL)->getGenePositions(); const int ploidy = pSpecies->isDiploid() ? 2 : 1; // Create /reset empty tables - if (popSNPCountTables.size() != 0) - resetPopSNPtables(); + if (popNeutralCountTables.size() != 0) + resetPopNeutralTables(); else { - popSNPCountTables.reserve(nLoci); + popNeutralCountTables.reserve(nLoci); for (int l = 0; l < nLoci; l++) { - popSNPCountTables.push_back(SNPCountsTable(nAlleles)); + popNeutralCountTables.push_back(NeutralCountsTable(nAlleles)); } } // Fill tallies for each locus for (Individual* individual : sampledInds) { - const auto trait = individual->getTrait(SNP); + const auto trait = individual->getTrait(NEUTRAL); int whichLocus = 0; for (auto position : positions) { int alleleOnChromA = (int)trait->getAlleleValueAtLocus(0, position); - popSNPCountTables[whichLocus].incrementTally(alleleOnChromA); + popNeutralCountTables[whichLocus].incrementTally(alleleOnChromA); if (ploidy == 2) { // second allele and heterozygosity int alleleOnChromB = (int)trait->getAlleleValueAtLocus(1, position); - popSNPCountTables[whichLocus].incrementTally(alleleOnChromB); + popNeutralCountTables[whichLocus].incrementTally(alleleOnChromB); bool isHetero = alleleOnChromA != alleleOnChromB; if (isHetero) { - popSNPCountTables[whichLocus].incrementHeteroTally(alleleOnChromA); - popSNPCountTables[whichLocus].incrementHeteroTally(alleleOnChromB); + popNeutralCountTables[whichLocus].incrementHeteroTally(alleleOnChromA); + popNeutralCountTables[whichLocus].incrementHeteroTally(alleleOnChromB); } } whichLocus++; @@ -375,24 +375,24 @@ void Population::updatePopSNPtables() { // Fill frequencies if (sampledInds.size() > 0) { std::for_each( - popSNPCountTables.begin(), - popSNPCountTables.end(), - [&](SNPCountsTable& thisLocus) -> void { + popNeutralCountTables.begin(), + popNeutralCountTables.end(), + [&](NeutralCountsTable& thisLocus) -> void { thisLocus.setFrequencies(static_cast(sampledInds.size()) * ploidy); }); } } double Population::getAlleleFrequency(int thisLocus, int whichAllele) { - return popSNPCountTables[thisLocus].getFrequency(whichAllele); + return popNeutralCountTables[thisLocus].getFrequency(whichAllele); } int Population::getAlleleTally(int thisLocus, int whichAllele) { - return popSNPCountTables[thisLocus].getTally(whichAllele); + return popNeutralCountTables[thisLocus].getTally(whichAllele); } int Population::getHeteroTally(int thisLocus, int whichAllele) { - return popSNPCountTables[thisLocus].getHeteroTally(whichAllele); + return popNeutralCountTables[thisLocus].getHeteroTally(whichAllele); } // ---------------------------------------------------------------------------------------- @@ -402,7 +402,7 @@ int Population::countHeterozygoteLoci() { int nbHetero = 0; if (pSpecies->isDiploid()) { for (Individual* ind : sampledInds) { - const auto trait = ind->getTrait(SNP); + const auto trait = ind->getTrait(NEUTRAL); nbHetero += trait->countHeterozygoteLoci(); } } @@ -413,12 +413,12 @@ int Population::countHeterozygoteLoci() { // Count number of heterozygotes among sampled individuals for each locus // ---------------------------------------------------------------------------------------- vector Population::countNbHeterozygotesEachLocus() { - const auto& positions = pSpecies->getSpTrait(SNP)->getGenePositions(); + const auto& positions = pSpecies->getSpTrait(NEUTRAL)->getGenePositions(); vector hetero(positions.size(), 0); if (pSpecies->isDiploid()) { for (Individual* ind : sampledInds) { - const auto trait = ind->getTrait(SNP); + const auto trait = ind->getTrait(NEUTRAL); int counter = 0; for (auto position : positions) { hetero[counter] += trait->isHeterozygoteAtLocus(position); @@ -433,8 +433,8 @@ vector Population::countNbHeterozygotesEachLocus() { // Compute the expected heterozygosity for population // ---------------------------------------------------------------------------------------- double Population::computeHs() { - int nLoci = pSpecies->getNPositionsForTrait(SNP); - int nAlleles = (int)pSpecies->getSpTrait(SNP)->getInitialParameters().find(MAX)->second; + int nLoci = pSpecies->getNPositionsForTrait(NEUTRAL); + int nAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getInitialParameters().find(MAX)->second; double hs = 0; double freq; vector locihet(nLoci, 1); diff --git a/Population.h b/Population.h index 642e623..b019183 100644 --- a/Population.h +++ b/Population.h @@ -221,7 +221,7 @@ class Population { void outputGeneValues(ofstream& ofsGenes, const int& yr, const int& gen) const; void clean(void); // Remove zero pointers to dead or dispersed individuals - void updatePopSNPtables(); + void updatePopNeutralTables(); double getAlleleFrequency(int locus, int allele); int getAlleleTally(int locus, int allele); int getHeteroTally(int locus, int allele); @@ -241,8 +241,8 @@ class Population { // has been completed vector sampledInds; - vector popSNPCountTables; - void resetPopSNPtables(); + vector popNeutralCountTables; + void resetPopNeutralTables(); }; //--------------------------------------------------------------------------- diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index f8cc187..fd9b571 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -83,7 +83,7 @@ bool SpeciesTrait::isValidTraitVal(const float& val) const { switch (traitType) { // Neutral trait - case SNP: // only need to check for input parameters + case NEUTRAL: // only need to check for input parameters { return val >= 0.0 && val <= 255.0; } diff --git a/TraitFactory.h b/TraitFactory.h index c29b2c3..a44c872 100644 --- a/TraitFactory.h +++ b/TraitFactory.h @@ -4,7 +4,7 @@ #include #include "SpeciesTrait.h" -#include "SNPTrait.h" +#include "NeutralTrait.h" #include "DispersalTrait.h" #include "GeneticFitnessTrait.h" @@ -16,8 +16,8 @@ class TraitFactory unique_ptr Create(const TraitType traitType, SpeciesTrait* protoTrait) { - if (traitType == SNP) { - return make_unique(protoTrait); + if (traitType == NEUTRAL) { + return make_unique(protoTrait); } else if (traitType == GENETIC_LOAD1 || traitType == GENETIC_LOAD2 From 7fadd23cb78d4722aca84781339e42328210ab8c Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 22 May 2024 13:41:30 +0100 Subject: [PATCH 124/332] rename TTrait into QuantitativeTrait --- DispersalTrait.cpp | 4 ++-- DispersalTrait.h | 8 ++++---- GeneticFitnessTrait.cpp | 4 ++-- GeneticFitnessTrait.h | 8 ++++---- Individual.cpp | 2 +- Individual.h | 4 ++-- NeutralTrait.cpp | 4 ++-- NeutralTrait.h | 8 ++++---- TTrait.h => QuantitativeTrait.h | 8 ++++---- Species.h | 2 +- TraitFactory.h | 2 +- 11 files changed, 27 insertions(+), 27 deletions(-) rename TTrait.h => QuantitativeTrait.h (69%) diff --git a/DispersalTrait.cpp b/DispersalTrait.cpp index 81931ad..7b982fb 100644 --- a/DispersalTrait.cpp +++ b/DispersalTrait.cpp @@ -192,9 +192,9 @@ void DispersalTrait::mutateNormal() // ---------------------------------------------------------------------------------------- // Wrapper to inheritance function // ---------------------------------------------------------------------------------------- -void DispersalTrait::inheritGenes(const bool& fromMother, TTrait* parentTrait, set const& recomPositions, int startingChromosome) +void DispersalTrait::inheritGenes(const bool& fromMother, QuantitativeTrait* parentTrait, set const& recomPositions, int startingChromosome) { - auto parentCast = dynamic_cast(parentTrait); // must convert TTrait to DispersalTrait + auto parentCast = dynamic_cast(parentTrait); // must convert QuantitativeTrait to DispersalTrait const auto& parent_seq = parentCast->getGenes(); (this->*_inherit_func_ptr)(fromMother, parent_seq, recomPositions, startingChromosome); } diff --git a/DispersalTrait.h b/DispersalTrait.h index bf47613..846fbea 100644 --- a/DispersalTrait.h +++ b/DispersalTrait.h @@ -6,14 +6,14 @@ #include #include -#include "TTrait.h" +#include "QuantitativeTrait.h" using namespace std; // Dispersal trait // // That is, all evolvable that control emigration, transfer and settlement -class DispersalTrait : public TTrait { +class DispersalTrait : public QuantitativeTrait { public: @@ -26,7 +26,7 @@ class DispersalTrait : public TTrait { // Make a shallow copy to pass to offspring trait // Return new pointer to new trait created by inheritance c'tor // This avoids copying shared attributes: distributions and parameters - virtual unique_ptr clone() const override { return std::make_unique(*this); } + virtual unique_ptr clone() const override { return std::make_unique(*this); } virtual ~DispersalTrait() { } @@ -39,7 +39,7 @@ class DispersalTrait : public TTrait { void mutate() override { (this->*_mutate_func_ptr) (); } float express() override { return (this->*_express_func_ptr) (); } - void inheritGenes(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; + void inheritGenes(const bool& fromMother, QuantitativeTrait* parent, set const& recomPositions, int startingChromosome) override; float getAlleleValueAtLocus(short chromosome, int i) const override; int countHeterozygoteLoci() const; diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index e7715db..1625966 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -293,9 +293,9 @@ float GeneticFitnessTrait::drawSelectionCoef() { // ---------------------------------------------------------------------------------------- // Wrapper to inheritance function // ---------------------------------------------------------------------------------------- -void GeneticFitnessTrait::inheritGenes(const bool& fromMother, TTrait* parentTrait, set const& recomPositions, int startingChromosome) +void GeneticFitnessTrait::inheritGenes(const bool& fromMother, QuantitativeTrait* parentTrait, set const& recomPositions, int startingChromosome) { - auto parentCast = dynamic_cast (parentTrait); // must convert TTrait to GeneticFitnessTrait + auto parentCast = dynamic_cast (parentTrait); // must convert QuantitativeTrait to GeneticFitnessTrait const auto& parent_seq = parentCast->getGenes(); (this->*_inherit_func_ptr) (fromMother, parent_seq, recomPositions, startingChromosome); } diff --git a/GeneticFitnessTrait.h b/GeneticFitnessTrait.h index 2563ea4..26f4e44 100644 --- a/GeneticFitnessTrait.h +++ b/GeneticFitnessTrait.h @@ -7,7 +7,7 @@ #include #include -#include "TTrait.h" +#include "QuantitativeTrait.h" using namespace std; @@ -17,7 +17,7 @@ using namespace std; // offspring viability. Alleles start with value // zero but increase through simulation via mutations. // There can be up to five genetic load traits. -class GeneticFitnessTrait : public TTrait { +class GeneticFitnessTrait : public QuantitativeTrait { public: @@ -30,7 +30,7 @@ class GeneticFitnessTrait : public TTrait { // Make a shallow copy to pass to offspring trait // Return new pointer to new trait created by inheritance c'tor // This avoids copying shared attributes: distributions and parameters - virtual unique_ptr clone() const override { return std::make_unique(*this); } + virtual unique_ptr clone() const override { return std::make_unique(*this); } virtual ~GeneticFitnessTrait() { } @@ -43,7 +43,7 @@ class GeneticFitnessTrait : public TTrait { virtual void mutate() override; virtual float express(); - virtual void inheritGenes(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; + virtual void inheritGenes(const bool& fromMother, QuantitativeTrait* parent, set const& recomPositions, int startingChromosome) override; virtual float getAlleleValueAtLocus(short chromosome, int position) const override; virtual int countHeterozygoteLoci() const; diff --git a/Individual.cpp b/Individual.cpp index e7bc108..e2ae7e0 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -97,7 +97,7 @@ void Individual::setSettleTraits(const settleTraits& settle) { pSettleTraits = make_unique(settle); } -TTrait* Individual::getTrait(TraitType trait) const { +QuantitativeTrait* Individual::getTrait(TraitType trait) const { auto p = this->spTraitTable.find(trait); if (p == spTraitTable.end()) throw runtime_error("Trait does not exist in trait table."); diff --git a/Individual.h b/Individual.h index 0fed752..9d79b71 100644 --- a/Individual.h +++ b/Individual.h @@ -251,7 +251,7 @@ class Individual { void setDispersalPhenotypes(Species* pSpecies, int resol); - TTrait* getTrait(TraitType trait) const; + QuantitativeTrait* getTrait(TraitType trait) const; set getTraitTypes(); @@ -399,7 +399,7 @@ class Individual { std::unique_ptr pSettleTraits; // pointer to settlement traits std::unique_ptr pTrfrData; //can be sms, kernel, crw std::queue memory; // memory of last N squares visited for SMS - map> spTraitTable; + map> spTraitTable; }; diff --git a/NeutralTrait.cpp b/NeutralTrait.cpp index 7b4240d..7c55c0c 100644 --- a/NeutralTrait.cpp +++ b/NeutralTrait.cpp @@ -171,9 +171,9 @@ void NeutralTrait::mutate_SSM() // ---------------------------------------------------------------------------------------- // Wrapper to inheritance function // ---------------------------------------------------------------------------------------- -void NeutralTrait::inheritGenes(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) +void NeutralTrait::inheritGenes(const bool& fromMother, QuantitativeTrait* parent, set const& recomPositions, int startingChromosome) { - auto parentCast = dynamic_cast (parent); // must convert TTrait to NeutralTrait + auto parentCast = dynamic_cast (parent); // must convert QuantitativeTrait to NeutralTrait const auto& parent_seq = parentCast->getGenes(); (this->*_inherit_func_ptr) (fromMother, parent_seq, recomPositions, startingChromosome); } diff --git a/NeutralTrait.h b/NeutralTrait.h index 7c1ac96..4581433 100644 --- a/NeutralTrait.h +++ b/NeutralTrait.h @@ -6,7 +6,7 @@ #include #include -#include "TTrait.h" +#include "QuantitativeTrait.h" using namespace std; @@ -16,7 +16,7 @@ using namespace std; // e.g. the Fst. // To save on mem usage, allele values are represented by character types, // taking a value between 0 and a user-specified max >= 255 -class NeutralTrait : public TTrait { +class NeutralTrait : public QuantitativeTrait { public: @@ -29,7 +29,7 @@ class NeutralTrait : public TTrait { // Make a shallow copy to pass to offspring trait // Return new pointer to new trait created by inheritance c'tor // This avoids copying shared attributes: distributions and parameters - virtual unique_ptr clone() const override { return std::make_unique(*this); } + virtual unique_ptr clone() const override { return std::make_unique(*this); } virtual ~NeutralTrait() { } @@ -40,7 +40,7 @@ class NeutralTrait : public TTrait { map>& getGenes() { return genes; } //returning reference, reciever must be const virtual void mutate() override { (this->*_mutate_func_ptr) (); } - virtual void inheritGenes(const bool& fromMother, TTrait* parent, set const& recomPositions, int startingChromosome) override; + virtual void inheritGenes(const bool& fromMother, QuantitativeTrait* parent, set const& recomPositions, int startingChromosome) override; virtual float express() { throw runtime_error("Neutral trait shouldn't be expressed."); return -9999; diff --git a/TTrait.h b/QuantitativeTrait.h similarity index 69% rename from TTrait.h rename to QuantitativeTrait.h index 2c42a9c..aab4966 100644 --- a/TTrait.h +++ b/QuantitativeTrait.h @@ -12,11 +12,11 @@ using namespace std; // Base interface for all genetic traits -class TTrait { +class QuantitativeTrait { public: virtual void mutate() = 0; - virtual unique_ptr clone() const = 0; //copies parameters (if not static) not gene seqeunces - virtual void inheritGenes(const bool&, TTrait*, set const& , int ) = 0; + virtual unique_ptr clone() const = 0; //copies parameters (if not static) not gene seqeunces + virtual void inheritGenes(const bool&, QuantitativeTrait*, set const& , int ) = 0; virtual int getNLoci() const = 0; virtual float getMutationRate() const = 0; virtual bool isInherited() const = 0; @@ -24,7 +24,7 @@ class TTrait { virtual int countHeterozygoteLoci() const = 0; virtual bool isHeterozygoteAtLocus(int loci) const = 0; virtual float express() = 0; - virtual ~TTrait() { } + virtual ~QuantitativeTrait() { } }; extern RSrandom* pRandom; diff --git a/Species.h b/Species.h index a545978..5beb9c7 100644 --- a/Species.h +++ b/Species.h @@ -52,7 +52,7 @@ #include "Parameters.h" #include "SpeciesTrait.h" -#include "TTrait.h" +#include "QuantitativeTrait.h" class SpeciesTrait; diff --git a/TraitFactory.h b/TraitFactory.h index a44c872..f5fc601 100644 --- a/TraitFactory.h +++ b/TraitFactory.h @@ -14,7 +14,7 @@ class TraitFactory public: TraitFactory() {}; - unique_ptr Create(const TraitType traitType, SpeciesTrait* protoTrait) + unique_ptr Create(const TraitType traitType, SpeciesTrait* protoTrait) { if (traitType == NEUTRAL) { return make_unique(protoTrait); From cda91a8955ebc987737c32732c35f76fb69645e9 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 27 May 2024 13:29:15 +0100 Subject: [PATCH 125/332] add forgotten sex-indpdt cases --- DispersalTrait.cpp | 18 +++++++++--------- SpeciesTrait.cpp | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/DispersalTrait.cpp b/DispersalTrait.cpp index 7b982fb..912e8ce 100644 --- a/DispersalTrait.cpp +++ b/DispersalTrait.cpp @@ -363,9 +363,9 @@ void DispersalTrait::trimPhenotype(float& val) { switch (pSpeciesTrait->getTraitType()) { // Values bound between 0 and 1 - case E_D0_F: case E_D0_M: - case S_S0_F: case S_S0_M: - case KERNEL_PROBABILITY_F: case KERNEL_PROBABILITY_M: + case E_D0_F: case E_D0_M: case E_D0: + case S_S0_F: case S_S0_M: case S_S0: + case KERNEL_PROBABILITY_F: case KERNEL_PROBABILITY_M: case KERNEL_PROBABILITY: case CRW_STEPCORRELATION: { if (val < 0.0) val = 0; @@ -373,16 +373,16 @@ void DispersalTrait::trimPhenotype(float& val) { break; } // Positive values - case KERNEL_MEANDIST_1_F: case KERNEL_MEANDIST_1_M: - case KERNEL_MEANDIST_2_F: case KERNEL_MEANDIST_2_M: + case KERNEL_MEANDIST_1_F: case KERNEL_MEANDIST_1_M: case KERNEL_MEANDIST_1: + case KERNEL_MEANDIST_2_F: case KERNEL_MEANDIST_2_M: case KERNEL_MEANDIST_2: case CRW_STEPLENGTH: { if (val < 0.0) val = 0; break; } // Strictly positive values - case E_ALPHA_F: case E_ALPHA_M: - case S_ALPHA_F: case S_ALPHA_M: + case E_ALPHA_F: case E_ALPHA_M: case E_ALPHA: + case S_ALPHA_F: case S_ALPHA_M: case S_ALPHA: case SMS_ALPHADB: { if (val <= 0.0) val = minPositiveVal; @@ -396,8 +396,8 @@ void DispersalTrait::trimPhenotype(float& val) { break; } // Not bound - case E_BETA_F: case E_BETA_M: - case S_BETA_F: case S_BETA_M: + case E_BETA_F: case E_BETA_M: case E_BETA: + case S_BETA_F: case S_BETA_M: case S_BETA: case SMS_BETADB: { break; diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index fd9b571..6ed9c3a 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -96,44 +96,44 @@ bool SpeciesTrait::isValidTraitVal(const float& val) const { } // Dispersal traits /// Emigration - case E_D0_F: case E_D0_M: { + case E_D0_F: case E_D0_M: case E_D0: { return val >= 0.0 && val <= 1.0; // is a probability break; } - case E_ALPHA_F: case E_ALPHA_M: + case E_ALPHA_F: case E_ALPHA_M: case E_ALPHA: { return val > 0.0; break; } - case E_BETA_F: case E_BETA_M: + case E_BETA_F: case E_BETA_M: case E_BETA: { return true; // inflexion point can be any value break; } /// Settlement - case S_S0_F: case S_S0_M: + case S_S0_F: case S_S0_M: case S_S0: { return val >= 0.0 && val <= 1.0; break; } - case S_ALPHA_F: case S_ALPHA_M: + case S_ALPHA_F: case S_ALPHA_M: case S_ALPHA: { return val > 0.0; break; } - case S_BETA_F: case S_BETA_M: + case S_BETA_F: case S_BETA_M: case S_BETA: { return true; break; } /// Transfer - Kernels - case KERNEL_MEANDIST_1_F: case KERNEL_MEANDIST_1_M: - case KERNEL_MEANDIST_2_F: case KERNEL_MEANDIST_2_M: + case KERNEL_MEANDIST_1_F: case KERNEL_MEANDIST_1_M: case KERNEL_MEANDIST_1: + case KERNEL_MEANDIST_2_F: case KERNEL_MEANDIST_2_M: case KERNEL_MEANDIST_2: { return val >= 0.0; // is a distance break; } - case KERNEL_PROBABILITY_F: case KERNEL_PROBABILITY_M: + case KERNEL_PROBABILITY_F: case KERNEL_PROBABILITY_M: case KERNEL_PROBABILITY: { return val >= 0.0 && val <= 1.0; break; From 9e81c82e9f1da1bcc4823ba41cdaadd9158e4d1a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 27 May 2024 14:41:37 +0100 Subject: [PATCH 126/332] refactor to lift ambiguities over which trait set/get are called --- Individual.cpp | 44 ++++++++++++++------------- Individual.h | 16 +++++----- Model.cpp | 81 +++++++++++++------------------------------------- Population.cpp | 42 +++++++++++++------------- Species.cpp | 38 +++++++++++------------ Species.h | 22 +++++++------- 6 files changed, 104 insertions(+), 139 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index e2ae7e0..452ea0b 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -244,13 +244,13 @@ void Individual::setDispersalPhenotypes(Species* pSpecies, int resol) { void Individual::setTransferTraits(Species* pSpecies, transferRules trfr, int resol) { if (trfr.usesMovtProc) { if (trfr.moveType == 1) { - setSMSTraits(pSpecies); + setIndSMSTraits(pSpecies); } else - setCRWTraits(pSpecies); + setIndCRWTraits(pSpecies); } else - setKernelTraits(pSpecies, trfr.sexDep, trfr.twinKern, resol); + setIndKernelTraits(pSpecies, trfr.sexDep, trfr.twinKern, resol); } void Individual::setSettlementTraits(Species* pSpecies, bool sexDep) { @@ -403,14 +403,17 @@ void Individual::setEmigTraits(Species* pSpecies, bool sexDep, bool densityDep) pEmigTraits->d0 = e.d0; pEmigTraits->alpha = e.alpha; pEmigTraits->beta = e.beta; + + // Below must never trigger, phenotype is bounded in express() if (pEmigTraits->d0 < 0.0) throw runtime_error("d0 value has become negative."); if (pEmigTraits->d0 > 1.0) throw runtime_error("d0 value has exceeded 1."); return; } // Get phenotypic emigration traits -emigTraits Individual::getEmigTraits(void) { - emigTraits e; e.d0 = e.alpha = e.beta = 0.0; +emigTraits Individual::getIndEmigTraits(void) { + emigTraits e; + e.d0 = e.alpha = e.beta = 0.0; if (pEmigTraits != 0) { e.d0 = pEmigTraits->d0; e.alpha = pEmigTraits->alpha; @@ -419,9 +422,10 @@ emigTraits Individual::getEmigTraits(void) { return e; } // Set phenotypic transfer by kernel traits -void Individual::setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel, int resol) { +void Individual::setIndKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel, int resol) { - trfrKernelParams k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; + trfrKernelParams k; + k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; if (sexDep) { if (this->sex == MAL) { @@ -475,7 +479,7 @@ void Individual::setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel // Get phenotypic emigration traits -trfrKernelParams Individual::getKernTraits(void) { +trfrKernelParams Individual::getIndKernTraits(void) { trfrKernelParams k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; if (pTrfrData != 0) { @@ -489,9 +493,9 @@ trfrKernelParams Individual::getKernTraits(void) { return k; } -void Individual::setSMSTraits(Species* pSpecies) { +void Individual::setIndSMSTraits(Species* pSpecies) { - trfrSMSTraits s = pSpecies->getSMSTraits(); + trfrSMSTraits s = pSpecies->getSpSMSTraits(); double dp, gb, alphaDB, betaDB; dp = gb = alphaDB = betaDB = 0.0; @@ -525,7 +529,7 @@ trfrData* Individual::getTrfrData(void) { } // Get phenotypic transfer by SMS traits -trfrSMSTraits Individual::getSMSTraits(void) { +trfrSMSTraits Individual::getIndSMSTraits(void) { trfrSMSTraits s; s.dp = s.gb = s.alphaDB = 1.0; s.betaDB = 1; if (pTrfrData != 0) { @@ -541,7 +545,7 @@ trfrSMSTraits Individual::getSMSTraits(void) { // Set phenotypic transfer by CRW traits -void Individual::setCRWTraits(Species* pSpecies) { +void Individual::setIndCRWTraits(Species* pSpecies) { trfrCRWTraits c; c.stepLength = c.rho = 0.0; c.stepLength = getTrait(CRW_STEPLENGTH)->express(); @@ -557,7 +561,7 @@ void Individual::setCRWTraits(Species* pSpecies) { } // Get phenotypic transfer by CRW traits -trfrCRWTraits Individual::getCRWTraits(void) { +trfrCRWTraits Individual::getIndCRWTraits(void) { trfrCRWTraits c; c.stepLength = c.rho = 0.0; if (pTrfrData != 0) { @@ -570,7 +574,7 @@ trfrCRWTraits Individual::getCRWTraits(void) { } // Get phenotypic settlement traits -settleTraits Individual::getSettTraits(void) { +settleTraits Individual::getIndSettTraits(void) { settleTraits s; s.s0 = s.alpha = s.beta = 0.0; if (pSettleTraits != 0) { s.s0 = pSettleTraits->s0; @@ -667,18 +671,18 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, else { // get kernel parameters for the species if (trfr.sexDep) { if (trfr.stgDep) { - kern = pSpecies->getKernTraits(stage, sex); + kern = pSpecies->getSpKernTraits(stage, sex); } else { - kern = pSpecies->getKernTraits(0, sex); + kern = pSpecies->getSpKernTraits(0, sex); } } else { if (trfr.stgDep) { - kern = pSpecies->getKernTraits(stage, 0); + kern = pSpecies->getSpKernTraits(stage, 0); } else { - kern = pSpecies->getKernTraits(0, 0); + kern = pSpecies->getSpKernTraits(0, 0); } } } @@ -846,7 +850,7 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, simParams sim = paramsSim->getSim(); transferRules trfr = pSpecies->getTransferRules(); - trfrCRWTraits movt = pSpecies->getCRWTraits(); + trfrCRWTraits movt = pSpecies->getSpCRWTraits(); settleSteps settsteps = pSpecies->getSteps(stage, sex); patch = pCurrCell->getPatch(); @@ -1049,7 +1053,7 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, } landData land = pLand->getLandData(); - trfrSMSTraits movt = pSpecies->getSMSTraits(); + trfrSMSTraits movt = pSpecies->getSpSMSTraits(); current = pCurrCell->getLocn(); //get weights for directional persistence.... diff --git a/Individual.h b/Individual.h index 9d79b71..d56102f 100644 --- a/Individual.h +++ b/Individual.h @@ -264,23 +264,23 @@ class Individual { void setEmigTraits(Species* pSpecies, bool sexDep, bool densityDep); void setTransferTraits(Species* pSpecies, transferRules trfr, int resol); - emigTraits getEmigTraits(void); // Get phenotypic emigration traits + emigTraits getIndEmigTraits(void); // Get phenotypic emigration traits - void setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel, int resol); + void setIndKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel, int resol); - trfrKernelParams getKernTraits(void); // Get phenotypic transfer by kernel traits + trfrKernelParams getIndKernTraits(void); // Get phenotypic transfer by kernel traits - void setSMSTraits(Species* pSpecies); + void setIndSMSTraits(Species* pSpecies); - trfrSMSTraits getSMSTraits(void); // Get phenotypic transfer by SMS traits + trfrSMSTraits getIndSMSTraits(void); // Get phenotypic transfer by SMS traits - void setCRWTraits(Species* pSpecies); + void setIndCRWTraits(Species* pSpecies); - trfrCRWTraits getCRWTraits(void); // Get phenotypic transfer by CRW traits + trfrCRWTraits getIndCRWTraits(void); // Get phenotypic transfer by CRW traits void setSettlementTraits(Species* pSpecies, bool sexDep); - settleTraits getSettTraits(void); // Get phenotypic settlement traits + settleTraits getIndSettTraits(void); // Get phenotypic settlement traits trfrData* getTrfrData(void); void setEmigTraits(const emigTraits& emig); diff --git a/Model.cpp b/Model.cpp index 05c5e80..21c78db 100644 --- a/Model.cpp +++ b/Model.cpp @@ -1073,45 +1073,6 @@ void OutParameters(Landscape* pLandscape) outPar << "females " << i << ":\t" << pSpecies->getSurv(i, 0) << endl; } } - /* - #if RSDEBUG - outPar << endl << "TRANSITION MATRIX AS ENTERED:" << endl; - if (batchMode) { - DEBUGLOG << "outParameters(): matrix = " << matrix - << " matrix[1][1] = " << matrix[1][1] - << endl; - if (dem.repType == 2) { - nrows = sstruct.nStages*2-1; ncols = sstruct.nStages*2; - } - else { - nrows = sstruct.nStages; ncols = sstruct.nStages; - } - for (int i = 0; i < nrows; i++) { - for (int j = 0; j < ncols; j++) { - outPar << matrix[j][i] << "\t"; - } - outPar << endl; - } - } - #if VCL - else { - - // NOTE: TO PREVENT COMPILING FOR BATCH MODE, THIS CODE NEEDS TO BE INCLUDED IN COMPILER - // CONDITIONAL BLOCK AS SHOWN - - // outPar << "Row count: " << frmSpecies->transMatrix->RowCount << endl; - // outPar << "Col count: " << frmSpecies->transMatrix->ColCount << endl; - for (int i = 1; i < frmSpecies->transMatrix->RowCount; i++) { - for (int j = 1; j < frmSpecies->transMatrix->ColCount; j++) { - outPar << frmSpecies->transMatrix->Cells[j][i].ToDouble() << "\t"; - } - outPar << endl; - } - } - #endif - outPar << endl; - #endif - */ outPar << "SCHEDULING OF SURVIVAL: "; switch (sstruct.survival) { @@ -1236,8 +1197,8 @@ void OutParameters(Landscape* pLandscape) outPar << indvar << "no" << endl; for (int i = 0; i < sstruct.nStages; i++) { outPar << "stage " << i << ":" << endl; - ep0 = pSpecies->getEmigTraits(i, 0); - ep1 = pSpecies->getEmigTraits(i, 1); + ep0 = pSpecies->getSpEmigTraits(i, 0); + ep1 = pSpecies->getSpEmigTraits(i, 1); outPar << "D0: females " << ep0.d0 << " males " << ep1.d0 << endl; outPar << "alpha: females " << ep0.alpha << " males " << ep1.alpha << endl; outPar << "beta: females " << ep0.beta << " males " << ep1.beta << endl; @@ -1245,8 +1206,8 @@ void OutParameters(Landscape* pLandscape) } else { // !emig.stgDep outPar << stgdept << "no" << endl; - ep0 = pSpecies->getEmigTraits(0, 0); - ep1 = pSpecies->getEmigTraits(0, 1); + ep0 = pSpecies->getSpEmigTraits(0, 0); + ep1 = pSpecies->getSpEmigTraits(0, 1); outPar << "D0: females " << ep0.d0 << " males " << ep1.d0 << endl; outPar << "alpha: females " << ep0.alpha << " males " << ep1.alpha << endl; outPar << "beta: females " << ep0.beta << " males " << ep1.beta << endl; @@ -1258,14 +1219,14 @@ void OutParameters(Landscape* pLandscape) outPar << stgdept << "yes" << endl; outPar << indvar << "no" << endl; for (int i = 0; i < sstruct.nStages; i++) { - ep0 = pSpecies->getEmigTraits(i, 0); + ep0 = pSpecies->getSpEmigTraits(i, 0); outPar << "stage " << i << ": \t" << "D0: " << ep0.d0; outPar << " \talpha: " << ep0.alpha << " \tbeta: " << ep0.beta << endl; } } else { // !emig.stgDep outPar << stgdept << "no" << endl; - ep0 = pSpecies->getEmigTraits(0, 0); + ep0 = pSpecies->getSpEmigTraits(0, 0); outPar << "D0: " << ep0.d0 << endl; outPar << "alpha: " << ep0.alpha << endl; outPar << "beta: " << ep0.beta << endl; @@ -1289,13 +1250,13 @@ void OutParameters(Landscape* pLandscape) outPar << indvar << "no" << endl; for (int i = 0; i < sstruct.nStages; i++) { outPar << "stage " << i << ": \t" << "EMIGRATION PROB.: \tfemales " - << pSpecies->getEmigD0(i, 0) << " \tmales " << pSpecies->getEmigD0(i, 1) << endl; + << pSpecies->getSpEmigD0(i, 0) << " \tmales " << pSpecies->getSpEmigD0(i, 1) << endl; } } else { // !emig.stgDep outPar << stgdept << "no" << endl; - outPar << "EMIGRATION PROB.: \tfemales " << pSpecies->getEmigD0(0, 0) - << "\t males " << pSpecies->getEmigD0(0, 1) << endl; + outPar << "EMIGRATION PROB.: \tfemales " << pSpecies->getSpEmigD0(0, 0) + << "\t males " << pSpecies->getSpEmigD0(0, 1) << endl; } } else { // !emig.sexDep @@ -1305,12 +1266,12 @@ void OutParameters(Landscape* pLandscape) outPar << indvar << "no" << endl; for (int i = 0; i < sstruct.nStages; i++) { outPar << "stage " << i << ": \t" << "EMIGRATION PROB.: " - << pSpecies->getEmigD0(i, 0) << endl; + << pSpecies->getSpEmigD0(i, 0) << endl; } } else { // !emig.stgDep outPar << stgdept << "no" << endl; - outPar << "EMIGRATION PROB.:\t" << pSpecies->getEmigD0(0, 0) << endl; + outPar << "EMIGRATION PROB.:\t" << pSpecies->getSpEmigD0(0, 0) << endl; } } } @@ -1322,7 +1283,7 @@ void OutParameters(Landscape* pLandscape) if (trfr.usesMovtProc) { bool straightenPath; if (trfr.moveType == 1) { // SMS - trfrSMSTraits move = pSpecies->getSMSTraits(); + trfrSMSTraits move = pSpecies->getSpSMSTraits(); straightenPath = move.straightenPath; if (trfr.costMap) { outPar << "SMS\tcosts from imported cost map" << endl; @@ -1359,7 +1320,7 @@ void OutParameters(Landscape* pLandscape) outPar << indvar << "no " << endl; } else { // CRW - trfrCRWTraits move = pSpecies->getCRWTraits(); + trfrCRWTraits move = pSpecies->getSpCRWTraits(); straightenPath = move.straightenPath; outPar << "CRW" << endl; string lgth = "STEP LENGTH (m) "; @@ -1387,7 +1348,7 @@ void OutParameters(Landscape* pLandscape) } else { - trfrCRWTraits move = pSpecies->getCRWTraits(); + trfrCRWTraits move = pSpecies->getSpCRWTraits(); outPar << "constant " << move.stepMort << endl; } } // end of movement process @@ -1406,8 +1367,8 @@ void OutParameters(Landscape* pLandscape) outPar << indvar << "no" << endl; for (int i = 0; i < sstruct.nStages; i++) { outPar << "stage " << i << ":" << endl; - kern0 = pSpecies->getKernTraits(i, 0); - kern1 = pSpecies->getKernTraits(i, 1); + kern0 = pSpecies->getSpKernTraits(i, 0); + kern1 = pSpecies->getSpKernTraits(i, 1); outPar << meandist << " I: \tfemales " << kern0.meanDist1 << " \tmales " << kern1.meanDist1 << endl; if (trfr.twinKern) { @@ -1418,8 +1379,8 @@ void OutParameters(Landscape* pLandscape) } else { // !trfr.stgDep outPar << stgdept << "no" << endl; - kern0 = pSpecies->getKernTraits(0, 0); - kern1 = pSpecies->getKernTraits(0, 1); + kern0 = pSpecies->getSpKernTraits(0, 0); + kern1 = pSpecies->getSpKernTraits(0, 1); outPar << meandist << " I: \tfemales " << kern0.meanDist1 << " \tmales " << kern1.meanDist1 << endl; if (trfr.twinKern) { @@ -1434,7 +1395,7 @@ void OutParameters(Landscape* pLandscape) outPar << stgdept << "yes" << endl; outPar << indvar << "no" << endl; for (int i = 0; i < sstruct.nStages; i++) { - kern0 = pSpecies->getKernTraits(i, 0); + kern0 = pSpecies->getSpKernTraits(i, 0); outPar << "stage " << i << ": \t" << meandist << " I: " << kern0.meanDist1; if (trfr.twinKern) { @@ -1446,7 +1407,7 @@ void OutParameters(Landscape* pLandscape) } else { // !trfr.stgDep outPar << stgdept << "no" << endl; - kern0 = pSpecies->getKernTraits(0, 0); + kern0 = pSpecies->getSpKernTraits(0, 0); outPar << meandist << " I: \t" << kern0.meanDist1 << endl; if (trfr.twinKern) { @@ -1547,7 +1508,7 @@ void OutParameters(Landscape* pLandscape) outPar << "find a suitable cell/patch "; srules = pSpecies->getSettRules(i, sx); if (srules.densDep) { - settleDD = pSpecies->getSettTraits(i, sx); + settleDD = pSpecies->getSpSettTraits(i, sx); outPar << "+ density dependence "; if (srules.findMate) outPar << plusmating; outPar << endl; diff --git a/Population.cpp b/Population.cpp index 90f3dca..fd42127 100644 --- a/Population.cpp +++ b/Population.cpp @@ -240,7 +240,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { ts.ninds[g] += 1; // emigration traits - emigTraits e = inds[iInd]->getEmigTraits(); + emigTraits e = inds[iInd]->getIndEmigTraits(); if (emig.sexDep) g = sex; else g = 0; ts.sumD0[g] += e.d0; @@ -257,7 +257,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { case 1: // SMS { - trfrSMSTraits sms = inds[iInd]->getSMSTraits(); + trfrSMSTraits sms = inds[iInd]->getIndSMSTraits(); g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT ts.sumDP[g] += sms.dp; ts.ssqDP[g] += sms.dp * sms.dp; @@ -271,7 +271,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { } case 2: { - trfrCRWTraits c = inds[iInd]->getCRWTraits(); + trfrCRWTraits c = inds[iInd]->getIndCRWTraits(); g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT ts.sumStepL[g] += c.stepLength; ts.ssqStepL[g] += c.stepLength * c.stepLength; @@ -285,7 +285,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { } } else { - trfrKernelParams k = inds[iInd]->getKernTraits(); + trfrKernelParams k = inds[iInd]->getIndKernTraits(); if (trfr.sexDep) g = sex; else g = 0; ts.sumDist1[g] += k.meanDist1; @@ -296,7 +296,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { ts.ssqProp1[g] += k.probKern1 * k.probKern1; } // settlement traits - settleTraits s = inds[iInd]->getSettTraits(); + settleTraits s = inds[iInd]->getIndSettTraits(); if (sett.sexDep) g = sex; else g = 0; // g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT @@ -901,18 +901,18 @@ void Population::emigration(float localK) if (emig.densDep) { if (emig.sexDep) { if (emig.stgDep) { - eparams = pSpecies->getEmigTraits(stg, sex); + eparams = pSpecies->getSpEmigTraits(stg, sex); } else { - eparams = pSpecies->getEmigTraits(0, sex); + eparams = pSpecies->getSpEmigTraits(0, sex); } } else { // !emig.sexDep if (emig.stgDep) { - eparams = pSpecies->getEmigTraits(stg, 0); + eparams = pSpecies->getSpEmigTraits(stg, 0); } else { - eparams = pSpecies->getEmigTraits(0, 0); + eparams = pSpecies->getSpEmigTraits(0, 0); } } Pemig[stg][sex] = eparams.d0 / (1.0 + exp(-(NK - eparams.beta) * eparams.alpha)); @@ -920,18 +920,18 @@ void Population::emigration(float localK) else { // density-independent if (emig.sexDep) { if (emig.stgDep) { - Pemig[stg][sex] = pSpecies->getEmigD0(stg, sex); + Pemig[stg][sex] = pSpecies->getSpEmigD0(stg, sex); } else { // !emig.stgDep - Pemig[stg][sex] = pSpecies->getEmigD0(0, sex); + Pemig[stg][sex] = pSpecies->getSpEmigD0(0, sex); } } else { // !emig.sexDep if (emig.stgDep) { - Pemig[stg][sex] = pSpecies->getEmigD0(stg, 0); + Pemig[stg][sex] = pSpecies->getSpEmigD0(stg, 0); } else { // !emig.stgDep - Pemig[stg][sex] = pSpecies->getEmigD0(0, 0); + Pemig[stg][sex] = pSpecies->getSpEmigD0(0, 0); } } } @@ -948,7 +948,7 @@ void Population::emigration(float localK) Pdisp = 0.0; } else { // non-structured or individual is in emigration stage - eparams = inds[i]->getEmigTraits(); + eparams = inds[i]->getIndEmigTraits(); if (emig.densDep) { // density-dependent NK = (float)totalPop() / localK; Pdisp = eparams.d0 / (1.0 + exp(-(NK - eparams.beta) * eparams.alpha)); @@ -1179,8 +1179,8 @@ int Population::transfer(Landscape* pLandscape, short landIx) } if (localK > 0.0) { // make settlement decision - if (settletype.indVar) settDD = inds[i]->getSettTraits(); - else settDD = pSpecies->getSettTraits(ind.stage, ind.sex); + if (settletype.indVar) settDD = inds[i]->getIndSettTraits(); + else settDD = pSpecies->getSpSettTraits(ind.stage, ind.sex); settprob = settDD.s0 / (1.0 + exp(-(popsize / localK - (double)settDD.beta) * (double)settDD.alpha)); if (pRandom->Bernoulli(settprob)) { // settlement allowed @@ -1869,7 +1869,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, if (pSpecies->getNbGenLoadTraits() > 0) outInds << "\t" << inds[i]->getGeneticFitness(); if (emig.indVar) { - emigTraits e = inds[i]->getEmigTraits(); + emigTraits e = inds[i]->getIndEmigTraits(); if (emig.densDep) { outInds << "\t" << e.d0 << "\t" << e.alpha << "\t" << e.beta; } @@ -1880,12 +1880,12 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, if (trfr.indVar) { if (trfr.usesMovtProc) { if (trfr.moveType == 1) { // SMS - trfrSMSTraits s = inds[i]->getSMSTraits(); + trfrSMSTraits s = inds[i]->getIndSMSTraits(); outInds << "\t" << s.dp << "\t" << s.gb; outInds << "\t" << s.alphaDB << "\t" << s.betaDB; } // end of SMS if (trfr.moveType == 2) { // CRW - trfrCRWTraits c = inds[i]->getCRWTraits(); + trfrCRWTraits c = inds[i]->getIndCRWTraits(); outInds << "\t" << c.stepLength << "\t" << c.rho; #if RSDEBUG //DEBUGLOG << "Population::outIndividual():" @@ -1896,7 +1896,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, } // end of CRW } else { // kernel - trfrKernelParams k = inds[i]->getKernTraits(); + trfrKernelParams k = inds[i]->getIndKernTraits(); if (trfr.twinKern) { outInds << "\t" << k.meanDist1 << "\t" << k.meanDist2 << "\t" << k.probKern1; @@ -1908,7 +1908,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, } if (sett.indVar) { - settleTraits s = inds[i]->getSettTraits(); + settleTraits s = inds[i]->getIndSettTraits(); outInds << "\t" << s.s0 << "\t" << s.alpha << "\t" << s.beta; } diff --git a/Species.cpp b/Species.cpp index 9098438..55dc8ed 100644 --- a/Species.cpp +++ b/Species.cpp @@ -501,7 +501,7 @@ emigRules Species::getEmigRules(void) { return e; } -void Species::setEmigTraits(const short stg, const short sex, const emigTraits e) { +void Species::setSpEmigTraits(const short stg, const short sex, const emigTraits e) { if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { if (e.d0 >= 0.0 && e.d0 <= 1.0) d0[stg][sex] = e.d0; alphaEmig[stg][sex] = e.alpha; @@ -509,7 +509,7 @@ void Species::setEmigTraits(const short stg, const short sex, const emigTraits e } } -emigTraits Species::getEmigTraits(short stg, short sex) { +emigTraits Species::getSpEmigTraits(short stg, short sex) { emigTraits e; if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { e.d0 = d0[stg][sex]; @@ -522,7 +522,7 @@ emigTraits Species::getEmigTraits(short stg, short sex) { return e; } -float Species::getEmigD0(short stg, short sex) { +float Species::getSpEmigD0(short stg, short sex) { if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { return d0[stg][sex]; } @@ -564,7 +564,7 @@ void Species::setFullKernel(bool k) { bool Species::useFullKernel(void) { return fullKernel; } -void Species::setKernTraits(const short stg, const short sex, +void Species::setSpKernTraits(const short stg, const short sex, const trfrKernelParams k, const int resol) { if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { @@ -574,7 +574,7 @@ void Species::setKernTraits(const short stg, const short sex, } } -trfrKernelParams Species::getKernTraits(short stg, short sex) { +trfrKernelParams Species::getSpKernTraits(short stg, short sex) { trfrKernelParams k; if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { k.meanDist1 = meanDist1[stg][sex]; @@ -599,7 +599,7 @@ trfrMortParams Species::getMortParams(void) { return m; } -void Species::setMovtTraits(const trfrMovtParams m) { +void Species::setSpMovtTraits(const trfrMovtParams m) { if (m.pr >= 1) pr = m.pr; if (m.prMethod >= 1 && m.prMethod <= 3) prMethod = m.prMethod; if (m.memSize >= 1 && m.memSize <= 14) memSize = m.memSize; @@ -614,7 +614,7 @@ void Species::setMovtTraits(const trfrMovtParams m) { straightenPath = m.straightenPath; } -trfrMovtParams Species::getMovtTraits(void) { +trfrMovtParams Species::getSpMovtTraits(void) { trfrMovtParams m; m.pr = pr; m.prMethod = prMethod; m.memSize = memSize; m.goalType = goalType; m.dp = dp; m.gb = gb; m.alphaDB = alphaDB; m.betaDB = betaDB; @@ -622,14 +622,14 @@ trfrMovtParams Species::getMovtTraits(void) { return m; } -trfrCRWTraits Species::getCRWTraits(void) { +trfrCRWTraits Species::getSpCRWTraits(void) { trfrCRWTraits m; m.stepMort = stepMort; m.stepLength = stepLength; m.rho = rho; m.straightenPath = straightenPath; return m; } -trfrSMSTraits Species::getSMSTraits(void) { +trfrSMSTraits Species::getSpSMSTraits(void) { trfrSMSTraits m; m.pr = pr; m.prMethod = prMethod; m.memSize = memSize; m.goalType = goalType; m.dp = dp; m.gb = gb; m.alphaDB = alphaDB; m.betaDB = betaDB; m.stepMort = stepMort; @@ -744,13 +744,22 @@ settleSteps Species::getSteps(short stg, short sex) { return s; } -void Species::setSettTraits(const short stg, const short sex, const settleTraits dd) { +void Species::setSpSettTraits(const short stg, const short sex, const settleTraits dd) { if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { if (dd.s0 > 0.0 && dd.s0 <= 1.0) s0[stg][sex] = dd.s0; alphaS[stg][sex] = dd.alpha; betaS[stg][sex] = dd.beta; } } +settleTraits Species::getSpSettTraits(short stg, short sex) { + settleTraits dd; + if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + dd.s0 = s0[stg][sex]; dd.alpha = alphaS[stg][sex]; dd.beta = betaS[stg][sex]; + } + else { dd.s0 = 1.0; dd.alpha = dd.beta = 0.0; } + return dd; +} + void Species::setGeneticParameters(const std::set& chromosomeEnds, const int genomeSize, const float recombinationRate, const std::set& samplePatchList, const string nIndsToSample, const std::set& stagesToSampleFrom, int nPatchesToSampleFrom) { @@ -768,15 +777,6 @@ void Species::setSamplePatchList(const set& samplePatchList) { this->samplePatchList = samplePatchList; } -settleTraits Species::getSettTraits(short stg, short sex) { - settleTraits dd; - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { - dd.s0 = s0[stg][sex]; dd.alpha = alphaS[stg][sex]; dd.beta = betaS[stg][sex]; - } - else { dd.s0 = 1.0; dd.alpha = dd.beta = 0.0; } - return dd; -} - //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- diff --git a/Species.h b/Species.h index 5beb9c7..59634a9 100644 --- a/Species.h +++ b/Species.h @@ -315,16 +315,16 @@ class Species { const emigRules // structure holding emigration rules ); emigRules getEmigRules(void); // Get emigration rules - void setEmigTraits( // Set emigration trait parameters + void setSpEmigTraits( // Set emigration trait parameters const short, // stage const short, // sex const emigTraits // structure holding emigration trait parameters ); - emigTraits getEmigTraits( // Get emigration trait parameters + emigTraits getSpEmigTraits( // Get emigration trait parameters short, // stage short // sex ); - float getEmigD0( // Get (maximum) emigration probability + float getSpEmigD0( // Get (maximum) emigration probability short, // stage short // sex ); @@ -339,13 +339,13 @@ class Species { bool // fullKernel value ); bool useFullKernel(void); - void setKernTraits( // Set transfer by kernel parameters + void setSpKernTraits( // Set transfer by kernel parameters const short, // stage const short, // sex const trfrKernelParams, // structure holding transfer by kernel parameters const int // Landscape resolution ); - trfrKernelParams getKernTraits( // Get transfer by kernel parameters + trfrKernelParams getSpKernTraits( // Get transfer by kernel parameters short, // stage short // sex ); @@ -353,12 +353,12 @@ class Species { const trfrMortParams // structure holding transfer mortality parameters ); trfrMortParams getMortParams(void); // Get transfer mortality parameters - void setMovtTraits( // Set transfer movement model parameters + void setSpMovtTraits( // Set transfer movement model parameters const trfrMovtParams // structure holding transfer movement model parameters ); - trfrMovtParams getMovtTraits(void); // Get transfer movement model traits - trfrCRWTraits getCRWTraits(void); // Get CRW traits - trfrSMSTraits getSMSTraits(void); // Get SMS traits + trfrMovtParams getSpMovtTraits(void); // Get transfer movement model traits + trfrCRWTraits getSpCRWTraits(void); // Get CRW traits + trfrSMSTraits getSpSMSTraits(void); // Get SMS traits // Return dimension of habitat-dependent step mortality and costs matrices short getMovtHabDim(void); void createHabCostMort( // Create habitat-dependent costs and mortality matrices @@ -404,12 +404,12 @@ class Species { short, // stage short // sex ); - void setSettTraits( // Set settlement density dependence traits + void setSpSettTraits( // Set settlement density dependence traits const short, // stage const short, // sex const settleTraits // structure holding density dependence traits ); - settleTraits getSettTraits( // Get settlement density dependence traits + settleTraits getSpSettTraits( // Get settlement density dependence traits short, // stage short // sex ); From 52821d38579cb4ef7c538604f0a7dd6b053cb601 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 27 May 2024 14:58:21 +0100 Subject: [PATCH 127/332] make global variables explicit --- Community.cpp | 12 ++++----- Individual.cpp | 4 +-- Model.cpp | 14 +++++----- Parameters.cpp | 6 ++--- Parameters.h | 13 +++++---- Patch.cpp | 8 +++--- Patch.h | 2 +- Population.cpp | 60 +++++++++++++++++++++--------------------- Population.h | 68 ++++++++++++++++++++++++------------------------ Species.cpp | 62 +++++++++++++++++++++---------------------- Species.h | 40 ++++++++++++++-------------- SubCommunity.cpp | 8 +++--- 12 files changed, 148 insertions(+), 149 deletions(-) diff --git a/Community.cpp b/Community.cpp index 89fa5a6..c4a3b14 100644 --- a/Community.cpp +++ b/Community.cpp @@ -828,7 +828,7 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) traitsums scts; // sub-community traits int ngenes, popsize; - for (int i = 0; i < maxNbSexes; i++) { + for (int i = 0; i < gMaxNbSexes; i++) { ts.ninds[i] = 0; ts.sumD0[i] = ts.ssqD0[i] = 0.0; ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; @@ -846,7 +846,7 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) int nsubcomms = (int)subComms.size(); for (int i = 0; i < nsubcomms; i++) { // all sub-communities (incl. matrix) scts = subComms[i]->outTraits(pLandscape, rep, yr, gen, true); - for (int j = 0; j < maxNbSexes; j++) { + for (int j = 0; j < gMaxNbSexes; j++) { ts.ninds[j] += scts.ninds[j]; ts.sumD0[j] += scts.sumD0[j]; ts.ssqD0[j] += scts.ssqD0[j]; ts.sumAlpha[j] += scts.sumAlpha[j]; ts.ssqAlpha[j] += scts.ssqAlpha[j]; @@ -1187,7 +1187,7 @@ void Community::outTraits(Species* pSpecies, int rep, int yr, int gen) // create array of traits means, etc., one for each row ts = new traitsums[land.dimY]; for (int y = 0; y < land.dimY; y++) { - for (int i = 0; i < maxNbSexes; i++) { + for (int i = 0; i < gMaxNbSexes; i++) { ts[y].ninds[i] = 0; ts[y].sumD0[i] = ts[y].ssqD0[i] = 0.0; ts[y].sumAlpha[i] = ts[y].ssqAlpha[i] = 0.0; @@ -1216,7 +1216,7 @@ void Community::outTraits(Species* pSpecies, int rep, int yr, int gen) int y = loc.y; if (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0) { - for (int s = 0; s < maxNbSexes; s++) { + for (int s = 0; s < gMaxNbSexes; s++) { ts[y].ninds[s] += sctraits.ninds[s]; ts[y].sumD0[s] += sctraits.sumD0[s]; ts[y].ssqD0[s] += sctraits.ssqD0[s]; ts[y].sumAlpha[s] += sctraits.sumAlpha[s]; ts[y].ssqAlpha[s] += sctraits.ssqAlpha[s]; @@ -1391,7 +1391,7 @@ void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int } if (pSpecies->getNbGenLoadTraits() > 0) { - if (maxNbSexes > 1) { + if (gMaxNbSexes > 1) { if (ts.ninds[0] > 0) mn = ts.sumGeneticFitness[0] / (double)ts.ninds[0]; else mn = 0.0; if (ts.ninds[0] > 1) sd = ts.ssqGeneticFitness[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; @@ -1500,7 +1500,7 @@ bool Community::outTraitsRowsHeaders(Species* pSpecies, int landNr) { } if (pSpecies->getNbGenLoadTraits() > 0) { - if (maxNbSexes > 1) { + if (gMaxNbSexes > 1) { outtraitsrows << "\tF_meanProbViable\tF_stdProbViable\tM_meanProbViable\tM_stdProbViable"; } else diff --git a/Individual.cpp b/Individual.cpp index 452ea0b..28555b1 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1384,8 +1384,8 @@ array3x3f Individual::getHabMatrix(Landscape* pLand, Species* pSpecies, Cell* pCell; landData land = pLand->getLandData(); - if (absorbing) nodatacost = absorbingNoDataCost; - else nodatacost = noDataCost; + if (absorbing) nodatacost = gAbsorbingNoDataCost; + else nodatacost = gNoDataCost; for (int x2 = -1; x2 < 2; x2++) { // index of relative move in x direction for (int y2 = -1; y2 < 2; y2++) { // index of relative move in x direction diff --git a/Model.cpp b/Model.cpp index 21c78db..b309e2e 100644 --- a/Model.cpp +++ b/Model.cpp @@ -1088,7 +1088,7 @@ void OutParameters(Landscape* pLandscape) } int mSize; // index for weights matrices - if (dem.repType == 2) mSize = sstruct.nStages * maxNbSexes; + if (dem.repType == 2) mSize = sstruct.nStages * gMaxNbSexes; else mSize = sstruct.nStages; outPar << "DENSITY-DEPENDENCE IN FECUNDITY:\t"; @@ -1098,8 +1098,8 @@ void OutParameters(Landscape* pLandscape) outPar << "STAGE'S WEIGHTS:" << endl; for (int i = 0; i < mSize; i++) { if (dem.repType == 2) { - outPar << "stage " << i / maxNbSexes << " "; - if (i % maxNbSexes == 0) outPar << "males : \t"; + outPar << "stage " << i / gMaxNbSexes << " "; + if (i % gMaxNbSexes == 0) outPar << "males : \t"; else outPar << "females: \t"; } else outPar << "stage " << i << ": \t"; @@ -1120,8 +1120,8 @@ void OutParameters(Landscape* pLandscape) outPar << "STAGE'S WEIGHTS:" << endl; for (int i = 0; i < mSize; i++) { if (dem.repType == 2) { - outPar << "stage " << i / maxNbSexes << " "; - if (i % maxNbSexes == 0) outPar << "males : \t"; + outPar << "stage " << i / gMaxNbSexes << " "; + if (i % gMaxNbSexes == 0) outPar << "males : \t"; else outPar << "females: \t"; } else outPar << "stage " << i << ": \t"; @@ -1140,8 +1140,8 @@ void OutParameters(Landscape* pLandscape) outPar << "STAGE'S WEIGHTS:" << endl; for (int i = 0; i < mSize; i++) { if (dem.repType == 2) { - outPar << "stage " << i / maxNbSexes << " "; - if (i % maxNbSexes == 0) outPar << "males : \t"; + outPar << "stage " << i / gMaxNbSexes << " "; + if (i % gMaxNbSexes == 0) outPar << "males : \t"; else outPar << "females: \t"; } else outPar << "stage " << i << ": \t"; diff --git a/Parameters.cpp b/Parameters.cpp index c0faafb..0c37dab 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -128,7 +128,7 @@ paramInit::paramInit(void) { minSeedX = 0; maxSeedX = 99999999; minSeedY = 0; maxSeedY = 99999999; nSeedPatches = 1; nSpDistPatches = 1; indsFile = "NULL"; - for (int i = 0; i < maxNbStages; i++) { + for (int i = 0; i < gMaxNbStages; i++) { initProp[i] = 0.0; } } @@ -176,12 +176,12 @@ initParams paramInit::getInit(void) { } void paramInit::setProp(short stg, float p) { - if (stg >= 0 && stg < maxNbStages && p >= 0.0 && p <= 1.0) initProp[stg] = p; + if (stg >= 0 && stg < gMaxNbStages && p >= 0.0 && p <= 1.0) initProp[stg] = p; } float paramInit::getProp(short stg) { float p = 0.0; - if (stg >= 0 && stg < maxNbStages) p = initProp[stg]; + if (stg >= 0 && stg < gMaxNbStages) p = initProp[stg]; return p; } diff --git a/Parameters.h b/Parameters.h index cfd81de..47b780a 100644 --- a/Parameters.h +++ b/Parameters.h @@ -65,13 +65,12 @@ using namespace std; #include "RSrandom.h" -constexpr int noDataCost = 100000; // cost to use in place of nodata value for SMS; -constexpr int absorbingNoDataCost = 100; // cost to use in place of nodata value for SMS; +constexpr int gNoDataCost = 100000; // cost to use in place of nodata value for SMS; +constexpr int gAbsorbingNoDataCost = 100; // cost to use in place of nodata value for SMS; // when boundaries are absorbing -constexpr int maxNbStages = 10; // maximum number of stages permitted -constexpr int maxNbSexes = 2; // maximum number of sexes permitted -constexpr int maxNbTraitsGUI = 18; // maximum number of variable traits which can be displayed - // in GUI (VCL version) +constexpr int gMaxNbStages = 10; // maximum number of stages permitted +constexpr int gMaxNbSexes = 2; // maximum number of sexes permitted + #if RS_RCPP typedef intptr_t intptr; #else @@ -305,7 +304,7 @@ class paramInit { int nSeedPatches; // no. of cells/patches to initialise int nSpDistPatches; // no. of species distribution cells to initialise string indsFile; // no. of species distribution cells to initialise - float initProp[maxNbStages]; // initial stage proportions (structured population only) + float initProp[gMaxNbStages]; // initial stage proportions (structured population only) vector initinds; // individuals to be initialised diff --git a/Patch.cpp b/Patch.cpp index 8504a57..f3f88f0 100644 --- a/Patch.cpp +++ b/Patch.cpp @@ -33,7 +33,7 @@ Patch::Patch(int seqnum, int num) xMin = yMin = 999999999; xMax = yMax = 0; x = y = 0; subCommPtr = 0; localK = 0.0; - for (int sex = 0; sex < maxNbSexes; sex++) { + for (int sex = 0; sex < gMaxNbSexes; sex++) { nTemp[sex] = 0; } changed = false; @@ -326,7 +326,7 @@ void Patch::resetPopn(void) { } void Patch::resetPossSettlers(void) { - for (int sex = 0; sex < maxNbSexes; sex++) { + for (int sex = 0; sex < gMaxNbSexes; sex++) { nTemp[sex] = 0; } } @@ -338,7 +338,7 @@ void Patch::incrPossSettler(Species* pSpecies, int sex) { // << " sex = " << sex << endl; #endif // NOTE: THE FOLLOWING OPERATION WILL NEED TO BE MADE SPECIES-SPECIFIC... - if (sex >= 0 && sex < maxNbSexes) { + if (sex >= 0 && sex < gMaxNbSexes) { nTemp[sex]++; } } @@ -350,7 +350,7 @@ int Patch::getPossSettlers(Species* pSpecies, int sex) { // << " sex = " << sex << endl; #endif // NOTE: THE FOLLOWING OPERATION WILL NEED TO BE MADE SPECIES-SPECIFIC... - if (sex >= 0 && sex < maxNbSexes) return nTemp[sex]; + if (sex >= 0 && sex < gMaxNbSexes) return nTemp[sex]; else return 0; } diff --git a/Patch.h b/Patch.h index 445dd02..1285daf 100644 --- a/Patch.h +++ b/Patch.h @@ -154,7 +154,7 @@ class Patch { float localK; // patch carrying capacity (individuals) bool changed; // NOTE: THE FOLLOWING ARRAY WILL NEED TO BE MADE SPECIES-SPECIFIC... - short nTemp[maxNbSexes]; // no. of potential settlers in each sex + short nTemp[gMaxNbSexes]; // no. of potential settlers in each sex std::vector cells; std::vector popns; diff --git a/Population.cpp b/Population.cpp index fd42127..3a302e7 100644 --- a/Population.cpp +++ b/Population.cpp @@ -77,14 +77,14 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) else { nSexes = 2; probmale = dem.propMales; } // set up population sub-totals - for (int stg = 0; stg < maxNbStages; stg++) { - for (int sex = 0; sex < maxNbSexes; sex++) { + for (int stg = 0; stg < gMaxNbStages; stg++) { + for (int sex = 0; sex < gMaxNbSexes; sex++) { nInds[stg][sex] = 0; } } // set up local copy of minimum age table - short minAge[maxNbStages][maxNbSexes]; + short minAge[gMaxNbStages][gMaxNbSexes]; for (int stg = 0; stg < nStages; stg++) { for (int sex = 0; sex < nSexes; sex++) { if (dem.stageStruct) { @@ -207,7 +207,7 @@ Population::~Population(void) { traitsums Population::getIndTraitsSums(Species* pSpecies) { int g; traitsums ts = traitsums(); - for (int sex = 0; sex < maxNbSexes; sex++) { + for (int sex = 0; sex < gMaxNbSexes; sex++) { ts.ninds[sex] = 0; ts.sumD0[sex] = ts.ssqD0[sex] = 0.0; ts.sumAlpha[sex] = ts.ssqAlpha[sex] = 0.0; @@ -307,7 +307,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { ts.sumBetaS[g] += s.beta; ts.ssqBetaS[g] += s.beta * s.beta; - if (maxNbSexes > 1) g = sex; + if (gMaxNbSexes > 1) g = sex; else g = 0; ts.sumGeneticFitness[g] += inds[iInd]->getGeneticFitness(); ts.ssqGeneticFitness[g] += inds[iInd]->getGeneticFitness() * inds[iInd]->getGeneticFitness(); @@ -559,7 +559,7 @@ void Population::reproduction(const float localK, const float envval, const int // set up local copy of species fecundity table - float fec[maxNbStages][maxNbSexes]; + float fec[gMaxNbStages][gMaxNbSexes]; for (int stg = 0; stg < sstruct.nStages; stg++) { for (int sex = 0; sex < nsexes; sex++) { if (dem.stageStruct) { @@ -873,7 +873,7 @@ vector Population::getIndividualsInStage(int stage) { void Population::emigration(float localK) { int nsexes; - double disp, Pdisp, NK; + double disp, pbDisp, NK; demogrParams dem = pSpecies->getDemogrParams(); stageParams sstruct = pSpecies->getStageParams(); emigRules emig = pSpecies->getEmigRules(); @@ -892,11 +892,11 @@ void Population::emigration(float localK) // NB - IT IS DOUBTFUL THIS CONTRIBUTES ANY SUBSTANTIAL TIME SAVING if (dem.repType == 0) nsexes = 1; else nsexes = 2; - double Pemig[maxNbStages][maxNbSexes]; + double pbEmig[gMaxNbStages][gMaxNbSexes]; for (int stg = 0; stg < sstruct.nStages; stg++) { for (int sex = 0; sex < nsexes; sex++) { - if (emig.indVar) Pemig[stg][sex] = 0.0; + if (emig.indVar) pbEmig[stg][sex] = 0.0; else { if (emig.densDep) { if (emig.sexDep) { @@ -915,23 +915,23 @@ void Population::emigration(float localK) eparams = pSpecies->getSpEmigTraits(0, 0); } } - Pemig[stg][sex] = eparams.d0 / (1.0 + exp(-(NK - eparams.beta) * eparams.alpha)); + pbEmig[stg][sex] = eparams.d0 / (1.0 + exp(-(NK - eparams.beta) * eparams.alpha)); } else { // density-independent if (emig.sexDep) { if (emig.stgDep) { - Pemig[stg][sex] = pSpecies->getSpEmigD0(stg, sex); + pbEmig[stg][sex] = pSpecies->getSpEmigD0(stg, sex); } else { // !emig.stgDep - Pemig[stg][sex] = pSpecies->getSpEmigD0(0, sex); + pbEmig[stg][sex] = pSpecies->getSpEmigD0(0, sex); } } else { // !emig.sexDep if (emig.stgDep) { - Pemig[stg][sex] = pSpecies->getSpEmigD0(stg, 0); + pbEmig[stg][sex] = pSpecies->getSpEmigD0(stg, 0); } else { // !emig.stgDep - Pemig[stg][sex] = pSpecies->getSpEmigD0(0, 0); + pbEmig[stg][sex] = pSpecies->getSpEmigD0(0, 0); } } } @@ -945,20 +945,20 @@ void Population::emigration(float localK) if (emig.indVar) { // individual variability in emigration if (dem.stageStruct && ind.stage != emig.emigStage) { // emigration may not occur - Pdisp = 0.0; + pbDisp = 0.0; } else { // non-structured or individual is in emigration stage eparams = inds[i]->getIndEmigTraits(); if (emig.densDep) { // density-dependent NK = (float)totalPop() / localK; - Pdisp = eparams.d0 / (1.0 + exp(-(NK - eparams.beta) * eparams.alpha)); + pbDisp = eparams.d0 / (1.0 + exp(-(NK - eparams.beta) * eparams.alpha)); } else { // density-independent if (emig.sexDep) { - Pdisp = Pemig[0][ind.sex] + eparams.d0; + pbDisp = pbEmig[0][ind.sex] + eparams.d0; } else { - Pdisp = Pemig[0][0] + eparams.d0; + pbDisp = pbEmig[0][0] + eparams.d0; } } } @@ -968,42 +968,42 @@ void Population::emigration(float localK) if (emig.densDep) { if (emig.sexDep) { if (emig.stgDep) { - Pdisp = Pemig[ind.stage][ind.sex]; + pbDisp = pbEmig[ind.stage][ind.sex]; } else { - Pdisp = Pemig[0][ind.sex]; + pbDisp = pbEmig[0][ind.sex]; } } else { // !emig.sexDep if (emig.stgDep) { - Pdisp = Pemig[ind.stage][0]; + pbDisp = pbEmig[ind.stage][0]; } else { - Pdisp = Pemig[0][0]; + pbDisp = pbEmig[0][0]; } } } else { // density-independent if (emig.sexDep) { if (emig.stgDep) { - Pdisp = Pemig[ind.stage][ind.sex]; + pbDisp = pbEmig[ind.stage][ind.sex]; } else { // !emig.stgDep - Pdisp = Pemig[0][ind.sex]; + pbDisp = pbEmig[0][ind.sex]; } } else { // !emig.sexDep if (emig.stgDep) { - Pdisp = Pemig[ind.stage][0]; + pbDisp = pbEmig[ind.stage][0]; } else { // !emig.stgDep - Pdisp = Pemig[0][0]; + pbDisp = pbEmig[0][0]; } } } } // end of no individual variability - disp = pRandom->Bernoulli(Pdisp); + disp = pRandom->Bernoulli(pbDisp); if (disp == 1) { // emigrant inds[i]->setStatus(1); @@ -1359,9 +1359,9 @@ void Population::survival0(float localK, short option0, short option1) // set up local copies of species development and survival tables int nsexes; if (dem.repType == 0) nsexes = 1; else nsexes = 2; - float dev[maxNbStages][maxNbSexes]; - float surv[maxNbStages][maxNbSexes]; - short minAge[maxNbStages][maxNbSexes]; + float dev[gMaxNbStages][gMaxNbSexes]; + float surv[gMaxNbStages][gMaxNbSexes]; + short minAge[gMaxNbStages][gMaxNbSexes]; for (int stg = 0; stg < sstruct.nStages; stg++) { for (int sex = 0; sex < nsexes; sex++) { if (dem.stageStruct) { diff --git a/Population.h b/Population.h index b019183..13e6538 100644 --- a/Population.h +++ b/Population.h @@ -72,39 +72,39 @@ struct zombie { Individual* pInd; }; struct traitsums { // sums of trait genes for dispersal - int ninds[maxNbSexes]; // no. of individuals - double sumD0[maxNbSexes]; // sum of maximum emigration probability - double ssqD0[maxNbSexes]; // sum of squares of maximum emigration probability - double sumAlpha[maxNbSexes]; // sum of slope of emigration dens-dep reaction norm - double ssqAlpha[maxNbSexes]; // sum of squares of slope of emigration den-dep reaction norm - double sumBeta[maxNbSexes]; // sum of inflection point of emigration reaction norm - double ssqBeta[maxNbSexes]; // sum of squares of inflection point of emigration reaction norm - double sumDist1[maxNbSexes]; // sum of kernel I mean - double ssqDist1[maxNbSexes]; // sum of squares of kernel I mean - double sumDist2[maxNbSexes]; // sum of kernel II mean - double ssqDist2[maxNbSexes]; // sum of squares of kernel II mean - double sumProp1[maxNbSexes]; // sum of propn using kernel I - double ssqProp1[maxNbSexes]; // sum of squares of propn using kernel I - double sumDP[maxNbSexes]; // sum of SMS directional persistence - double ssqDP[maxNbSexes]; // sum of squares of SMS directional persistence - double sumGB[maxNbSexes]; // sum of SMS goal bias - double ssqGB[maxNbSexes]; // sum of squares of SMS goal bias - double sumAlphaDB[maxNbSexes]; // sum of SMS dispersal bias decay rate - double ssqAlphaDB[maxNbSexes]; // sum of squares of SMS dispersal bias decay rate - double sumBetaDB[maxNbSexes]; // sum of SMS dispersal bias decay infl. pt. - double ssqBetaDB[maxNbSexes]; // sum of squares of SMS dispersal bias decay infl. pt. - double sumStepL[maxNbSexes]; // sum of CRW step length - double ssqStepL[maxNbSexes]; // sum of squares of CRW step length - double sumRho[maxNbSexes]; // sum of CRW correlation coefficient - double ssqRho[maxNbSexes]; // sum of squares of CRW correlation coefficient - double sumS0[maxNbSexes]; // sum of maximum settlement probability - double ssqS0[maxNbSexes]; // sum of squares of maximum settlement probability - double sumAlphaS[maxNbSexes]; // sum of slope of settlement den-dep reaction norm - double ssqAlphaS[maxNbSexes]; // sum of squares of slope of settlement den-dep reaction norm - double sumBetaS[maxNbSexes]; // sum of inflection point of settlement reaction norm - double ssqBetaS[maxNbSexes]; // sum of squares of inflection point of settlement reaction norm - double sumGeneticFitness[maxNbSexes]; - double ssqGeneticFitness[maxNbSexes]; + int ninds[gMaxNbSexes]; // no. of individuals + double sumD0[gMaxNbSexes]; // sum of maximum emigration probability + double ssqD0[gMaxNbSexes]; // sum of squares of maximum emigration probability + double sumAlpha[gMaxNbSexes]; // sum of slope of emigration dens-dep reaction norm + double ssqAlpha[gMaxNbSexes]; // sum of squares of slope of emigration den-dep reaction norm + double sumBeta[gMaxNbSexes]; // sum of inflection point of emigration reaction norm + double ssqBeta[gMaxNbSexes]; // sum of squares of inflection point of emigration reaction norm + double sumDist1[gMaxNbSexes]; // sum of kernel I mean + double ssqDist1[gMaxNbSexes]; // sum of squares of kernel I mean + double sumDist2[gMaxNbSexes]; // sum of kernel II mean + double ssqDist2[gMaxNbSexes]; // sum of squares of kernel II mean + double sumProp1[gMaxNbSexes]; // sum of propn using kernel I + double ssqProp1[gMaxNbSexes]; // sum of squares of propn using kernel I + double sumDP[gMaxNbSexes]; // sum of SMS directional persistence + double ssqDP[gMaxNbSexes]; // sum of squares of SMS directional persistence + double sumGB[gMaxNbSexes]; // sum of SMS goal bias + double ssqGB[gMaxNbSexes]; // sum of squares of SMS goal bias + double sumAlphaDB[gMaxNbSexes]; // sum of SMS dispersal bias decay rate + double ssqAlphaDB[gMaxNbSexes]; // sum of squares of SMS dispersal bias decay rate + double sumBetaDB[gMaxNbSexes]; // sum of SMS dispersal bias decay infl. pt. + double ssqBetaDB[gMaxNbSexes]; // sum of squares of SMS dispersal bias decay infl. pt. + double sumStepL[gMaxNbSexes]; // sum of CRW step length + double ssqStepL[gMaxNbSexes]; // sum of squares of CRW step length + double sumRho[gMaxNbSexes]; // sum of CRW correlation coefficient + double ssqRho[gMaxNbSexes]; // sum of squares of CRW correlation coefficient + double sumS0[gMaxNbSexes]; // sum of maximum settlement probability + double ssqS0[gMaxNbSexes]; // sum of squares of maximum settlement probability + double sumAlphaS[gMaxNbSexes]; // sum of slope of settlement den-dep reaction norm + double ssqAlphaS[gMaxNbSexes]; // sum of squares of slope of settlement den-dep reaction norm + double sumBetaS[gMaxNbSexes]; // sum of inflection point of settlement reaction norm + double ssqBetaS[gMaxNbSexes]; // sum of squares of inflection point of settlement reaction norm + double sumGeneticFitness[gMaxNbSexes]; + double ssqGeneticFitness[gMaxNbSexes]; }; class Population { @@ -234,7 +234,7 @@ class Population { short nSexes; Species* pSpecies; // pointer to the species Patch* pPatch; // pointer to the patch - int nInds[maxNbStages][maxNbSexes]; // no. of individuals in each stage/sex + int nInds[gMaxNbStages][gMaxNbSexes]; // no. of individuals in each stage/sex vector inds; // all individuals in population except ... vector juvs; // ... juveniles until reproduction of ALL species diff --git a/Species.cpp b/Species.cpp index 55dc8ed..ba4fccb 100644 --- a/Species.cpp +++ b/Species.cpp @@ -37,8 +37,8 @@ Species::Species(void) devDens = false; devStageDens = false; survDens = false; survStageDens = false; disperseOnLoss = false; - for (int i = 0; i < maxNbStages; i++) { - for (int j = 0; j < maxNbSexes; j++) { + for (int i = 0; i < gMaxNbStages; i++) { + for (int j = 0; j < gMaxNbSexes; j++) { fec[i][j] = 0.0; dev[i][j] = 0.0; surv[i][j] = 0.0; minAge[i][j] = 0; } @@ -52,8 +52,8 @@ Species::Species(void) // initialise emigration parameters densDepEmig = false; stgDepEmig = false; sexDepEmig = false; indVarEmig = false; emigStage = 0; - for (int i = 0; i < maxNbStages; i++) { - for (int j = 0; j < maxNbSexes; j++) { + for (int i = 0; i < gMaxNbStages; i++) { + for (int j = 0; j < gMaxNbSexes; j++) { d0[i][j] = 0.0; alphaEmig[i][j] = 0.0; betaEmig[i][j] = 1.0; } } @@ -64,8 +64,8 @@ Species::Species(void) habMort = false; costMap = false; moveType = 1; - for (int i = 0; i < maxNbStages; i++) { - for (int j = 0; j < maxNbSexes; j++) { + for (int i = 0; i < gMaxNbStages; i++) { + for (int j = 0; j < gMaxNbSexes; j++) { meanDist1[i][j] = 100.0f; meanDist2[i][j] = 1000.0f; probKern1[i][j] = 0.99f; } } @@ -80,8 +80,8 @@ Species::Species(void) fullKernel = false; // initialise settlement parameters stgDepSett = false; sexDepSett = false; indVarSett = false; - for (int i = 0; i < maxNbStages; i++) { - for (int j = 0; j < maxNbSexes; j++) { + for (int i = 0; i < gMaxNbStages; i++) { + for (int j = 0; j < gMaxNbSexes; j++) { densDepSett[i][j] = false; wait[i][j] = false; go2nbrLocn[i][j] = false; findMate[i][j] = false; maxStepsYr[i][j] = 99999999; minSteps[i][j] = 0; maxSteps[i][j] = 99999999; s0[i][j] = 1.0; alphaS[i][j] = 0.0; betaS[i][j] = 1.0; @@ -198,12 +198,12 @@ stageParams Species::getStageParams(void) { void Species::setFec(short stg, short sex, float f) { // NB fecundity for stage 0 must always be zero - if (stg > 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes && f >= 0) + if (stg > 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes && f >= 0) fec[stg][sex] = f; } float Species::getFec(short stg, short sex) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) return fec[stg][sex]; else return 0.0; } @@ -211,7 +211,7 @@ float Species::getFec(short stg, short sex) { float Species::getMaxFec(void) { float maxfec = 0.0; if (stageStruct) { - for (int stg = 1; stg < maxNbStages; stg++) { + for (int stg = 1; stg < gMaxNbStages; stg++) { if (fec[stg][0] > maxfec) maxfec = fec[stg][0]; } } @@ -220,35 +220,35 @@ float Species::getMaxFec(void) { } void Species::setDev(short stg, short sex, float d) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes && d >= 0) + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes && d >= 0) dev[stg][sex] = d; } float Species::getDev(short stg, short sex) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) return dev[stg][sex]; else return 0.0; } void Species::setSurv(short stg, short sex, float s) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes && s >= 0) + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes && s >= 0) surv[stg][sex] = s; } float Species::getSurv(short stg, short sex) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) return surv[stg][sex]; else return 0.0; } void Species::setMinAge(short stg, short sex, int age) { // NB min age for stages 0 & 1 must always be zero - if (stg > 1 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes && age >= 0) + if (stg > 1 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes && age >= 0) minAge[stg][sex] = age; } short Species::getMinAge(short stg, short sex) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) return minAge[stg][sex]; else return 0; } @@ -265,7 +265,7 @@ densDepParams Species::getDensDep(void) { } void Species::createDDwtFec(short mSize) { - if (mSize >= 0 && mSize < (maxNbStages * maxNbSexes)) { + if (mSize >= 0 && mSize < (gMaxNbStages * gMaxNbSexes)) { if (ddwtFec != 0) deleteDDwtFec(); ddwtFecDim = mSize; ddwtFec = new float* [mSize]; @@ -297,7 +297,7 @@ void Species::deleteDDwtFec(void) { } void Species::createDDwtDev(short mSize) { - if (mSize >= 0 && mSize < (maxNbStages * maxNbSexes)) { + if (mSize >= 0 && mSize < (gMaxNbStages * gMaxNbSexes)) { if (ddwtDev != 0) deleteDDwtDev(); ddwtDevDim = mSize; ddwtDev = new float* [mSize]; @@ -329,7 +329,7 @@ void Species::deleteDDwtDev(void) { } void Species::createDDwtSurv(short mSize) { - if (mSize >= 0 && mSize < (maxNbStages * maxNbSexes)) { + if (mSize >= 0 && mSize < (gMaxNbStages * gMaxNbSexes)) { if (ddwtSurv != 0) deleteDDwtSurv(); ddwtSurvDim = mSize; ddwtSurv = new float* [mSize]; @@ -502,7 +502,7 @@ emigRules Species::getEmigRules(void) { } void Species::setSpEmigTraits(const short stg, const short sex, const emigTraits e) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { if (e.d0 >= 0.0 && e.d0 <= 1.0) d0[stg][sex] = e.d0; alphaEmig[stg][sex] = e.alpha; betaEmig[stg][sex] = e.beta; @@ -511,7 +511,7 @@ void Species::setSpEmigTraits(const short stg, const short sex, const emigTraits emigTraits Species::getSpEmigTraits(short stg, short sex) { emigTraits e; - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { e.d0 = d0[stg][sex]; e.alpha = alphaEmig[stg][sex]; e.beta = betaEmig[stg][sex]; @@ -523,7 +523,7 @@ emigTraits Species::getSpEmigTraits(short stg, short sex) { } float Species::getSpEmigD0(short stg, short sex) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { return d0[stg][sex]; } else { @@ -567,7 +567,7 @@ bool Species::useFullKernel(void) { return fullKernel; } void Species::setSpKernTraits(const short stg, const short sex, const trfrKernelParams k, const int resol) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { if (k.meanDist1 > 0.0 && k.meanDist1 >= (float)resol) meanDist1[stg][sex] = k.meanDist1; if (k.meanDist2 >= (float)resol) meanDist2[stg][sex] = k.meanDist2; if (k.probKern1 > 0.0 && k.probKern1 < 1.0) probKern1[stg][sex] = k.probKern1; @@ -576,7 +576,7 @@ void Species::setSpKernTraits(const short stg, const short sex, trfrKernelParams Species::getSpKernTraits(short stg, short sex) { trfrKernelParams k; - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { k.meanDist1 = meanDist1[stg][sex]; k.meanDist2 = meanDist2[stg][sex]; k.probKern1 = probKern1[stg][sex]; @@ -699,7 +699,7 @@ settleType Species::getSettle(void) { } void Species::setSettRules(const short stg, const short sex, const settleRules s) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { densDepSett[stg][sex] = s.densDep; wait[stg][sex] = s.wait; go2nbrLocn[stg][sex] = s.go2nbrLocn; findMate[stg][sex] = s.findMate; } @@ -711,7 +711,7 @@ settleRules Species::getSettRules(short stg, short sex) { s.findMate = false; s.go2nbrLocn = false; s.wait = false; - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { s.densDep = densDepSett[stg][sex]; s.wait = wait[stg][sex]; s.go2nbrLocn = go2nbrLocn[stg][sex]; s.findMate = findMate[stg][sex]; } @@ -719,7 +719,7 @@ settleRules Species::getSettRules(short stg, short sex) { } void Species::setSteps(const short stg, const short sex, const settleSteps s) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { if (s.maxStepsYr >= 1) maxStepsYr[stg][sex] = s.maxStepsYr; else maxStepsYr[stg][sex] = 99999999; if (s.minSteps >= 0) minSteps[stg][sex] = s.minSteps; @@ -731,7 +731,7 @@ void Species::setSteps(const short stg, const short sex, const settleSteps s) { settleSteps Species::getSteps(short stg, short sex) { settleSteps s; - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { s.maxStepsYr = maxStepsYr[stg][sex]; s.minSteps = minSteps[stg][sex]; s.maxSteps = maxSteps[stg][sex]; @@ -745,7 +745,7 @@ settleSteps Species::getSteps(short stg, short sex) { } void Species::setSpSettTraits(const short stg, const short sex, const settleTraits dd) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { if (dd.s0 > 0.0 && dd.s0 <= 1.0) s0[stg][sex] = dd.s0; alphaS[stg][sex] = dd.alpha; betaS[stg][sex] = dd.beta; } @@ -753,7 +753,7 @@ void Species::setSpSettTraits(const short stg, const short sex, const settleTrai settleTraits Species::getSpSettTraits(short stg, short sex) { settleTraits dd; - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { dd.s0 = s0[stg][sex]; dd.alpha = alphaS[stg][sex]; dd.beta = betaS[stg][sex]; } else { dd.s0 = 1.0; dd.alpha = dd.beta = 0.0; } diff --git a/Species.h b/Species.h index 59634a9..557de11 100644 --- a/Species.h +++ b/Species.h @@ -468,10 +468,10 @@ class Species { float** ddwtDev; // density-dependent weights matrix for development float** ddwtSurv; // density-dependent weights matrix for survival // NB for the following arrays, sex 0 is females, sex 1 is males - float fec[maxNbStages][maxNbSexes]; // fecundities - float dev[maxNbStages][maxNbSexes]; // development probabilities - float surv[maxNbStages][maxNbSexes]; // survival probabilities - short minAge[maxNbStages][maxNbSexes]; // minimum age to enter stage + float fec[gMaxNbStages][gMaxNbSexes]; // fecundities + float dev[gMaxNbStages][gMaxNbSexes]; // development probabilities + float surv[gMaxNbStages][gMaxNbSexes]; // survival probabilities + short minAge[gMaxNbStages][gMaxNbSexes]; // minimum age to enter stage // NOTE - IN THEORY, NEXT 3 VARIABLES COULD BE COMMON, BUT WE WOULD NEED TO ENSURE THAT // ALL MATRICES ARE DELETED IF THERE IS A CHANGE IN NO. OF STAGES OR REPRODUCTION TYPE // ***** TO BE RECONSIDERED LATER ***** @@ -505,9 +505,9 @@ class Species { short emigStage; // stage which emigrates (used for stage-strucutred population // having individual variability in emigration probability) // NB for the following arrays, sex 0 is females, sex 1 is males - float d0[maxNbStages][maxNbSexes]; // maximum emigration probability - float alphaEmig[maxNbStages][maxNbSexes]; // slope of density-dependent reaction norm - float betaEmig[maxNbStages][maxNbSexes]; // inflection point of reaction norm (in terms of N/K) + float d0[gMaxNbStages][gMaxNbSexes]; // maximum emigration probability + float alphaEmig[gMaxNbStages][gMaxNbSexes]; // slope of density-dependent reaction norm + float betaEmig[gMaxNbStages][gMaxNbSexes]; // inflection point of reaction norm (in terms of N/K) // NB Initialisation parameters are made double to avoid conversion errors (reason unclear) // on traits maps using FloatToStr() @@ -520,9 +520,9 @@ class Species { bool indVarTrfr; bool twinKern; bool habMort; // habitat-dependent mortality - float meanDist1[maxNbStages][maxNbSexes]; // mean of 1st dispersal kernel (m) - float meanDist2[maxNbStages][maxNbSexes]; // mean of 2nd dispersal kernel (m) - float probKern1[maxNbStages][maxNbSexes]; // probability of dispersing with the 1st kernel + float meanDist1[gMaxNbStages][gMaxNbSexes]; // mean of 1st dispersal kernel (m) + float meanDist2[gMaxNbStages][gMaxNbSexes]; // mean of 2nd dispersal kernel (m) + float probKern1[gMaxNbStages][gMaxNbSexes]; // probability of dispersing with the 1st kernel // NB INITIAL limits are made double to avoid conversion errors (reason unclear) // on traits maps using FloatToStr() // As evolving traits are are not stage-dependent, no. of rows can be 1 @@ -556,16 +556,16 @@ class Species { bool stgDepSett; bool sexDepSett; bool indVarSett; // individual variation in settlement - bool densDepSett[maxNbStages][maxNbSexes]; - bool wait[maxNbStages][maxNbSexes]; // wait to continue moving next season (stage-structured model only) - bool go2nbrLocn[maxNbStages][maxNbSexes]; // settle in neighbouring cell/patch if available (ditto) - bool findMate[maxNbStages][maxNbSexes]; - int minSteps[maxNbStages][maxNbSexes]; // minimum no. of steps - int maxSteps[maxNbStages][maxNbSexes]; // maximum total no. of steps - int maxStepsYr[maxNbStages][maxNbSexes]; // maximum no. of steps in any one dispersal period - float s0[maxNbStages][maxNbSexes]; // maximum settlement probability - float alphaS[maxNbStages][maxNbSexes]; // slope of the settlement reaction norm to density - float betaS[maxNbStages][maxNbSexes]; // inflection point of the settlement reaction norm to density + bool densDepSett[gMaxNbStages][gMaxNbSexes]; + bool wait[gMaxNbStages][gMaxNbSexes]; // wait to continue moving next season (stage-structured model only) + bool go2nbrLocn[gMaxNbStages][gMaxNbSexes]; // settle in neighbouring cell/patch if available (ditto) + bool findMate[gMaxNbStages][gMaxNbSexes]; + int minSteps[gMaxNbStages][gMaxNbSexes]; // minimum no. of steps + int maxSteps[gMaxNbStages][gMaxNbSexes]; // maximum total no. of steps + int maxStepsYr[gMaxNbStages][gMaxNbSexes]; // maximum no. of steps in any one dispersal period + float s0[gMaxNbStages][gMaxNbSexes]; // maximum settlement probability + float alphaS[gMaxNbStages][gMaxNbSexes]; // slope of the settlement reaction norm to density + float betaS[gMaxNbStages][gMaxNbSexes]; // inflection point of the settlement reaction norm to density // other attributes int spNum; diff --git a/SubCommunity.cpp b/SubCommunity.cpp index cf80e8a..7199b43 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -716,7 +716,7 @@ bool SubCommunity::outTraitsHeaders(Landscape* pLandscape, Species* pSpecies, in } } if (pSpecies->getNbGenLoadTraits() > 0) { - if (maxNbSexes > 1) { + if (gMaxNbSexes > 1) { outtraits << "\tF_meanProbViable\tF_stdProbViable\tM_meanProbViable\tM_stdProbViable"; } else { @@ -739,7 +739,7 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge if (sim.outTraitsCells && yr % sim.outIntTraitCell == 0 && !commlevel) writefile = true; traitsums ts, indTraitsSums; - for (int i = 0; i < maxNbSexes; i++) { + for (int i = 0; i < gMaxNbSexes; i++) { ts.ninds[i] = 0; ts.sumD0[i] = ts.ssqD0[i] = 0.0; ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; @@ -1009,7 +1009,7 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge } } if (writefile) { - if (maxNbSexes > 1) { + if (gMaxNbSexes > 1) { outtraits << "\t" << mnProbViable[0] << "\t" << sdProbViable[0]; outtraits << "\t" << mnProbViable[1] << "\t" << sdProbViable[1]; } @@ -1022,7 +1022,7 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT if (writefile) outtraits << endl; - for (int iSex = 0; iSex < maxNbSexes; iSex++) { + for (int iSex = 0; iSex < gMaxNbSexes; iSex++) { ts.ninds[iSex] += indTraitsSums.ninds[iSex]; ts.sumD0[iSex] += indTraitsSums.sumD0[iSex]; ts.ssqD0[iSex] += indTraitsSums.ssqD0[iSex]; From a2089240ce095b6a1458bbb66d8fad8d85a075e8 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 27 May 2024 14:58:21 +0100 Subject: [PATCH 128/332] make global variables explicit --- Community.cpp | 12 ++++----- Individual.cpp | 4 +-- Model.cpp | 14 +++++----- Parameters.cpp | 6 ++--- Parameters.h | 13 +++++---- Patch.cpp | 8 +++--- Patch.h | 2 +- Population.cpp | 60 +++++++++++++++++++++--------------------- Population.h | 68 ++++++++++++++++++++++++------------------------ Species.cpp | 62 +++++++++++++++++++++---------------------- Species.h | 40 ++++++++++++++-------------- SubCommunity.cpp | 8 +++--- 12 files changed, 148 insertions(+), 149 deletions(-) diff --git a/Community.cpp b/Community.cpp index 89fa5a6..c4a3b14 100644 --- a/Community.cpp +++ b/Community.cpp @@ -828,7 +828,7 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) traitsums scts; // sub-community traits int ngenes, popsize; - for (int i = 0; i < maxNbSexes; i++) { + for (int i = 0; i < gMaxNbSexes; i++) { ts.ninds[i] = 0; ts.sumD0[i] = ts.ssqD0[i] = 0.0; ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; @@ -846,7 +846,7 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) int nsubcomms = (int)subComms.size(); for (int i = 0; i < nsubcomms; i++) { // all sub-communities (incl. matrix) scts = subComms[i]->outTraits(pLandscape, rep, yr, gen, true); - for (int j = 0; j < maxNbSexes; j++) { + for (int j = 0; j < gMaxNbSexes; j++) { ts.ninds[j] += scts.ninds[j]; ts.sumD0[j] += scts.sumD0[j]; ts.ssqD0[j] += scts.ssqD0[j]; ts.sumAlpha[j] += scts.sumAlpha[j]; ts.ssqAlpha[j] += scts.ssqAlpha[j]; @@ -1187,7 +1187,7 @@ void Community::outTraits(Species* pSpecies, int rep, int yr, int gen) // create array of traits means, etc., one for each row ts = new traitsums[land.dimY]; for (int y = 0; y < land.dimY; y++) { - for (int i = 0; i < maxNbSexes; i++) { + for (int i = 0; i < gMaxNbSexes; i++) { ts[y].ninds[i] = 0; ts[y].sumD0[i] = ts[y].ssqD0[i] = 0.0; ts[y].sumAlpha[i] = ts[y].ssqAlpha[i] = 0.0; @@ -1216,7 +1216,7 @@ void Community::outTraits(Species* pSpecies, int rep, int yr, int gen) int y = loc.y; if (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0) { - for (int s = 0; s < maxNbSexes; s++) { + for (int s = 0; s < gMaxNbSexes; s++) { ts[y].ninds[s] += sctraits.ninds[s]; ts[y].sumD0[s] += sctraits.sumD0[s]; ts[y].ssqD0[s] += sctraits.ssqD0[s]; ts[y].sumAlpha[s] += sctraits.sumAlpha[s]; ts[y].ssqAlpha[s] += sctraits.ssqAlpha[s]; @@ -1391,7 +1391,7 @@ void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int } if (pSpecies->getNbGenLoadTraits() > 0) { - if (maxNbSexes > 1) { + if (gMaxNbSexes > 1) { if (ts.ninds[0] > 0) mn = ts.sumGeneticFitness[0] / (double)ts.ninds[0]; else mn = 0.0; if (ts.ninds[0] > 1) sd = ts.ssqGeneticFitness[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; @@ -1500,7 +1500,7 @@ bool Community::outTraitsRowsHeaders(Species* pSpecies, int landNr) { } if (pSpecies->getNbGenLoadTraits() > 0) { - if (maxNbSexes > 1) { + if (gMaxNbSexes > 1) { outtraitsrows << "\tF_meanProbViable\tF_stdProbViable\tM_meanProbViable\tM_stdProbViable"; } else diff --git a/Individual.cpp b/Individual.cpp index 452ea0b..28555b1 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1384,8 +1384,8 @@ array3x3f Individual::getHabMatrix(Landscape* pLand, Species* pSpecies, Cell* pCell; landData land = pLand->getLandData(); - if (absorbing) nodatacost = absorbingNoDataCost; - else nodatacost = noDataCost; + if (absorbing) nodatacost = gAbsorbingNoDataCost; + else nodatacost = gNoDataCost; for (int x2 = -1; x2 < 2; x2++) { // index of relative move in x direction for (int y2 = -1; y2 < 2; y2++) { // index of relative move in x direction diff --git a/Model.cpp b/Model.cpp index 21c78db..b309e2e 100644 --- a/Model.cpp +++ b/Model.cpp @@ -1088,7 +1088,7 @@ void OutParameters(Landscape* pLandscape) } int mSize; // index for weights matrices - if (dem.repType == 2) mSize = sstruct.nStages * maxNbSexes; + if (dem.repType == 2) mSize = sstruct.nStages * gMaxNbSexes; else mSize = sstruct.nStages; outPar << "DENSITY-DEPENDENCE IN FECUNDITY:\t"; @@ -1098,8 +1098,8 @@ void OutParameters(Landscape* pLandscape) outPar << "STAGE'S WEIGHTS:" << endl; for (int i = 0; i < mSize; i++) { if (dem.repType == 2) { - outPar << "stage " << i / maxNbSexes << " "; - if (i % maxNbSexes == 0) outPar << "males : \t"; + outPar << "stage " << i / gMaxNbSexes << " "; + if (i % gMaxNbSexes == 0) outPar << "males : \t"; else outPar << "females: \t"; } else outPar << "stage " << i << ": \t"; @@ -1120,8 +1120,8 @@ void OutParameters(Landscape* pLandscape) outPar << "STAGE'S WEIGHTS:" << endl; for (int i = 0; i < mSize; i++) { if (dem.repType == 2) { - outPar << "stage " << i / maxNbSexes << " "; - if (i % maxNbSexes == 0) outPar << "males : \t"; + outPar << "stage " << i / gMaxNbSexes << " "; + if (i % gMaxNbSexes == 0) outPar << "males : \t"; else outPar << "females: \t"; } else outPar << "stage " << i << ": \t"; @@ -1140,8 +1140,8 @@ void OutParameters(Landscape* pLandscape) outPar << "STAGE'S WEIGHTS:" << endl; for (int i = 0; i < mSize; i++) { if (dem.repType == 2) { - outPar << "stage " << i / maxNbSexes << " "; - if (i % maxNbSexes == 0) outPar << "males : \t"; + outPar << "stage " << i / gMaxNbSexes << " "; + if (i % gMaxNbSexes == 0) outPar << "males : \t"; else outPar << "females: \t"; } else outPar << "stage " << i << ": \t"; diff --git a/Parameters.cpp b/Parameters.cpp index c0faafb..0c37dab 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -128,7 +128,7 @@ paramInit::paramInit(void) { minSeedX = 0; maxSeedX = 99999999; minSeedY = 0; maxSeedY = 99999999; nSeedPatches = 1; nSpDistPatches = 1; indsFile = "NULL"; - for (int i = 0; i < maxNbStages; i++) { + for (int i = 0; i < gMaxNbStages; i++) { initProp[i] = 0.0; } } @@ -176,12 +176,12 @@ initParams paramInit::getInit(void) { } void paramInit::setProp(short stg, float p) { - if (stg >= 0 && stg < maxNbStages && p >= 0.0 && p <= 1.0) initProp[stg] = p; + if (stg >= 0 && stg < gMaxNbStages && p >= 0.0 && p <= 1.0) initProp[stg] = p; } float paramInit::getProp(short stg) { float p = 0.0; - if (stg >= 0 && stg < maxNbStages) p = initProp[stg]; + if (stg >= 0 && stg < gMaxNbStages) p = initProp[stg]; return p; } diff --git a/Parameters.h b/Parameters.h index cfd81de..47b780a 100644 --- a/Parameters.h +++ b/Parameters.h @@ -65,13 +65,12 @@ using namespace std; #include "RSrandom.h" -constexpr int noDataCost = 100000; // cost to use in place of nodata value for SMS; -constexpr int absorbingNoDataCost = 100; // cost to use in place of nodata value for SMS; +constexpr int gNoDataCost = 100000; // cost to use in place of nodata value for SMS; +constexpr int gAbsorbingNoDataCost = 100; // cost to use in place of nodata value for SMS; // when boundaries are absorbing -constexpr int maxNbStages = 10; // maximum number of stages permitted -constexpr int maxNbSexes = 2; // maximum number of sexes permitted -constexpr int maxNbTraitsGUI = 18; // maximum number of variable traits which can be displayed - // in GUI (VCL version) +constexpr int gMaxNbStages = 10; // maximum number of stages permitted +constexpr int gMaxNbSexes = 2; // maximum number of sexes permitted + #if RS_RCPP typedef intptr_t intptr; #else @@ -305,7 +304,7 @@ class paramInit { int nSeedPatches; // no. of cells/patches to initialise int nSpDistPatches; // no. of species distribution cells to initialise string indsFile; // no. of species distribution cells to initialise - float initProp[maxNbStages]; // initial stage proportions (structured population only) + float initProp[gMaxNbStages]; // initial stage proportions (structured population only) vector initinds; // individuals to be initialised diff --git a/Patch.cpp b/Patch.cpp index 8504a57..f3f88f0 100644 --- a/Patch.cpp +++ b/Patch.cpp @@ -33,7 +33,7 @@ Patch::Patch(int seqnum, int num) xMin = yMin = 999999999; xMax = yMax = 0; x = y = 0; subCommPtr = 0; localK = 0.0; - for (int sex = 0; sex < maxNbSexes; sex++) { + for (int sex = 0; sex < gMaxNbSexes; sex++) { nTemp[sex] = 0; } changed = false; @@ -326,7 +326,7 @@ void Patch::resetPopn(void) { } void Patch::resetPossSettlers(void) { - for (int sex = 0; sex < maxNbSexes; sex++) { + for (int sex = 0; sex < gMaxNbSexes; sex++) { nTemp[sex] = 0; } } @@ -338,7 +338,7 @@ void Patch::incrPossSettler(Species* pSpecies, int sex) { // << " sex = " << sex << endl; #endif // NOTE: THE FOLLOWING OPERATION WILL NEED TO BE MADE SPECIES-SPECIFIC... - if (sex >= 0 && sex < maxNbSexes) { + if (sex >= 0 && sex < gMaxNbSexes) { nTemp[sex]++; } } @@ -350,7 +350,7 @@ int Patch::getPossSettlers(Species* pSpecies, int sex) { // << " sex = " << sex << endl; #endif // NOTE: THE FOLLOWING OPERATION WILL NEED TO BE MADE SPECIES-SPECIFIC... - if (sex >= 0 && sex < maxNbSexes) return nTemp[sex]; + if (sex >= 0 && sex < gMaxNbSexes) return nTemp[sex]; else return 0; } diff --git a/Patch.h b/Patch.h index 445dd02..1285daf 100644 --- a/Patch.h +++ b/Patch.h @@ -154,7 +154,7 @@ class Patch { float localK; // patch carrying capacity (individuals) bool changed; // NOTE: THE FOLLOWING ARRAY WILL NEED TO BE MADE SPECIES-SPECIFIC... - short nTemp[maxNbSexes]; // no. of potential settlers in each sex + short nTemp[gMaxNbSexes]; // no. of potential settlers in each sex std::vector cells; std::vector popns; diff --git a/Population.cpp b/Population.cpp index fd42127..3a302e7 100644 --- a/Population.cpp +++ b/Population.cpp @@ -77,14 +77,14 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) else { nSexes = 2; probmale = dem.propMales; } // set up population sub-totals - for (int stg = 0; stg < maxNbStages; stg++) { - for (int sex = 0; sex < maxNbSexes; sex++) { + for (int stg = 0; stg < gMaxNbStages; stg++) { + for (int sex = 0; sex < gMaxNbSexes; sex++) { nInds[stg][sex] = 0; } } // set up local copy of minimum age table - short minAge[maxNbStages][maxNbSexes]; + short minAge[gMaxNbStages][gMaxNbSexes]; for (int stg = 0; stg < nStages; stg++) { for (int sex = 0; sex < nSexes; sex++) { if (dem.stageStruct) { @@ -207,7 +207,7 @@ Population::~Population(void) { traitsums Population::getIndTraitsSums(Species* pSpecies) { int g; traitsums ts = traitsums(); - for (int sex = 0; sex < maxNbSexes; sex++) { + for (int sex = 0; sex < gMaxNbSexes; sex++) { ts.ninds[sex] = 0; ts.sumD0[sex] = ts.ssqD0[sex] = 0.0; ts.sumAlpha[sex] = ts.ssqAlpha[sex] = 0.0; @@ -307,7 +307,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { ts.sumBetaS[g] += s.beta; ts.ssqBetaS[g] += s.beta * s.beta; - if (maxNbSexes > 1) g = sex; + if (gMaxNbSexes > 1) g = sex; else g = 0; ts.sumGeneticFitness[g] += inds[iInd]->getGeneticFitness(); ts.ssqGeneticFitness[g] += inds[iInd]->getGeneticFitness() * inds[iInd]->getGeneticFitness(); @@ -559,7 +559,7 @@ void Population::reproduction(const float localK, const float envval, const int // set up local copy of species fecundity table - float fec[maxNbStages][maxNbSexes]; + float fec[gMaxNbStages][gMaxNbSexes]; for (int stg = 0; stg < sstruct.nStages; stg++) { for (int sex = 0; sex < nsexes; sex++) { if (dem.stageStruct) { @@ -873,7 +873,7 @@ vector Population::getIndividualsInStage(int stage) { void Population::emigration(float localK) { int nsexes; - double disp, Pdisp, NK; + double disp, pbDisp, NK; demogrParams dem = pSpecies->getDemogrParams(); stageParams sstruct = pSpecies->getStageParams(); emigRules emig = pSpecies->getEmigRules(); @@ -892,11 +892,11 @@ void Population::emigration(float localK) // NB - IT IS DOUBTFUL THIS CONTRIBUTES ANY SUBSTANTIAL TIME SAVING if (dem.repType == 0) nsexes = 1; else nsexes = 2; - double Pemig[maxNbStages][maxNbSexes]; + double pbEmig[gMaxNbStages][gMaxNbSexes]; for (int stg = 0; stg < sstruct.nStages; stg++) { for (int sex = 0; sex < nsexes; sex++) { - if (emig.indVar) Pemig[stg][sex] = 0.0; + if (emig.indVar) pbEmig[stg][sex] = 0.0; else { if (emig.densDep) { if (emig.sexDep) { @@ -915,23 +915,23 @@ void Population::emigration(float localK) eparams = pSpecies->getSpEmigTraits(0, 0); } } - Pemig[stg][sex] = eparams.d0 / (1.0 + exp(-(NK - eparams.beta) * eparams.alpha)); + pbEmig[stg][sex] = eparams.d0 / (1.0 + exp(-(NK - eparams.beta) * eparams.alpha)); } else { // density-independent if (emig.sexDep) { if (emig.stgDep) { - Pemig[stg][sex] = pSpecies->getSpEmigD0(stg, sex); + pbEmig[stg][sex] = pSpecies->getSpEmigD0(stg, sex); } else { // !emig.stgDep - Pemig[stg][sex] = pSpecies->getSpEmigD0(0, sex); + pbEmig[stg][sex] = pSpecies->getSpEmigD0(0, sex); } } else { // !emig.sexDep if (emig.stgDep) { - Pemig[stg][sex] = pSpecies->getSpEmigD0(stg, 0); + pbEmig[stg][sex] = pSpecies->getSpEmigD0(stg, 0); } else { // !emig.stgDep - Pemig[stg][sex] = pSpecies->getSpEmigD0(0, 0); + pbEmig[stg][sex] = pSpecies->getSpEmigD0(0, 0); } } } @@ -945,20 +945,20 @@ void Population::emigration(float localK) if (emig.indVar) { // individual variability in emigration if (dem.stageStruct && ind.stage != emig.emigStage) { // emigration may not occur - Pdisp = 0.0; + pbDisp = 0.0; } else { // non-structured or individual is in emigration stage eparams = inds[i]->getIndEmigTraits(); if (emig.densDep) { // density-dependent NK = (float)totalPop() / localK; - Pdisp = eparams.d0 / (1.0 + exp(-(NK - eparams.beta) * eparams.alpha)); + pbDisp = eparams.d0 / (1.0 + exp(-(NK - eparams.beta) * eparams.alpha)); } else { // density-independent if (emig.sexDep) { - Pdisp = Pemig[0][ind.sex] + eparams.d0; + pbDisp = pbEmig[0][ind.sex] + eparams.d0; } else { - Pdisp = Pemig[0][0] + eparams.d0; + pbDisp = pbEmig[0][0] + eparams.d0; } } } @@ -968,42 +968,42 @@ void Population::emigration(float localK) if (emig.densDep) { if (emig.sexDep) { if (emig.stgDep) { - Pdisp = Pemig[ind.stage][ind.sex]; + pbDisp = pbEmig[ind.stage][ind.sex]; } else { - Pdisp = Pemig[0][ind.sex]; + pbDisp = pbEmig[0][ind.sex]; } } else { // !emig.sexDep if (emig.stgDep) { - Pdisp = Pemig[ind.stage][0]; + pbDisp = pbEmig[ind.stage][0]; } else { - Pdisp = Pemig[0][0]; + pbDisp = pbEmig[0][0]; } } } else { // density-independent if (emig.sexDep) { if (emig.stgDep) { - Pdisp = Pemig[ind.stage][ind.sex]; + pbDisp = pbEmig[ind.stage][ind.sex]; } else { // !emig.stgDep - Pdisp = Pemig[0][ind.sex]; + pbDisp = pbEmig[0][ind.sex]; } } else { // !emig.sexDep if (emig.stgDep) { - Pdisp = Pemig[ind.stage][0]; + pbDisp = pbEmig[ind.stage][0]; } else { // !emig.stgDep - Pdisp = Pemig[0][0]; + pbDisp = pbEmig[0][0]; } } } } // end of no individual variability - disp = pRandom->Bernoulli(Pdisp); + disp = pRandom->Bernoulli(pbDisp); if (disp == 1) { // emigrant inds[i]->setStatus(1); @@ -1359,9 +1359,9 @@ void Population::survival0(float localK, short option0, short option1) // set up local copies of species development and survival tables int nsexes; if (dem.repType == 0) nsexes = 1; else nsexes = 2; - float dev[maxNbStages][maxNbSexes]; - float surv[maxNbStages][maxNbSexes]; - short minAge[maxNbStages][maxNbSexes]; + float dev[gMaxNbStages][gMaxNbSexes]; + float surv[gMaxNbStages][gMaxNbSexes]; + short minAge[gMaxNbStages][gMaxNbSexes]; for (int stg = 0; stg < sstruct.nStages; stg++) { for (int sex = 0; sex < nsexes; sex++) { if (dem.stageStruct) { diff --git a/Population.h b/Population.h index b019183..13e6538 100644 --- a/Population.h +++ b/Population.h @@ -72,39 +72,39 @@ struct zombie { Individual* pInd; }; struct traitsums { // sums of trait genes for dispersal - int ninds[maxNbSexes]; // no. of individuals - double sumD0[maxNbSexes]; // sum of maximum emigration probability - double ssqD0[maxNbSexes]; // sum of squares of maximum emigration probability - double sumAlpha[maxNbSexes]; // sum of slope of emigration dens-dep reaction norm - double ssqAlpha[maxNbSexes]; // sum of squares of slope of emigration den-dep reaction norm - double sumBeta[maxNbSexes]; // sum of inflection point of emigration reaction norm - double ssqBeta[maxNbSexes]; // sum of squares of inflection point of emigration reaction norm - double sumDist1[maxNbSexes]; // sum of kernel I mean - double ssqDist1[maxNbSexes]; // sum of squares of kernel I mean - double sumDist2[maxNbSexes]; // sum of kernel II mean - double ssqDist2[maxNbSexes]; // sum of squares of kernel II mean - double sumProp1[maxNbSexes]; // sum of propn using kernel I - double ssqProp1[maxNbSexes]; // sum of squares of propn using kernel I - double sumDP[maxNbSexes]; // sum of SMS directional persistence - double ssqDP[maxNbSexes]; // sum of squares of SMS directional persistence - double sumGB[maxNbSexes]; // sum of SMS goal bias - double ssqGB[maxNbSexes]; // sum of squares of SMS goal bias - double sumAlphaDB[maxNbSexes]; // sum of SMS dispersal bias decay rate - double ssqAlphaDB[maxNbSexes]; // sum of squares of SMS dispersal bias decay rate - double sumBetaDB[maxNbSexes]; // sum of SMS dispersal bias decay infl. pt. - double ssqBetaDB[maxNbSexes]; // sum of squares of SMS dispersal bias decay infl. pt. - double sumStepL[maxNbSexes]; // sum of CRW step length - double ssqStepL[maxNbSexes]; // sum of squares of CRW step length - double sumRho[maxNbSexes]; // sum of CRW correlation coefficient - double ssqRho[maxNbSexes]; // sum of squares of CRW correlation coefficient - double sumS0[maxNbSexes]; // sum of maximum settlement probability - double ssqS0[maxNbSexes]; // sum of squares of maximum settlement probability - double sumAlphaS[maxNbSexes]; // sum of slope of settlement den-dep reaction norm - double ssqAlphaS[maxNbSexes]; // sum of squares of slope of settlement den-dep reaction norm - double sumBetaS[maxNbSexes]; // sum of inflection point of settlement reaction norm - double ssqBetaS[maxNbSexes]; // sum of squares of inflection point of settlement reaction norm - double sumGeneticFitness[maxNbSexes]; - double ssqGeneticFitness[maxNbSexes]; + int ninds[gMaxNbSexes]; // no. of individuals + double sumD0[gMaxNbSexes]; // sum of maximum emigration probability + double ssqD0[gMaxNbSexes]; // sum of squares of maximum emigration probability + double sumAlpha[gMaxNbSexes]; // sum of slope of emigration dens-dep reaction norm + double ssqAlpha[gMaxNbSexes]; // sum of squares of slope of emigration den-dep reaction norm + double sumBeta[gMaxNbSexes]; // sum of inflection point of emigration reaction norm + double ssqBeta[gMaxNbSexes]; // sum of squares of inflection point of emigration reaction norm + double sumDist1[gMaxNbSexes]; // sum of kernel I mean + double ssqDist1[gMaxNbSexes]; // sum of squares of kernel I mean + double sumDist2[gMaxNbSexes]; // sum of kernel II mean + double ssqDist2[gMaxNbSexes]; // sum of squares of kernel II mean + double sumProp1[gMaxNbSexes]; // sum of propn using kernel I + double ssqProp1[gMaxNbSexes]; // sum of squares of propn using kernel I + double sumDP[gMaxNbSexes]; // sum of SMS directional persistence + double ssqDP[gMaxNbSexes]; // sum of squares of SMS directional persistence + double sumGB[gMaxNbSexes]; // sum of SMS goal bias + double ssqGB[gMaxNbSexes]; // sum of squares of SMS goal bias + double sumAlphaDB[gMaxNbSexes]; // sum of SMS dispersal bias decay rate + double ssqAlphaDB[gMaxNbSexes]; // sum of squares of SMS dispersal bias decay rate + double sumBetaDB[gMaxNbSexes]; // sum of SMS dispersal bias decay infl. pt. + double ssqBetaDB[gMaxNbSexes]; // sum of squares of SMS dispersal bias decay infl. pt. + double sumStepL[gMaxNbSexes]; // sum of CRW step length + double ssqStepL[gMaxNbSexes]; // sum of squares of CRW step length + double sumRho[gMaxNbSexes]; // sum of CRW correlation coefficient + double ssqRho[gMaxNbSexes]; // sum of squares of CRW correlation coefficient + double sumS0[gMaxNbSexes]; // sum of maximum settlement probability + double ssqS0[gMaxNbSexes]; // sum of squares of maximum settlement probability + double sumAlphaS[gMaxNbSexes]; // sum of slope of settlement den-dep reaction norm + double ssqAlphaS[gMaxNbSexes]; // sum of squares of slope of settlement den-dep reaction norm + double sumBetaS[gMaxNbSexes]; // sum of inflection point of settlement reaction norm + double ssqBetaS[gMaxNbSexes]; // sum of squares of inflection point of settlement reaction norm + double sumGeneticFitness[gMaxNbSexes]; + double ssqGeneticFitness[gMaxNbSexes]; }; class Population { @@ -234,7 +234,7 @@ class Population { short nSexes; Species* pSpecies; // pointer to the species Patch* pPatch; // pointer to the patch - int nInds[maxNbStages][maxNbSexes]; // no. of individuals in each stage/sex + int nInds[gMaxNbStages][gMaxNbSexes]; // no. of individuals in each stage/sex vector inds; // all individuals in population except ... vector juvs; // ... juveniles until reproduction of ALL species diff --git a/Species.cpp b/Species.cpp index 55dc8ed..ba4fccb 100644 --- a/Species.cpp +++ b/Species.cpp @@ -37,8 +37,8 @@ Species::Species(void) devDens = false; devStageDens = false; survDens = false; survStageDens = false; disperseOnLoss = false; - for (int i = 0; i < maxNbStages; i++) { - for (int j = 0; j < maxNbSexes; j++) { + for (int i = 0; i < gMaxNbStages; i++) { + for (int j = 0; j < gMaxNbSexes; j++) { fec[i][j] = 0.0; dev[i][j] = 0.0; surv[i][j] = 0.0; minAge[i][j] = 0; } @@ -52,8 +52,8 @@ Species::Species(void) // initialise emigration parameters densDepEmig = false; stgDepEmig = false; sexDepEmig = false; indVarEmig = false; emigStage = 0; - for (int i = 0; i < maxNbStages; i++) { - for (int j = 0; j < maxNbSexes; j++) { + for (int i = 0; i < gMaxNbStages; i++) { + for (int j = 0; j < gMaxNbSexes; j++) { d0[i][j] = 0.0; alphaEmig[i][j] = 0.0; betaEmig[i][j] = 1.0; } } @@ -64,8 +64,8 @@ Species::Species(void) habMort = false; costMap = false; moveType = 1; - for (int i = 0; i < maxNbStages; i++) { - for (int j = 0; j < maxNbSexes; j++) { + for (int i = 0; i < gMaxNbStages; i++) { + for (int j = 0; j < gMaxNbSexes; j++) { meanDist1[i][j] = 100.0f; meanDist2[i][j] = 1000.0f; probKern1[i][j] = 0.99f; } } @@ -80,8 +80,8 @@ Species::Species(void) fullKernel = false; // initialise settlement parameters stgDepSett = false; sexDepSett = false; indVarSett = false; - for (int i = 0; i < maxNbStages; i++) { - for (int j = 0; j < maxNbSexes; j++) { + for (int i = 0; i < gMaxNbStages; i++) { + for (int j = 0; j < gMaxNbSexes; j++) { densDepSett[i][j] = false; wait[i][j] = false; go2nbrLocn[i][j] = false; findMate[i][j] = false; maxStepsYr[i][j] = 99999999; minSteps[i][j] = 0; maxSteps[i][j] = 99999999; s0[i][j] = 1.0; alphaS[i][j] = 0.0; betaS[i][j] = 1.0; @@ -198,12 +198,12 @@ stageParams Species::getStageParams(void) { void Species::setFec(short stg, short sex, float f) { // NB fecundity for stage 0 must always be zero - if (stg > 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes && f >= 0) + if (stg > 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes && f >= 0) fec[stg][sex] = f; } float Species::getFec(short stg, short sex) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) return fec[stg][sex]; else return 0.0; } @@ -211,7 +211,7 @@ float Species::getFec(short stg, short sex) { float Species::getMaxFec(void) { float maxfec = 0.0; if (stageStruct) { - for (int stg = 1; stg < maxNbStages; stg++) { + for (int stg = 1; stg < gMaxNbStages; stg++) { if (fec[stg][0] > maxfec) maxfec = fec[stg][0]; } } @@ -220,35 +220,35 @@ float Species::getMaxFec(void) { } void Species::setDev(short stg, short sex, float d) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes && d >= 0) + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes && d >= 0) dev[stg][sex] = d; } float Species::getDev(short stg, short sex) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) return dev[stg][sex]; else return 0.0; } void Species::setSurv(short stg, short sex, float s) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes && s >= 0) + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes && s >= 0) surv[stg][sex] = s; } float Species::getSurv(short stg, short sex) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) return surv[stg][sex]; else return 0.0; } void Species::setMinAge(short stg, short sex, int age) { // NB min age for stages 0 & 1 must always be zero - if (stg > 1 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes && age >= 0) + if (stg > 1 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes && age >= 0) minAge[stg][sex] = age; } short Species::getMinAge(short stg, short sex) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) return minAge[stg][sex]; else return 0; } @@ -265,7 +265,7 @@ densDepParams Species::getDensDep(void) { } void Species::createDDwtFec(short mSize) { - if (mSize >= 0 && mSize < (maxNbStages * maxNbSexes)) { + if (mSize >= 0 && mSize < (gMaxNbStages * gMaxNbSexes)) { if (ddwtFec != 0) deleteDDwtFec(); ddwtFecDim = mSize; ddwtFec = new float* [mSize]; @@ -297,7 +297,7 @@ void Species::deleteDDwtFec(void) { } void Species::createDDwtDev(short mSize) { - if (mSize >= 0 && mSize < (maxNbStages * maxNbSexes)) { + if (mSize >= 0 && mSize < (gMaxNbStages * gMaxNbSexes)) { if (ddwtDev != 0) deleteDDwtDev(); ddwtDevDim = mSize; ddwtDev = new float* [mSize]; @@ -329,7 +329,7 @@ void Species::deleteDDwtDev(void) { } void Species::createDDwtSurv(short mSize) { - if (mSize >= 0 && mSize < (maxNbStages * maxNbSexes)) { + if (mSize >= 0 && mSize < (gMaxNbStages * gMaxNbSexes)) { if (ddwtSurv != 0) deleteDDwtSurv(); ddwtSurvDim = mSize; ddwtSurv = new float* [mSize]; @@ -502,7 +502,7 @@ emigRules Species::getEmigRules(void) { } void Species::setSpEmigTraits(const short stg, const short sex, const emigTraits e) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { if (e.d0 >= 0.0 && e.d0 <= 1.0) d0[stg][sex] = e.d0; alphaEmig[stg][sex] = e.alpha; betaEmig[stg][sex] = e.beta; @@ -511,7 +511,7 @@ void Species::setSpEmigTraits(const short stg, const short sex, const emigTraits emigTraits Species::getSpEmigTraits(short stg, short sex) { emigTraits e; - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { e.d0 = d0[stg][sex]; e.alpha = alphaEmig[stg][sex]; e.beta = betaEmig[stg][sex]; @@ -523,7 +523,7 @@ emigTraits Species::getSpEmigTraits(short stg, short sex) { } float Species::getSpEmigD0(short stg, short sex) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { return d0[stg][sex]; } else { @@ -567,7 +567,7 @@ bool Species::useFullKernel(void) { return fullKernel; } void Species::setSpKernTraits(const short stg, const short sex, const trfrKernelParams k, const int resol) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { if (k.meanDist1 > 0.0 && k.meanDist1 >= (float)resol) meanDist1[stg][sex] = k.meanDist1; if (k.meanDist2 >= (float)resol) meanDist2[stg][sex] = k.meanDist2; if (k.probKern1 > 0.0 && k.probKern1 < 1.0) probKern1[stg][sex] = k.probKern1; @@ -576,7 +576,7 @@ void Species::setSpKernTraits(const short stg, const short sex, trfrKernelParams Species::getSpKernTraits(short stg, short sex) { trfrKernelParams k; - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { k.meanDist1 = meanDist1[stg][sex]; k.meanDist2 = meanDist2[stg][sex]; k.probKern1 = probKern1[stg][sex]; @@ -699,7 +699,7 @@ settleType Species::getSettle(void) { } void Species::setSettRules(const short stg, const short sex, const settleRules s) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { densDepSett[stg][sex] = s.densDep; wait[stg][sex] = s.wait; go2nbrLocn[stg][sex] = s.go2nbrLocn; findMate[stg][sex] = s.findMate; } @@ -711,7 +711,7 @@ settleRules Species::getSettRules(short stg, short sex) { s.findMate = false; s.go2nbrLocn = false; s.wait = false; - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { s.densDep = densDepSett[stg][sex]; s.wait = wait[stg][sex]; s.go2nbrLocn = go2nbrLocn[stg][sex]; s.findMate = findMate[stg][sex]; } @@ -719,7 +719,7 @@ settleRules Species::getSettRules(short stg, short sex) { } void Species::setSteps(const short stg, const short sex, const settleSteps s) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { if (s.maxStepsYr >= 1) maxStepsYr[stg][sex] = s.maxStepsYr; else maxStepsYr[stg][sex] = 99999999; if (s.minSteps >= 0) minSteps[stg][sex] = s.minSteps; @@ -731,7 +731,7 @@ void Species::setSteps(const short stg, const short sex, const settleSteps s) { settleSteps Species::getSteps(short stg, short sex) { settleSteps s; - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { s.maxStepsYr = maxStepsYr[stg][sex]; s.minSteps = minSteps[stg][sex]; s.maxSteps = maxSteps[stg][sex]; @@ -745,7 +745,7 @@ settleSteps Species::getSteps(short stg, short sex) { } void Species::setSpSettTraits(const short stg, const short sex, const settleTraits dd) { - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { if (dd.s0 > 0.0 && dd.s0 <= 1.0) s0[stg][sex] = dd.s0; alphaS[stg][sex] = dd.alpha; betaS[stg][sex] = dd.beta; } @@ -753,7 +753,7 @@ void Species::setSpSettTraits(const short stg, const short sex, const settleTrai settleTraits Species::getSpSettTraits(short stg, short sex) { settleTraits dd; - if (stg >= 0 && stg < maxNbStages && sex >= 0 && sex < maxNbSexes) { + if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { dd.s0 = s0[stg][sex]; dd.alpha = alphaS[stg][sex]; dd.beta = betaS[stg][sex]; } else { dd.s0 = 1.0; dd.alpha = dd.beta = 0.0; } diff --git a/Species.h b/Species.h index 59634a9..557de11 100644 --- a/Species.h +++ b/Species.h @@ -468,10 +468,10 @@ class Species { float** ddwtDev; // density-dependent weights matrix for development float** ddwtSurv; // density-dependent weights matrix for survival // NB for the following arrays, sex 0 is females, sex 1 is males - float fec[maxNbStages][maxNbSexes]; // fecundities - float dev[maxNbStages][maxNbSexes]; // development probabilities - float surv[maxNbStages][maxNbSexes]; // survival probabilities - short minAge[maxNbStages][maxNbSexes]; // minimum age to enter stage + float fec[gMaxNbStages][gMaxNbSexes]; // fecundities + float dev[gMaxNbStages][gMaxNbSexes]; // development probabilities + float surv[gMaxNbStages][gMaxNbSexes]; // survival probabilities + short minAge[gMaxNbStages][gMaxNbSexes]; // minimum age to enter stage // NOTE - IN THEORY, NEXT 3 VARIABLES COULD BE COMMON, BUT WE WOULD NEED TO ENSURE THAT // ALL MATRICES ARE DELETED IF THERE IS A CHANGE IN NO. OF STAGES OR REPRODUCTION TYPE // ***** TO BE RECONSIDERED LATER ***** @@ -505,9 +505,9 @@ class Species { short emigStage; // stage which emigrates (used for stage-strucutred population // having individual variability in emigration probability) // NB for the following arrays, sex 0 is females, sex 1 is males - float d0[maxNbStages][maxNbSexes]; // maximum emigration probability - float alphaEmig[maxNbStages][maxNbSexes]; // slope of density-dependent reaction norm - float betaEmig[maxNbStages][maxNbSexes]; // inflection point of reaction norm (in terms of N/K) + float d0[gMaxNbStages][gMaxNbSexes]; // maximum emigration probability + float alphaEmig[gMaxNbStages][gMaxNbSexes]; // slope of density-dependent reaction norm + float betaEmig[gMaxNbStages][gMaxNbSexes]; // inflection point of reaction norm (in terms of N/K) // NB Initialisation parameters are made double to avoid conversion errors (reason unclear) // on traits maps using FloatToStr() @@ -520,9 +520,9 @@ class Species { bool indVarTrfr; bool twinKern; bool habMort; // habitat-dependent mortality - float meanDist1[maxNbStages][maxNbSexes]; // mean of 1st dispersal kernel (m) - float meanDist2[maxNbStages][maxNbSexes]; // mean of 2nd dispersal kernel (m) - float probKern1[maxNbStages][maxNbSexes]; // probability of dispersing with the 1st kernel + float meanDist1[gMaxNbStages][gMaxNbSexes]; // mean of 1st dispersal kernel (m) + float meanDist2[gMaxNbStages][gMaxNbSexes]; // mean of 2nd dispersal kernel (m) + float probKern1[gMaxNbStages][gMaxNbSexes]; // probability of dispersing with the 1st kernel // NB INITIAL limits are made double to avoid conversion errors (reason unclear) // on traits maps using FloatToStr() // As evolving traits are are not stage-dependent, no. of rows can be 1 @@ -556,16 +556,16 @@ class Species { bool stgDepSett; bool sexDepSett; bool indVarSett; // individual variation in settlement - bool densDepSett[maxNbStages][maxNbSexes]; - bool wait[maxNbStages][maxNbSexes]; // wait to continue moving next season (stage-structured model only) - bool go2nbrLocn[maxNbStages][maxNbSexes]; // settle in neighbouring cell/patch if available (ditto) - bool findMate[maxNbStages][maxNbSexes]; - int minSteps[maxNbStages][maxNbSexes]; // minimum no. of steps - int maxSteps[maxNbStages][maxNbSexes]; // maximum total no. of steps - int maxStepsYr[maxNbStages][maxNbSexes]; // maximum no. of steps in any one dispersal period - float s0[maxNbStages][maxNbSexes]; // maximum settlement probability - float alphaS[maxNbStages][maxNbSexes]; // slope of the settlement reaction norm to density - float betaS[maxNbStages][maxNbSexes]; // inflection point of the settlement reaction norm to density + bool densDepSett[gMaxNbStages][gMaxNbSexes]; + bool wait[gMaxNbStages][gMaxNbSexes]; // wait to continue moving next season (stage-structured model only) + bool go2nbrLocn[gMaxNbStages][gMaxNbSexes]; // settle in neighbouring cell/patch if available (ditto) + bool findMate[gMaxNbStages][gMaxNbSexes]; + int minSteps[gMaxNbStages][gMaxNbSexes]; // minimum no. of steps + int maxSteps[gMaxNbStages][gMaxNbSexes]; // maximum total no. of steps + int maxStepsYr[gMaxNbStages][gMaxNbSexes]; // maximum no. of steps in any one dispersal period + float s0[gMaxNbStages][gMaxNbSexes]; // maximum settlement probability + float alphaS[gMaxNbStages][gMaxNbSexes]; // slope of the settlement reaction norm to density + float betaS[gMaxNbStages][gMaxNbSexes]; // inflection point of the settlement reaction norm to density // other attributes int spNum; diff --git a/SubCommunity.cpp b/SubCommunity.cpp index cf80e8a..7199b43 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -716,7 +716,7 @@ bool SubCommunity::outTraitsHeaders(Landscape* pLandscape, Species* pSpecies, in } } if (pSpecies->getNbGenLoadTraits() > 0) { - if (maxNbSexes > 1) { + if (gMaxNbSexes > 1) { outtraits << "\tF_meanProbViable\tF_stdProbViable\tM_meanProbViable\tM_stdProbViable"; } else { @@ -739,7 +739,7 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge if (sim.outTraitsCells && yr % sim.outIntTraitCell == 0 && !commlevel) writefile = true; traitsums ts, indTraitsSums; - for (int i = 0; i < maxNbSexes; i++) { + for (int i = 0; i < gMaxNbSexes; i++) { ts.ninds[i] = 0; ts.sumD0[i] = ts.ssqD0[i] = 0.0; ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; @@ -1009,7 +1009,7 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge } } if (writefile) { - if (maxNbSexes > 1) { + if (gMaxNbSexes > 1) { outtraits << "\t" << mnProbViable[0] << "\t" << sdProbViable[0]; outtraits << "\t" << mnProbViable[1] << "\t" << sdProbViable[1]; } @@ -1022,7 +1022,7 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT if (writefile) outtraits << endl; - for (int iSex = 0; iSex < maxNbSexes; iSex++) { + for (int iSex = 0; iSex < gMaxNbSexes; iSex++) { ts.ninds[iSex] += indTraitsSums.ninds[iSex]; ts.sumD0[iSex] += indTraitsSums.sumD0[iSex]; ts.ssqD0[iSex] += indTraitsSums.ssqD0[iSex]; From eef2e6d03038520d86aa0132849eeaa119a8e5b6 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 30 May 2024 11:21:08 +0100 Subject: [PATCH 129/332] trigger GHA build --- Main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Main.cpp b/Main.cpp index b5e05b4..8106316 100644 --- a/Main.cpp +++ b/Main.cpp @@ -90,7 +90,7 @@ int _tmain(int argc, _TCHAR* argv[]) #ifdef NDEBUG cout << "This code is only for running tests and not meant to run in release." << endl; return 1; -# else +#else // Initialise globals paramsGrad = new paramGrad; From 6701e196dde7bbc4b217b2147aca47d7d8af92bf Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 30 May 2024 12:37:25 +0100 Subject: [PATCH 130/332] attempt to pass CRW test, step len 1 is not enough --- Individual.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index f11b523..568ab02 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -2108,6 +2108,7 @@ void testIndividual() { ls_params.minX = ls_params.minY = 0; ls_params.maxX = ls_params.maxY = ls_params.dimX - 1; ls_params.resol = 1; + double cellDiagLength = ls_params.resol * SQRT2; Landscape ls; ls.setLandParams(ls_params, true); @@ -2144,7 +2145,7 @@ void testIndividual() { // Transfer CRW traits trfrMovtTraits m; m.stepMort = 0.0; - m.stepLength = ls_params.resol; + m.stepLength = cellDiagLength; // guaranteed to move out m.rho = 1.0; m.straigtenPath = false; sp.setMovtTraits(m); @@ -2201,9 +2202,9 @@ void testIndividual() { // ... // Step size + ls = Landscape(); ls.setLandParams(ls_params, true); - sp.createHabK(2); const int hab_suitable = 0; const int hab_unsuitable = 1; @@ -2305,7 +2306,7 @@ void testIndividual() { ls.allocatePatches(&sp); ls.updateCarryingCapacity(&sp, 0, 0); // Individual moves by 1 along the diagonal - m.stepLength = ls_params.resol * SQRT2; // 1 diagonal cell + m.stepLength = cellDiagLength; // 1 diagonal cell m.rho = 1; // angle = previous angle sp.setMovtTraits(m); steps.maxStepsYr = steps.maxSteps = ls_params.dimX; From ebb15462abda441fa160beac68d387981d259f1b Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 30 May 2024 15:57:59 +0100 Subject: [PATCH 131/332] cleanup --- Community.cpp | 66 ++++++++++++++++++++++++------------------------ Landscape.cpp | 60 ++++++++++++++----------------------------- Landscape.h | 7 ----- Model.cpp | 8 +++--- Population.cpp | 16 ++++++------ SubCommunity.cpp | 12 ++++----- 6 files changed, 70 insertions(+), 99 deletions(-) diff --git a/Community.cpp b/Community.cpp index c4a3b14..d7698be 100644 --- a/Community.cpp +++ b/Community.cpp @@ -672,13 +672,13 @@ bool Community::outRangeHeaders(Species* pSpecies, int landNr) if (sim.batchMode) { name = paramsSim->getDir(2) - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" - + Int2Str(landNr) + + "Batch" + to_string(sim.batchNum) + "_" + + "Sim" + to_string(sim.simulation) + "_Land" + + to_string(landNr) + "_Range.txt"; } else { - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Range.txt"; + name = paramsSim->getDir(2) + "Sim" + to_string(sim.simulation) + "_Range.txt"; } outrange.open(name.c_str()); outrange << "Rep\tYear\tRepSeason"; @@ -1088,22 +1088,22 @@ bool Community::outOccupancyHeaders(int option) name = paramsSim->getDir(2); if (sim.batchMode) { - name += "Batch" + Int2Str(sim.batchNum) + "_"; - name += "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(ppLand.landNum); + name += "Batch" + to_string(sim.batchNum) + "_"; + name += "Sim" + to_string(sim.simulation) + "_Land" + to_string(ppLand.landNum); } else - name += "Sim" + Int2Str(sim.simulation); + name += "Sim" + to_string(sim.simulation); name += "_Occupancy_Stats.txt"; outsuit.open(name.c_str()); outsuit << "Year\tMean_OccupSuit\tStd_error" << endl; name = paramsSim->getDir(2); if (sim.batchMode) { - name += "Batch" + Int2Str(sim.batchNum) + "_"; - name += "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(ppLand.landNum); + name += "Batch" + to_string(sim.batchNum) + "_"; + name += "Sim" + to_string(sim.simulation) + "_Land" + to_string(ppLand.landNum); } else - name += "Sim" + Int2Str(sim.simulation); + name += "Sim" + to_string(sim.simulation); name += "_Occupancy.txt"; outoccup.open(name.c_str()); if (ppLand.patchModel) { @@ -1429,11 +1429,11 @@ bool Community::outTraitsRowsHeaders(Species* pSpecies, int landNr) { string DirOut = paramsSim->getDir(2); if (sim.batchMode) { name = DirOut - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) + "_TraitsXrow.txt"; + + "Batch" + to_string(sim.batchNum) + "_" + + "Sim" + to_string(sim.simulation) + "_Land" + to_string(landNr) + "_TraitsXrow.txt"; } else { - name = DirOut + "Sim" + Int2Str(sim.simulation) + "_TraitsXrow.txt"; + name = DirOut + "Sim" + to_string(sim.simulation) + "_TraitsXrow.txt"; } outtraitsrows.open(name.c_str()); @@ -1569,15 +1569,15 @@ bool Community::openOutGenesFile(const bool& isDiploid, const int landNr, const if (sim.batchMode) { name = paramsSim->getDir(2) - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" - + Int2Str(landNr) + "_Rep" + Int2Str(rep) + + "Batch" + to_string(sim.batchNum) + "_" + + "Sim" + to_string(sim.simulation) + "_Land" + + to_string(landNr) + "_Rep" + to_string(rep) + "_geneValues.txt"; } else { name = paramsSim->getDir(2) - + "Sim" + Int2Str(sim.simulation) + "_Land" - + Int2Str(landNr) + "_Rep" + Int2Str(rep) + + "Sim" + to_string(sim.simulation) + "_Land" + + to_string(landNr) + "_Rep" + to_string(rep) + "_geneValues.txt"; } @@ -1649,13 +1649,13 @@ bool Community::openWCFstatFile(Species* pSpecies, int landNr) if (sim.batchMode) { name = paramsSim->getDir(2) - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" - + Int2Str(landNr) + + "Batch" + to_string(sim.batchNum) + "_" + + "Sim" + to_string(sim.simulation) + "_Land" + + to_string(landNr) + "_neutralGenetics.txt"; } else { - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_neutralGenetics.txt"; + name = paramsSim->getDir(2) + "Sim" + to_string(sim.simulation) + "_neutralGenetics.txt"; } outwcfstat.open(name.c_str()); outwcfstat << "Rep\tYear\tRepSeason\tnExtantPatches\tnIndividuals\tfst\tfis\tfit\tmeanAllelePerLocus\tmeanAllelePerLocusPatches\tmeanFixedLoci\tmeanFixedLociPatches\tmeanObHeterozygosity"; @@ -1684,20 +1684,20 @@ bool Community::openWCPerLocusFstatFile(Species* pSpecies, Landscape* pLandscape if (sim.batchMode) { name = paramsSim->getDir(2) - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" - + Int2Str(landNr) + "_Rep" - + Int2Str(rep) + + "Batch" + to_string(sim.batchNum) + "_" + + "Sim" + to_string(sim.simulation) + "_Land" + + to_string(landNr) + "_Rep" + + to_string(rep) + "_perLocusNeutralGenetics.txt"; } else { - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Rep" + Int2Str(rep) + "_perLocusNeutralGenetics.txt"; + name = paramsSim->getDir(2) + "Sim" + to_string(sim.simulation) + "_Rep" + to_string(rep) + "_perLocusNeutralGenetics.txt"; } outperlocusfstat.open(name.c_str()); outperlocusfstat << "Year\tRepSeason\tlocus\tfst\tfis\tfit\tpopHet"; for (int patchId : patchList) { - outperlocusfstat << "\tpatch_" + Int2Str(patchId) + "_Het"; + outperlocusfstat << "\tpatch_" + to_string(patchId) + "_Het"; } outperlocusfstat << endl; @@ -1723,14 +1723,14 @@ bool Community::openPairwiseFSTFile(Species* pSpecies, Landscape* pLandscape, co if (sim.batchMode) { name = paramsSim->getDir(2) - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" - + Int2Str(landNr) + "_Rep" - + Int2Str(rep) + + "Batch" + to_string(sim.batchNum) + "_" + + "Sim" + to_string(sim.simulation) + "_Land" + + to_string(landNr) + "_Rep" + + to_string(rep) + "_pairwisePatchNeutralGenetics.txt"; } else { - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Rep" + Int2Str(rep) + "_pairwisePatchNeutralGenetics.txt"; + name = paramsSim->getDir(2) + "Sim" + to_string(sim.simulation) + "_Rep" + to_string(rep) + "_pairwisePatchNeutralGenetics.txt"; } outpairwisefst.open(name.c_str()); outpairwisefst << "Year\tRepSeason\tpatchA\tpatchB\tfst"; diff --git a/Landscape.cpp b/Landscape.cpp index 569e7a0..497bc29 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -300,7 +300,6 @@ Landscape::~Landscape() { patchnums.clear(); habCodes.clear(); - colours.clear(); landchanges.clear(); patchchanges.clear(); @@ -495,27 +494,6 @@ int Landscape::getHabCode(int ixhab) { void Landscape::clearHabitats(void) { habCodes.clear(); - colours.clear(); -} - -void Landscape::addColour(rgb c) { - colours.push_back(c); -} - -void Landscape::changeColour(int i, rgb col) { - int ncolours = (int)colours.size(); - if (i >= 0 && i < ncolours) { - if (col.r >= 0 && col.r <= 255 && col.g >= 0 && col.g <= 255 && col.b >= 0 && col.b <= 255) - colours[i] = col; - } -} - -rgb Landscape::getColour(int ix) { - return colours[ix]; -} - -int Landscape::colourCount(void) { - return (int)colours.size(); } //--------------------------------------------------------------------------- @@ -2503,11 +2481,11 @@ bool Landscape::outConnectHeaders(int option) string name = paramsSim->getDir(2); if (sim.batchMode) { - name += "Batch" + Int2Str(sim.batchNum) + "_"; - name += "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNum); + name += "Batch" + to_string(sim.batchNum) + "_"; + name += "Sim" + to_string(sim.simulation) + "_Land" + to_string(landNum); } else - name += "Sim" + Int2Str(sim.simulation); + name += "Sim" + to_string(sim.simulation); name += "_Connect.txt"; outConnMat.open(name.c_str()); @@ -2529,14 +2507,14 @@ void Landscape::outPathsHeaders(int rep, int option) simParams sim = paramsSim->getSim(); string name = paramsSim->getDir(2); if (sim.batchMode) { - name += "Batch" + Int2Str(sim.batchNum) - + "_Sim" + Int2Str(sim.simulation) - + "_Land" + Int2Str(landNum) - + "_Rep" + Int2Str(rep); + name += "Batch" + to_string(sim.batchNum) + + "_Sim" + to_string(sim.simulation) + + "_Land" + to_string(landNum) + + "_Rep" + to_string(rep); } else { - name += "Sim" + Int2Str(sim.simulation) - + "_Rep" + Int2Str(rep); + name += "Sim" + to_string(sim.simulation) + + "_Rep" + to_string(rep); } name += "_MovePaths.txt"; @@ -2622,22 +2600,22 @@ void Landscape::outVisits(int rep, int landNr) { if (sim.batchMode) { name = paramsSim->getDir(3) #if RS_RCPP - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) - + "_Land" + Int2Str(landNr) + "_Rep" + Int2Str(rep) + + "Batch" + to_string(sim.batchNum) + "_" + + "Sim" + to_string(sim.simulation) + + "_Land" + to_string(landNr) + "_Rep" + to_string(rep) #else - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) - + "_land" + Int2Str(landNr) + "_rep" + Int2Str(rep) + + "Batch" + to_string(sim.batchNum) + "_" + + "Sim" + to_string(sim.simulation) + + "_land" + to_string(landNr) + "_rep" + to_string(rep) #endif - // + "_yr" + Int2Str(yr) + // + "_yr" + to_string(yr) + "_Visits.txt"; } else { name = paramsSim->getDir(3) - + "Sim" + Int2Str(sim.simulation) - + "_land" + Int2Str(landNr) + "_rep" + Int2Str(rep) - // + "_yr" + Int2Str(yr) + + "Sim" + to_string(sim.simulation) + + "_land" + to_string(landNr) + "_rep" + to_string(rep) + // + "_yr" + to_string(yr) + "_Visits.txt"; } outvisits.open(name.c_str()); diff --git a/Landscape.h b/Landscape.h index 1d0bf92..3fa56c4 100644 --- a/Landscape.h +++ b/Landscape.h @@ -225,10 +225,6 @@ class Landscape { int findHabCode(int); int getHabCode(int); void clearHabitats(void); - void addColour(rgb); - void changeColour(int, rgb); - rgb getColour(int); - int colourCount(void); // functions to handle patches and cells @@ -495,9 +491,6 @@ class Landscape { // list of habitat codes std::vector habCodes; - // list of colours for habitat codes - std::vector colours; - // list of dynamic landscape changes std::vector landchanges; std::vector patchchanges; diff --git a/Model.cpp b/Model.cpp index b309e2e..17ec8e7 100644 --- a/Model.cpp +++ b/Model.cpp @@ -782,11 +782,11 @@ void OutParameters(Landscape* pLandscape) string name; if (sim.batchMode) name = paramsSim->getDir(2) - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) - + "_Land" + Int2Str(ppLand.landNum) + "_Parameters.txt"; + + "Batch" + to_string(sim.batchNum) + "_" + + "Sim" + to_string(sim.simulation) + + "_Land" + to_string(ppLand.landNum) + "_Parameters.txt"; else - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Parameters.txt"; + name = paramsSim->getDir(2) + "Sim" + to_string(sim.simulation) + "_Parameters.txt"; outPar.open(name.c_str()); outPar << "RangeShifter 2.0 "; diff --git a/Population.cpp b/Population.cpp index 3a302e7..d7b9072 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1646,11 +1646,11 @@ bool Population::outPopHeaders(int landNr, bool patchModel) { stageParams sstruct = pSpecies->getStageParams(); if (sim.batchMode) { name = paramsSim->getDir(2) - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) + "_Pop.txt"; + + "Batch" + to_string(sim.batchNum) + "_" + + "Sim" + to_string(sim.simulation) + "_Land" + to_string(landNr) + "_Pop.txt"; } else { - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Pop.txt"; + name = paramsSim->getDir(2) + "Sim" + to_string(sim.simulation) + "_Pop.txt"; } outPop.open(name.c_str()); outPop << "Rep\tYear\tRepSeason"; @@ -1761,13 +1761,13 @@ void Population::outIndsHeaders(int rep, int landNr, bool patchModel) if (sim.batchMode) { name = paramsSim->getDir(2) - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) - + "_Land" + Int2Str(landNr) + "_Rep" + Int2Str(rep) + "_Inds.txt"; + + "Batch" + to_string(sim.batchNum) + "_" + + "Sim" + to_string(sim.simulation) + + "_Land" + to_string(landNr) + "_Rep" + to_string(rep) + "_Inds.txt"; } else { - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) - + "_Rep" + Int2Str(rep) + "_Inds.txt"; + name = paramsSim->getDir(2) + "Sim" + to_string(sim.simulation) + + "_Rep" + to_string(rep) + "_Inds.txt"; } outInds.open(name.c_str()); outInds << "Rep\tYear\tRepSeason\tSpecies\tIndID\tStatus"; diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 7199b43..60abb6c 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -631,23 +631,23 @@ bool SubCommunity::outTraitsHeaders(Landscape* pLandscape, Species* pSpecies, in if (sim.batchMode) { if (land.patchModel) { name = DirOut - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) + + "Batch" + to_string(sim.batchNum) + "_" + + "Sim" + to_string(sim.simulation) + "_Land" + to_string(landNr) + "_TraitsXpatch.txt"; } else { name = DirOut - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) + + "Batch" + to_string(sim.batchNum) + "_" + + "Sim" + to_string(sim.simulation) + "_Land" + to_string(landNr) + "_TraitsXcell.txt"; } } else { if (land.patchModel) { - name = DirOut + "Sim" + Int2Str(sim.simulation) + "_TraitsXpatch.txt"; + name = DirOut + "Sim" + to_string(sim.simulation) + "_TraitsXpatch.txt"; } else { - name = DirOut + "Sim" + Int2Str(sim.simulation) + "_TraitsXcell.txt"; + name = DirOut + "Sim" + to_string(sim.simulation) + "_TraitsXcell.txt"; } } outtraits.open(name.c_str()); From c934a7d9a66f12a6addc81f9c7912b5b009c0034 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 31 May 2024 13:29:41 +0100 Subject: [PATCH 132/332] merge progress --- Individual.cpp | 127 +++++++++++++++++++------------------------------ Individual.h | 65 ++++++++----------------- Patch.cpp | 36 -------------- Patch.h | 2 +- Species.cpp | 3 +- 5 files changed, 71 insertions(+), 162 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 2f4ad9a..2ec4871 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1598,8 +1598,8 @@ void Individual::setPath(pathData* pPath) { path = pPath; } -void Individual::setCRW(crwParams* pCRW) { - crw = pCRW; +void Individual::setCRW(crwData* pCRW) { + pTrfrData = make_unique(pCRW->prevdrn, pCRW->xc, pCRW->yc); } // TP: Both functions below are a bad fix to an issue I have for testing @@ -1612,14 +1612,16 @@ void Individual::forceInitPath() { setPath(pPath); } // Force initialisation of crw -void Individual::forceInitCRW(const trfrMovtTraits& m) { - crwParams* pCRW = new crwParams; - pCRW->prevdrn = (float)(pRandom->Random() * 2.0 * PI); - pCRW->xc = ((float)pRandom->Random() * 0.999f) + (float)pCurrCell->getLocn().x; - pCRW->yc = ((float)pRandom->Random() * 0.999f) + (float)pCurrCell->getLocn().y; +/* +void Individual::forceInitCRW(const trfrMovtParams& m) { + float prevdrn = (float)(pRandom->Random() * 2.0 * PI); + float xc = ((float)pRandom->Random() * 0.999f) + (float)pCurrCell->getLocn().x; + float yc = ((float)pRandom->Random() * 0.999f) + (float)pCurrCell->getLocn().y; + std::unique_ptr pCRW = make_unique(prevdrn, xc, yc); pCRW->stepL = m.stepLength; pCRW->rho = m.rho; setCRW(pCRW); } +*/ void Individual::setInitAngle(const float angle) { crw->prevdrn = angle; @@ -1629,38 +1631,6 @@ void Individual::setInitAngle(const float angle) { void testIndividual() { - /* - Patch* pPatch = new Patch(0, 0); - int cell_x = 2; - int cell_y = 5; - int cell_hab = 2; - Cell* pCell = new Cell(cell_x, cell_y, (intptr)pPatch, cell_hab); - - // Create an individual - short stg = 0; - short age = 0; - short repInt = 0; - float probmale = 0; - bool uses_movt_process = true; - short moveType = 1; - Individual ind(pCell, pPatch, stg, age, repInt, probmale, uses_movt_process, moveType); - */ - - // Gets its sex drawn from pmale - - // Can age or develop - - // - - // Reproduces - // depending on whether it is sexual or not - // depending on the stage - // depending on the trait inheritance - - // Disperses - // Emigrates - // Transfers - // Kernel-based transfer { // Simple cell-based landscape layout @@ -1690,15 +1660,15 @@ void testIndividual() { d.stageStruct = false; sp.setDemogr(d); // Transfer rules - trfrRules trfr; + transferRules trfr; trfr.indVar = trfr.sexDep = trfr.stgDep = false; trfr.twinKern = trfr.distMort = false; - sp.setTrfr(trfr); + sp.setTrfrRules(trfr); sp.setFullKernel(false); // Transfer traits - trfrKernTraits kern; + trfrKernelParams kern; kern.meanDist1 = static_cast(ls_params.dimX); // can reach destination cell reasonably often - sp.setKernTraits(0, 0, kern, ls_params.resol); + sp.setSpKernTraits(0, 0, kern, ls_params.resol); // Transfer mortality params trfrMortParams mort; mort.fixedMort = 0.0; @@ -1717,7 +1687,6 @@ void testIndividual() { //Individual starting_ind(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // Set aside original individual and test on a copy Individual ind(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); - // pathData *path; ? int isDispersing = ind.moveKernel(&ls, &sp, false); // After moving, individual should be in the only available cell @@ -1728,7 +1697,7 @@ void testIndividual() { // If no cell within reasonable dispersal reach, individual does not move and dies kern.meanDist1 = 1.0; - sp.setKernTraits(0, 0, kern, ls_params.resol); + sp.setSpKernTraits(0, 0, kern, ls_params.resol); ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual isDispersing = ind.moveKernel(&ls, &sp, false); curr_cell = ind.getCurrCell(); @@ -1737,34 +1706,34 @@ void testIndividual() { // Twin kernels trfr.twinKern = true; - sp.setTrfr(trfr); + sp.setTrfrRules(trfr); kern.meanDist1 = 1.0; // very unlikely to reach suitable cell kern.meanDist2 = 5.0; // easily reaches suitable cell... kern.probKern1 = 1.0; // ... but never used - sp.setKernTraits(0, 0, kern, ls_params.resol); + sp.setSpKernTraits(0, 0, kern, ls_params.resol); ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind.moveKernel(&ls, &sp, false); assert(ind.getStatus() == 6); kern.probKern1 = 0.0; // always use second kernel - sp.setKernTraits(0, 0, kern, ls_params.resol); + sp.setSpKernTraits(0, 0, kern, ls_params.resol); ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind.moveKernel(&ls, &sp, false); assert(ind.getStatus() == 2); // reset trfr.twinKern = false; - sp.setTrfr(trfr); + sp.setTrfrRules(trfr); kern.probKern1 = 1.0; - sp.setKernTraits(0, 0, kern, ls_params.resol); + sp.setSpKernTraits(0, 0, kern, ls_params.resol); // Sex-dependent dispersal distances trfr.sexDep = true; - sp.setTrfr(trfr); - trfrKernTraits kern_f = kern; + sp.setTrfrRules(trfr); + trfrKernelParams kern_f = kern; kern_f.meanDist1 = 1.0; // female very unlikely to reach suitable cell - sp.setKernTraits(0, 0, kern_f, ls_params.resol); - trfrKernTraits kern_m = kern; + sp.setSpKernTraits(0, 0, kern_f, ls_params.resol); + trfrKernelParams kern_m = kern; kern_m.meanDist1 = 5.0; // male easily reaches suitable cell - sp.setKernTraits(0, 1, kern_m, ls_params.resol); + sp.setSpKernTraits(0, 1, kern_m, ls_params.resol); ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // female as default isDispersing = ind.moveKernel(&ls, &sp, false); @@ -1776,17 +1745,17 @@ void testIndividual() { assert(ind.getStatus() == 2); // reset trfr.sexDep = false; - sp.setTrfr(trfr); + sp.setTrfrRules(trfr); // Stage-dependent trfr.stgDep = true; - sp.setTrfr(trfr); - trfrKernTraits kern_juv = kern; + sp.setTrfrRules(trfr); + trfrKernelParams kern_juv = kern; kern_juv.meanDist1 = 1.0; // juveniles very unlikely to reach suitable cell - sp.setKernTraits(0, 0, kern_juv, ls_params.resol); - trfrKernTraits kern_adult = kern; + sp.setSpKernTraits(0, 0, kern_juv, ls_params.resol); + trfrKernelParams kern_adult = kern; kern_adult.meanDist1 = 5.0; // adults easily reach suitable cell - sp.setKernTraits(1, 0, kern_adult, ls_params.resol); + sp.setSpKernTraits(1, 0, kern_adult, ls_params.resol); ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, false, 0); // juvenile isDispersing = ind.moveKernel(&ls, &sp, false); @@ -1797,7 +1766,7 @@ void testIndividual() { assert(ind.getStatus() == 2); // reset trfr.stgDep = false; - sp.setTrfr(trfr); + sp.setTrfrRules(trfr); /* Boundaries: dispersal distance overshoots Only adjacent cells are available @@ -1823,7 +1792,7 @@ void testIndividual() { init_patch = (Patch*)init_cell->getPatch(); kern.meanDist1 = 10; // overshoots *most* of the time... - sp.setKernTraits(0, 0, kern, ls_params.resol); + sp.setSpKernTraits(0, 0, kern, ls_params.resol); ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual // Non-absorbing boundaries @@ -1846,18 +1815,18 @@ void testIndividual() { mort.fixedMort = 1.0; // Individual *will* die after any step sp.setMortParams(mort); trfr.distMort = false; - sp.setTrfr(trfr); + sp.setTrfrRules(trfr); ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind.moveKernel(&ls, &sp, false); assert(ind.getStatus() == 7); // Distance-dependent mortality trfr.distMort = true; - sp.setTrfr(trfr); + sp.setTrfrRules(trfr); mort.mortAlpha = 1000.0; // very steep threshold mort.mortBeta = 0.5; // very small distance sp.setMortParams(mort); kern.meanDist1 = 5; // very likely to go over threshold - sp.setKernTraits(0, 0, kern, ls_params.resol); + sp.setSpKernTraits(0, 0, kern, ls_params.resol); ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind.moveKernel(&ls, &sp, false); assert(ind.getStatus() == 7); @@ -1870,12 +1839,13 @@ void testIndividual() { // Reset mortality params trfr.distMort = false; mort.fixedMort = 0.0; - sp.setTrfr(trfr); + sp.setTrfrRules(trfr); sp.setMortParams(mort); ind.~Individual(); } + /* // Correlated random walk (CRW) { // Simple cell-based landscape layout @@ -1912,19 +1882,19 @@ void testIndividual() { sp.createHabCostMort(1); // Transfer rules - trfrRules trfr; + transferRules trfr; trfr.indVar = false; trfr.habMort = false; trfr.moveType = 2; // CRW - sp.setTrfr(trfr); + sp.setTrfrRules(trfr); // Transfer CRW traits - trfrMovtTraits m; + trfrMovtParams m; m.stepMort = 0.0; m.stepLength = cellDiagLength; // guaranteed to move out m.rho = 1.0; - m.straigtenPath = false; - sp.setMovtTraits(m); + m.straightenPath = false; + sp.setSpMovtTraits(m); // Settlement rules settleRules sett; @@ -1952,7 +1922,7 @@ void testIndividual() { // Per-step mortality m.stepMort = 1.0; // should die - sp.setMovtTraits(m); + sp.setSpMovtTraits(m); ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); // force set path bc for some reason path gets deallocated upon exiting constructor?? ind.forceInitPath(); @@ -1972,7 +1942,7 @@ void testIndividual() { assert(ind.getCurrCell() == first_step_cell); // shouldn't have moved assert(ind.getStatus() == 7); // died by transfer m.stepMort = 0.0; // not dying - sp.setMovtTraits(m); + sp.setSpMovtTraits(m); // Habitat-dep mortality // ... @@ -2002,7 +1972,7 @@ void testIndividual() { // Step length too short m.stepLength = 0.1; // will not reach final cell m.rho = 0.0; // random angle - sp.setMovtTraits(m); + sp.setSpMovtTraits(m); steps.minSteps = 1; steps.maxStepsYr = 2; steps.maxSteps = 3; @@ -2027,7 +1997,7 @@ void testIndividual() { // Step length too long m.stepLength = ls_params.dimX * SQRT2 * 1.5; // overshoots - sp.setMovtTraits(m); + sp.setSpMovtTraits(m); ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); ind.setStatus(1); // dispersing ind.forceInitPath(); @@ -2042,7 +2012,7 @@ void testIndividual() { // Adequate step length m.stepLength = (ls_params.dimX - 1) * SQRT2; - sp.setMovtTraits(m); + sp.setSpMovtTraits(m); ind = Individual(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); ind.setStatus(1); // dispersing ind.forceInitPath(); @@ -2084,7 +2054,7 @@ void testIndividual() { // Individual moves by 1 along the diagonal m.stepLength = cellDiagLength; // 1 diagonal cell m.rho = 1; // angle = previous angle - sp.setMovtTraits(m); + sp.setSpMovtTraits(m); steps.maxStepsYr = steps.maxSteps = ls_params.dimX; sp.setSteps(0, 0, steps); ind = Individual(cell_vec[0], natalPatch, 0, 0, 0, 0.0, true, 2); @@ -2100,6 +2070,7 @@ void testIndividual() { assert(ind.getCurrCell() == cell_vec[i * (ls_params.dimX + 1)]); } } + */ } #endif // RSDEBUG diff --git a/Individual.h b/Individual.h index 6a052e9..40d1085 100644 --- a/Individual.h +++ b/Individual.h @@ -68,9 +68,10 @@ struct pathData { // to hold path data common to SMS and CRW models int year, total, out; // nos. of steps Patch* pSettPatch; // pointer to most recent patch tested for settlement short settleStatus; // whether ind may settle in current patch - // 0 = not set, 1 = debarred through density dependence rule - // 2 = OK to settle subject to finding a mate -// bool leftNatalPatch; // individual has moved out of its natal patch + // 0 = not set, + // 1 = debarred through density dependence rule + // 2 = OK to settle subject to finding a mate + #if RS_RCPP short pathoutput; #endif @@ -83,17 +84,11 @@ struct settlePatch { }; struct trfrData { - virtual void addMyself(trfrData& toAdd) = 0; - virtual void clone(const trfrData& copyFrom) = 0; - virtual void divideTraitsBy(int) = 0; - virtual movement_t getType() = 0; - virtual ~trfrData() {} - }; struct crwData : trfrData { // to hold data for CRW movement model @@ -102,36 +97,25 @@ struct crwData : trfrData { // to hold data for CRW movement model float xc, yc; // continuous cell co-ordinates float rho; // phenotypic step correlation coefficient float stepLength; // phenotypic step length (m) - //static bool straigtenPath; //does not vary between individuals, shared - //static float stepMort; //does not vary between individuals, shared crwData(float prevdrnA, float xcA, float ycA) : prevdrn(prevdrnA), xc(xcA), yc(ycA), rho(0.0), stepLength(0.0) {} ~crwData() {} void addMyself(trfrData& toAdd) { - auto& CRW = dynamic_cast(toAdd); - CRW.stepLength += stepLength; CRW.rho += rho; - - //stepLength += pCRW.stepLength; - // rho += pCRW.rho; } movement_t getType() { return CRW; } void clone(const trfrData& copyFrom) { - - const crwData& pCopy = dynamic_cast(copyFrom); - stepLength = pCopy.stepLength; rho = pCopy.rho; } void divideTraitsBy(int i) { - stepLength /= i; rho /= i; } @@ -147,18 +131,9 @@ struct smsData : trfrData { float alphaDB; // dispersal bias decay rate int betaDB; // dispersal bias decay inflection point (no. of steps) - //below are shared - //static short pr; - //static short prMethod; - //static short memSize; - //static short goalType; - //static float stepMort; - //static bool straigtenPath; - smsData(locn prevA, locn goalA) : prev(prevA), goal(goalA), dp(0.0), gb(0.0), alphaDB(0.0), betaDB(0) {} ~smsData() {} - void addMyself(trfrData& toAdd) { auto& SMS = dynamic_cast(toAdd); SMS.dp += dp; @@ -178,7 +153,6 @@ struct smsData : trfrData { } void divideTraitsBy(int i) { - dp /= i; gb /= i; alphaDB /= i; @@ -372,9 +346,9 @@ class Individual { // Testing utilities Cell* getCurrCell() const; void setPath(pathData* pPath); - void setCRW(crwParams* pCRW); + void setCRW(crwData* pCRW); void forceInitPath(); - void forceInitCRW(const trfrMovtTraits&); + //void forceInitCRW(const trfrMovtTraits&); void setInitAngle(const float angle); #endif @@ -384,19 +358,20 @@ class Individual { short stage; sex_t sex; short age; - short status; // 0 = initial status in natal patch / philopatric recruit - // 1 = disperser - // 2 = disperser awaiting settlement in possible suitable patch - // 3 = waiting between dispersal events - // 4 = completed settlement - // 5 = completed settlement in a suitable neighbouring cell - // 6 = died during transfer by failing to find a suitable patch - // (includes exceeding maximum number of steps or crossing - // absorbing boundary) - // 7 = died during transfer by constant, step-dependent, - // habitat-dependent or distance-dependent mortality - // 8 = failed to survive annual (demographic) mortality - // 9 = exceeded maximum age + short status; + // 0 = initial status in natal patch / philopatric recruit + // 1 = disperser + // 2 = disperser awaiting settlement in possible suitable patch + // 3 = waiting between dispersal events + // 4 = completed settlement + // 5 = completed settlement in a suitable neighbouring cell + // 6 = died during transfer by failing to find a suitable patch + // (includes exceeding maximum number of steps or crossing + // absorbing boundary) + // 7 = died during transfer by constant, step-dependent, + // habitat-dependent or distance-dependent mortality + // 8 = failed to survive annual (demographic) mortality + // 9 = exceeded maximum age short fallow; // reproductive seasons since last reproduction bool isDeveloping; Cell* pPrevCell; // pointer to previous Cell diff --git a/Patch.cpp b/Patch.cpp index f3f88f0..2c80bb8 100644 --- a/Patch.cpp +++ b/Patch.cpp @@ -136,23 +136,12 @@ void Patch::setCarryingCapacity(Species* pSpecies, patchLimits landlimits, int nsuitable = 0; double mean; -#if RSDEBUG - //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum - // << " xMin=" << xMin << " yMin=" << yMin << " xMax=" << xMax << " yMax=" << yMax - // << endl; -#endif - if (xMin > landlimits.xMax || xMax < landlimits.xMin || yMin > landlimits.yMax || yMax < landlimits.yMin) { // patch lies wholely outwith current landscape limits // NB the next statement is unnecessary, as localK has been set to zero above // retained only for consistency in standard variant localK = 0.0; -#if RSDEBUG - //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum - // << " localK=" << localK - // << endl; -#endif return; } @@ -200,19 +189,9 @@ void Patch::setCarryingCapacity(Species* pSpecies, patchLimits landlimits, } break; } -#if RSDEBUG - //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum - // << " i=" << i << " hx=" << hx << " q=" << q << " k=" << k << " localK=" << localK - // << endl; -#endif loc = cells[i]->getLocn(); xsum += loc.x; ysum += loc.y; } -#if RSDEBUG - //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum - // << " epsGlobal=" << epsGlobal << " localK=" << localK - // << endl; -#endif // calculate centroid co-ordinates if (ncells > 0) { mean = (double)xsum / (double)ncells; @@ -226,24 +205,9 @@ void Patch::setCarryingCapacity(Species* pSpecies, patchLimits landlimits, float limit; limit = pSpecies->getMinMax(0) * (float)nsuitable; if (localK < limit) localK = limit; -#if RSDEBUG - //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum - // << " limit=" << limit << " localK=" << localK - // << endl; -#endif limit = pSpecies->getMinMax(1) * (float)nsuitable; if (localK > limit) localK = limit; -#if RSDEBUG - //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum - // << " limit=" << limit << " localK=" << localK - // << endl; -#endif } -#if RSDEBUG - //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum - // << " localK=" << localK - // << endl; -#endif } diff --git a/Patch.h b/Patch.h index f49bc4e..1285daf 100644 --- a/Patch.h +++ b/Patch.h @@ -131,7 +131,7 @@ class Patch { Species*, // pointer to the Species int // sex of the settlers ); - void calculateKXY( // Calculate total Patch carrying capacity (no. of inds) + void setCarryingCapacity( // Calculate total Patch carrying capacity (no. of inds) Species*, // pointer to the Species patchLimits, // current min and max limits of landscape float, // global stochasticity value (epsilon) for the current year diff --git a/Species.cpp b/Species.cpp index 18d24f6..70ff4fe 100644 --- a/Species.cpp +++ b/Species.cpp @@ -545,7 +545,6 @@ void Species::setTrfrRules(const transferRules t) { habMort = t.habMort; moveType = t.moveType; costMap = t.costMap; -//setGenome(); } transferRules Species::getTransferRules(void) { @@ -611,7 +610,7 @@ void Species::setSpMovtTraits(const trfrMovtParams m) { if (m.stepMort >= 0.0 && m.stepMort <= 1.0) stepMort = m.stepMort; if (m.stepLength > 0.0) stepLength = m.stepLength; if (m.rho > 0.0 && m.rho <= 1.0) rho = m.rho; - straigtenPath = m.straigtenPath; + straightenPath = m.straightenPath; } trfrMovtParams Species::getSpMovtTraits(void) { From 6f7bd05ffc0164ceefbec4d4a7c25054a75028e3 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Sat, 8 Jun 2024 19:19:10 +0100 Subject: [PATCH 133/332] inverted fis and fit; refactor some neutral stats --- NeutralStatsManager.cpp | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 307bce3..5c72d95 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -279,39 +279,39 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int double inverseNtotal; double sumWeights = 0; double nBar, nC, inverseNbar; - unsigned int nbPopulatedPatches = 0; + unsigned int nbPops = 0; const int ploidy = pSpecies->isDiploid() ? 2 : 1; - const int totalSampleSize = nbSampledIndsInComm * ploidy; + const int globalSampleSize = nbSampledIndsInComm * ploidy; // total nb of alleles for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop != 0) { - int sampleSize = pPop->sampleSize() * ploidy; - if (sampleSize > 0) { - nbPopulatedPatches++; - sumWeights += static_cast(sampleSize * sampleSize) / totalSampleSize; + int popSampleSize = pPop->sampleSize() * ploidy; + if (popSampleSize > 0) { + nbPops++; + sumWeights += static_cast(popSampleSize * popSampleSize) / globalSampleSize; } } } - nbExtantPops = nbPopulatedPatches; - totalNbSampledInds = nbSampledIndsInComm; // r * nBar + nbExtantPops = nbPops; + totalNbSampledInds = nbSampledIndsInComm; - if (nbPopulatedPatches > 1) { + if (nbPops > 1) { // Calculate F stats - nBar = static_cast(totalSampleSize) / nbPopulatedPatches; // average sample size, cannot be less than 1 - nC = (totalSampleSize - sumWeights) / nbPopulatedPatches - 1; + nBar = static_cast(globalSampleSize) / nbPops; // average sample size, cannot be less than 1 + nC = (globalSampleSize - sumWeights) / nbPops - 1; double nBarMinusOne = (nBar == 1.0) ? 1.0 : nBar - 1.0; // avoid / 0 if exactly 1 ind per pop inverseNbar = 1.0 / nBarMinusOne; - inverseNtotal = 1.0 / nbSampledIndsInComm; + inverseNtotal = 1.0 / globalSampleSize; double var; double s2, pBar, hBar; - double s2Denom = 1.0 / ((nbPopulatedPatches - 1) * nBar); - double rTerm = static_cast(nbPopulatedPatches - 1) / nbPopulatedPatches; - double hBarFactor = (2 * nBarMinusOne) / (4 * nBar); + double s2Denom = 1.0 / ((nbPops - 1) * nBar); + double rTerm = static_cast (nbPops - 1) / nbPops; + double hBarFactor = (2 * nBar - 1) / (4 * nBar); double a = 0, b = 0, c = 0, intermediateTerm; for (int thisLocus = 0; thisLocus < nLoci; ++thisLocus) { @@ -346,8 +346,8 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int c *= 0.5; fst = a / (a + b + c); // theta hat in eq. 1 in WC 1984 - fis = (a + b) / (a + b + c); // F hat - fit = b / (b + c); // f hat + fis = b / (b + c); // f hat + fit = (a + b) / (a + b + c); // F hat } else { // zero or one sampled pops, cannot compute F stats fst = 0.0; @@ -621,12 +621,12 @@ void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, con double pi, pj; for (int l = 0; l < nLoci; ++l) for (int u = 0; u < nAlleles; ++u) - for (int i = 0; i < nPatches - 1; ++i) { + for (int i = 0; i < nPatches - 1; ++i) { // nPatches-1 bc bottom row not filled if (popSizes[i] == 0) continue; const auto patch = pLandscape->findPatch(patchVect[i]); const auto pPopI = (Population*)patch->getPopn((intptr)pSpecies); - for (int j = i + 1; j < nPatches; ++j) { + for (int j = i + 1; j < nPatches; ++j) { // fill only upper half of matrix if (popSizes[j] == 0) continue; const auto patch = pLandscape->findPatch(patchVect[j]); const auto pPopJ = (Population*)patch->getPopn((intptr)pSpecies); From d6eb56c9c9e0afd979f8fd6aa50ca4c0e3f6cf62 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 11 Jun 2024 13:34:37 +0100 Subject: [PATCH 134/332] fix bug with inverted sexes --- Individual.cpp | 100 ++++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 52 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 2ec4871..1901924 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -38,7 +38,7 @@ Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short rep geneticFitness = 1.0; stage = stg; if (probmale <= 0.0) sex = FEM; - else sex = pRandom->Bernoulli(probmale) ? FEM : MAL; + else sex = pRandom->Bernoulli(probmale) ? MAL : FEM; age = a; status = 0; @@ -1621,19 +1621,18 @@ void Individual::forceInitCRW(const trfrMovtParams& m) { pCRW->stepL = m.stepLength; pCRW->rho = m.rho; setCRW(pCRW); } -*/ + void Individual::setInitAngle(const float angle) { crw->prevdrn = angle; } - - +*/ void testIndividual() { // Kernel-based transfer { - // Simple cell-based landscape layout + // Simple 5*5 cell-based landscape layout landParams ls_params; ls_params.dimX = ls_params.dimY = 5; ls_params.minX = ls_params.minY = 0; @@ -1684,24 +1683,22 @@ void testIndividual() { Patch* init_patch = (Patch*)init_cell->getPatch(); // Create and set up individual - //Individual starting_ind(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); - // Set aside original individual and test on a copy - Individual ind(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); - int isDispersing = ind.moveKernel(&ls, &sp, false); + Individual ind1(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + int isDispersing = ind1.moveKernel(&ls, &sp, false); // After moving, individual should be in the only available cell - Cell* curr_cell = ind.getCurrCell(); + Cell* curr_cell = ind1.getCurrCell(); assert(curr_cell != init_cell); assert(curr_cell == final_cell); - assert(ind.getStatus() == 2); // potential settler + assert(ind1.getStatus() == 2); // potential settler // If no cell within reasonable dispersal reach, individual does not move and dies kern.meanDist1 = 1.0; sp.setSpKernTraits(0, 0, kern, ls_params.resol); - ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual - isDispersing = ind.moveKernel(&ls, &sp, false); - curr_cell = ind.getCurrCell(); - assert(ind.getStatus() == 6); // RIP in peace + Individual ind2(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual + isDispersing = ind2.moveKernel(&ls, &sp, false); + curr_cell = ind2.getCurrCell(); + assert(ind2.getStatus() == 6); // RIP in peace assert(curr_cell == init_cell); // Twin kernels @@ -1711,14 +1708,14 @@ void testIndividual() { kern.meanDist2 = 5.0; // easily reaches suitable cell... kern.probKern1 = 1.0; // ... but never used sp.setSpKernTraits(0, 0, kern, ls_params.resol); - ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); - isDispersing = ind.moveKernel(&ls, &sp, false); - assert(ind.getStatus() == 6); + Individual ind3(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + isDispersing = ind3.moveKernel(&ls, &sp, false); + assert(ind3.getStatus() == 6); // dead, could not reach destination cell kern.probKern1 = 0.0; // always use second kernel sp.setSpKernTraits(0, 0, kern, ls_params.resol); - ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); - isDispersing = ind.moveKernel(&ls, &sp, false); - assert(ind.getStatus() == 2); + Individual ind4(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + isDispersing = ind4.moveKernel(&ls, &sp, false); + assert(ind4.getStatus() == 2); // reset trfr.twinKern = false; sp.setTrfrRules(trfr); @@ -1735,14 +1732,14 @@ void testIndividual() { kern_m.meanDist1 = 5.0; // male easily reaches suitable cell sp.setSpKernTraits(0, 1, kern_m, ls_params.resol); - ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // female as default - isDispersing = ind.moveKernel(&ls, &sp, false); - assert(ind.getStatus() == 6); + Individual ind5(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // female as default + isDispersing = ind5.moveKernel(&ls, &sp, false); + assert(ind5.getStatus() == 6); // dead, could not reach destination - ind = Individual(init_cell, init_patch, 1, 0, 0, 1.0, false, 0); // male - assert(ind.getSex() == 1); - isDispersing = ind.moveKernel(&ls, &sp, false); - assert(ind.getStatus() == 2); + Individual ind6(init_cell, init_patch, 1, 0, 0, 1.0, false, 0); // male + assert(ind6.getSex() == 1); + isDispersing = ind6.moveKernel(&ls, &sp, false); + assert(ind6.getStatus() == 2); // reset trfr.sexDep = false; sp.setTrfrRules(trfr); @@ -1757,13 +1754,13 @@ void testIndividual() { kern_adult.meanDist1 = 5.0; // adults easily reach suitable cell sp.setSpKernTraits(1, 0, kern_adult, ls_params.resol); - ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, false, 0); // juvenile - isDispersing = ind.moveKernel(&ls, &sp, false); - assert(ind.getStatus() == 6); + Individual ind7(init_cell, init_patch, 0, 0, 0, 0.0, false, 0); // juvenile + isDispersing = ind7.moveKernel(&ls, &sp, false); + assert(ind7.getStatus() == 6); - ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // adult by default - isDispersing = ind.moveKernel(&ls, &sp, false); - assert(ind.getStatus() == 2); + Individual ind8(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // adult by default + isDispersing = ind8.moveKernel(&ls, &sp, false); + assert(ind8.getStatus() == 2); // reset trfr.stgDep = false; sp.setTrfrRules(trfr); @@ -1793,21 +1790,21 @@ void testIndividual() { kern.meanDist1 = 10; // overshoots *most* of the time... sp.setSpKernTraits(0, 0, kern, ls_params.resol); - ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual + Individual ind9(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual // Non-absorbing boundaries bool absorbing_boundaries{ false }; - isDispersing = ind.moveKernel(&ls, &sp, absorbing_boundaries); - curr_cell = ind.getCurrCell(); + isDispersing = ind9.moveKernel(&ls, &sp, absorbing_boundaries); + curr_cell = ind9.getCurrCell(); assert(curr_cell != init_cell); // ...should be able to move eventually - assert(ind.getStatus() == 2); + assert(ind9.getStatus() == 2); // Absorbing boundaries absorbing_boundaries = true; - ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual - isDispersing = ind.moveKernel(&ls, &sp, absorbing_boundaries); - curr_cell = ind.getCurrCell(); - assert(ind.getStatus() == 6); + Individual ind10(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual + isDispersing = ind10.moveKernel(&ls, &sp, absorbing_boundaries); + curr_cell = ind10.getCurrCell(); + assert(ind10.getStatus() == 6); assert(curr_cell == 0); // out of the landscape // Dispersal-related mortality @@ -1816,9 +1813,9 @@ void testIndividual() { sp.setMortParams(mort); trfr.distMort = false; sp.setTrfrRules(trfr); - ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); - isDispersing = ind.moveKernel(&ls, &sp, false); - assert(ind.getStatus() == 7); + Individual ind11(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + isDispersing = ind11.moveKernel(&ls, &sp, false); + assert(ind11.getStatus() == 7); // Distance-dependent mortality trfr.distMort = true; sp.setTrfrRules(trfr); @@ -1827,14 +1824,14 @@ void testIndividual() { sp.setMortParams(mort); kern.meanDist1 = 5; // very likely to go over threshold sp.setSpKernTraits(0, 0, kern, ls_params.resol); - ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); - isDispersing = ind.moveKernel(&ls, &sp, false); - assert(ind.getStatus() == 7); + Individual ind12(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + isDispersing = ind12.moveKernel(&ls, &sp, false); + assert(ind12.getStatus() == 7); mort.mortBeta = 30; // very large distance, unlikely to draw sp.setMortParams(mort); - ind = Individual(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); - isDispersing = ind.moveKernel(&ls, &sp, false); - assert(ind.getStatus() != 7); + Individual ind13(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + isDispersing = ind13.moveKernel(&ls, &sp, false); + assert(ind13.getStatus() != 7); // Reset mortality params trfr.distMort = false; @@ -1842,7 +1839,6 @@ void testIndividual() { sp.setTrfrRules(trfr); sp.setMortParams(mort); - ind.~Individual(); } /* From 1f203055cd7e8e7fd44b468571fd1035ccf0ba18 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 11 Jun 2024 13:34:52 +0100 Subject: [PATCH 135/332] resolve kernel tests merge --- Landscape.cpp | 2 +- Main.cpp | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index 163d60f..773955c 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -905,7 +905,7 @@ void Landscape::updateCarryingCapacity(Species* pSpecies, int yr, short landIx) int npatches = (int)patches.size(); for (int i = 0; i < npatches; i++) { if (patches[i]->getPatchNum() != 0) { // not matrix patch - patches[i]->calculateKXY(pSpecies, landlimits, + patches[i]->setCarryingCapacity(pSpecies, landlimits, getGlobalStoch(yr), nHab, rasterType, landIx, gradK); } } diff --git a/Main.cpp b/Main.cpp index 9845cae..63faf8a 100644 --- a/Main.cpp +++ b/Main.cpp @@ -84,15 +84,6 @@ int _tmain(int argc, _TCHAR* argv[]) pRandom = new RSrandom; assert(0.1 > 0.0); // assert does run correctly - try { - run_unit_tests(); - } - catch (const runtime_error& e) { - cerr << e.what(); - } - catch (const logic_error& e) { - cerr << e.what(); - } try { run_unit_tests(); From 12a87de029608ab4c2d2f5139f5e110398ecb8cb Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 11 Jun 2024 14:53:47 +0100 Subject: [PATCH 136/332] fix CRW test merge + cleanup --- Individual.cpp | 145 ++++++++++++++++++------------------------------- Individual.h | 4 -- 2 files changed, 52 insertions(+), 97 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 1901924..e5dcd5b 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -563,7 +563,8 @@ void Individual::setIndCRWTraits(Species* pSpecies) { // Get phenotypic transfer by CRW traits trfrCRWTraits Individual::getIndCRWTraits(void) { - trfrCRWTraits c; c.stepLength = c.rho = 0.0; + trfrCRWTraits c; + c.stepLength = c.rho = 0.0; if (pTrfrData != 0) { auto& pCRW = dynamic_cast(*pTrfrData); c.stepLength = pCRW.stepLength; @@ -1594,39 +1595,11 @@ Cell* Individual::getCurrCell() const { return pCurrCell; } -void Individual::setPath(pathData* pPath) { - path = pPath; -} - -void Individual::setCRW(crwData* pCRW) { - pTrfrData = make_unique(pCRW->prevdrn, pCRW->xc, pCRW->yc); -} - -// TP: Both functions below are a bad fix to an issue I have for testing -// Smh upon exiting individual initialisation path and CRW get deallocated -// Force initialisation of path -void Individual::forceInitPath() { - pathData* pPath = new pathData; - pPath->out = pPath->year = pPath->total = 0; - pPath->pSettPatch = 0; pPath->settleStatus = 0; - setPath(pPath); -} -// Force initialisation of crw -/* -void Individual::forceInitCRW(const trfrMovtParams& m) { - float prevdrn = (float)(pRandom->Random() * 2.0 * PI); - float xc = ((float)pRandom->Random() * 0.999f) + (float)pCurrCell->getLocn().x; - float yc = ((float)pRandom->Random() * 0.999f) + (float)pCurrCell->getLocn().y; - std::unique_ptr pCRW = make_unique(prevdrn, xc, yc); - pCRW->stepL = m.stepLength; pCRW->rho = m.rho; - setCRW(pCRW); -} - - void Individual::setInitAngle(const float angle) { - crw->prevdrn = angle; + auto pCRW = dynamic_cast(pTrfrData.get()); + pCRW->prevdrn = angle; } -*/ + void testIndividual() { @@ -1841,7 +1814,6 @@ void testIndividual() { } - /* // Correlated random walk (CRW) { // Simple cell-based landscape layout @@ -1908,35 +1880,33 @@ void testIndividual() { Patch* init_patch = (Patch*)init_cell->getPatch(); // Create and set up individual - Individual ind(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); + Individual ind0(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); // Set status - assert(ind.getStatus() == 0); // default status, not emigrating - int isDispersing = ind.moveStep(&ls, &sp, hab_index, false); - assert(ind.getStatus() == 0); // status didn't change - assert(ind.getCurrCell() == init_cell); // not emigrating so didn't move + assert(ind0.getStatus() == 0); // default status, not emigrating + int isDispersing = ind0.moveStep(&ls, &sp, hab_index, false); + assert(ind0.getStatus() == 0); // status didn't change + assert(ind0.getCurrCell() == init_cell); // not emigrating so didn't move // Per-step mortality m.stepMort = 1.0; // should die sp.setSpMovtTraits(m); - ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + Individual ind1(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); // force set path bc for some reason path gets deallocated upon exiting constructor?? - ind.forceInitPath(); - ind.forceInitCRW(m); - ind.setStatus(1); - isDispersing = ind.moveStep(&ls, &sp, hab_index, false); + ind1.setStatus(1); + isDispersing = ind1.moveStep(&ls, &sp, hab_index, false); // Individual begins in natal patch so mortality is disabled - assert(ind.getStatus() != 7); + assert(ind1.getStatus() != 7); // Individual should be in a different patch - Cell* first_step_cell = ind.getCurrCell(); + Cell* first_step_cell = ind1.getCurrCell(); assert(first_step_cell != init_cell); assert((Patch*)first_step_cell->getPatch() != init_patch); - ind.setStatus(1); // emigrating again + ind1.setStatus(1); // emigrating again // Individual should die on second step - isDispersing = ind.moveStep(&ls, &sp, hab_index, false); - assert(ind.getCurrCell() == first_step_cell); // shouldn't have moved - assert(ind.getStatus() == 7); // died by transfer + isDispersing = ind1.moveStep(&ls, &sp, hab_index, false); + assert(ind1.getCurrCell() == first_step_cell); // shouldn't have moved + assert(ind1.getStatus() == 7); // died by transfer m.stepMort = 0.0; // not dying sp.setSpMovtTraits(m); @@ -1973,60 +1943,52 @@ void testIndividual() { steps.maxStepsYr = 2; steps.maxSteps = 3; sp.setSteps(0, 0, steps); - ind = Individual(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); - ind.setStatus(1); // dispersing - ind.forceInitPath(); - ind.forceInitCRW(m); + Individual ind2(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); + ind2.setStatus(1); // dispersing // First step - still in unsuitable cell so still dispersing - isDispersing = ind.moveStep(&ls, &sp, hab_index, false); - assert(ind.getCurrCell() == init_cell); - assert(ind.getStatus() == 1); + isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); + assert(ind2.getCurrCell() == init_cell); + assert(ind2.getStatus() == 1); // Second step - reaching max steps this year, wait next year - isDispersing = ind.moveStep(&ls, &sp, hab_index, false); - assert(ind.getCurrCell() == init_cell); - assert(ind.getStatus() == 3); - ind.setStatus(1); // dispersing again + isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); + assert(ind2.getCurrCell() == init_cell); + assert(ind2.getStatus() == 3); + ind2.setStatus(1); // dispersing again // Third step - reaching max steps, dies in unsuitable cell - isDispersing = ind.moveStep(&ls, &sp, hab_index, false); - assert(ind.getCurrCell() == init_cell); - assert(ind.getStatus() == 6); + isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); + assert(ind2.getCurrCell() == init_cell); + assert(ind2.getStatus() == 6); // Step length too long m.stepLength = ls_params.dimX * SQRT2 * 1.5; // overshoots sp.setSpMovtTraits(m); - ind = Individual(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); - ind.setStatus(1); // dispersing - ind.forceInitPath(); - ind.forceInitCRW(m); + Individual ind3(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + ind3.setStatus(1); // dispersing steps.minSteps = 1; steps.maxStepsYr = 1; steps.maxSteps = 1; // no need to test more than one step this time sp.setSteps(0, 0, steps); - isDispersing = ind.moveStep(&ls, &sp, hab_index, false); - assert(ind.getCurrCell() == init_cell); - assert(ind.getStatus() == 6); + isDispersing = ind3.moveStep(&ls, &sp, hab_index, false); + assert(ind3.getCurrCell() == init_cell); + assert(ind3.getStatus() == 6); // Adequate step length m.stepLength = (ls_params.dimX - 1) * SQRT2; sp.setSpMovtTraits(m); - ind = Individual(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); - ind.setStatus(1); // dispersing - ind.forceInitPath(); - ind.forceInitCRW(m); + Individual ind4(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); + ind4.setStatus(1); // dispersing // Initial angle still random but should eventually reach the suitable cell - isDispersing = ind.moveStep(&ls, &sp, hab_index, false); - assert(ind.getStatus() == 2); - assert(ind.getCurrCell() == final_cell); + isDispersing = ind4.moveStep(&ls, &sp, hab_index, false); + assert(ind4.getStatus() == 2); + assert(ind4.getCurrCell() == final_cell); // If boundaries are absorbing however, most likely to die - ind = Individual(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); - ind.setStatus(1); // dispersing - ind.forceInitPath(); - ind.forceInitCRW(m); + Individual ind5(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); + ind5.setStatus(1); // dispersing bool absorbing_boundaries = true; - isDispersing = ind.moveStep(&ls, &sp, hab_index, absorbing_boundaries); - assert(ind.getStatus() == 6); - assert(ind.getCurrCell() == 0); // deref apparently + isDispersing = ind5.moveStep(&ls, &sp, hab_index, absorbing_boundaries); + assert(ind5.getStatus() == 6); + assert(ind5.getCurrCell() == 0); // deref apparently // Correlation parameter // If rho = 1 should move in a straight line @@ -2053,20 +2015,17 @@ void testIndividual() { sp.setSpMovtTraits(m); steps.maxStepsYr = steps.maxSteps = ls_params.dimX; sp.setSteps(0, 0, steps); - ind = Individual(cell_vec[0], natalPatch, 0, 0, 0, 0.0, true, 2); - ind.forceInitPath(); - ind.forceInitCRW(m); + Individual ind6(cell_vec[0], natalPatch, 0, 0, 0, 0.0, true, 2); const float diag_angle = PI / 4.0; // 45 degrees - ind.setInitAngle(diag_angle); + ind6.setInitAngle(diag_angle); // Individual moves only along diagonal cells for (int i = 1; i < ls_params.dimX; ++i) { - ind.setStatus(1); // dispersing - isDispersing = ind.moveStep(&ls, &sp, hab_index, false); - assert(ind.getStatus() == 2); - assert(ind.getCurrCell() == cell_vec[i * (ls_params.dimX + 1)]); + ind6.setStatus(1); // dispersing + isDispersing = ind6.moveStep(&ls, &sp, hab_index, false); + assert(ind6.getStatus() == 2); + assert(ind6.getCurrCell() == cell_vec[i * (ls_params.dimX + 1)]); } } - */ } #endif // RSDEBUG diff --git a/Individual.h b/Individual.h index 40d1085..d63d799 100644 --- a/Individual.h +++ b/Individual.h @@ -345,10 +345,6 @@ class Individual { #if RSDEBUG // Testing utilities Cell* getCurrCell() const; - void setPath(pathData* pPath); - void setCRW(crwData* pCRW); - void forceInitPath(); - //void forceInitCRW(const trfrMovtTraits&); void setInitAngle(const float angle); #endif From 08db4d161a0484713b673ca499e256bfef4604ef Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 11 Jun 2024 16:00:27 +0100 Subject: [PATCH 137/332] trigger build, try to id source of floating point exception in tests --- Individual.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Individual.cpp b/Individual.cpp index e5dcd5b..88ece01 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1595,6 +1595,7 @@ Cell* Individual::getCurrCell() const { return pCurrCell; } + void Individual::setInitAngle(const float angle) { auto pCRW = dynamic_cast(pTrfrData.get()); pCRW->prevdrn = angle; @@ -1815,6 +1816,7 @@ void testIndividual() { } // Correlated random walk (CRW) + /* { // Simple cell-based landscape layout landParams ls_params; @@ -2026,6 +2028,7 @@ void testIndividual() { assert(ind6.getCurrCell() == cell_vec[i * (ls_params.dimX + 1)]); } } + */ } #endif // RSDEBUG From a6b2faf22378a7248638f1771e3b334c553878a5 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 11 Jun 2024 16:02:10 +0100 Subject: [PATCH 138/332] just making sure it's bc of tests --- Individual.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Individual.cpp b/Individual.cpp index 88ece01..ba341b4 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1606,6 +1606,7 @@ void testIndividual() { // Kernel-based transfer { + /* // Simple 5*5 cell-based landscape layout landParams ls_params; ls_params.dimX = ls_params.dimY = 5; @@ -1739,6 +1740,8 @@ void testIndividual() { trfr.stgDep = false; sp.setTrfrRules(trfr); + + /* Boundaries: dispersal distance overshoots Only adjacent cells are available ----- @@ -1746,7 +1749,6 @@ void testIndividual() { -oio- -ooo- ----- - */ ls.setCellArray(); // reset cells vector cells; // Set central cell and all adjacent @@ -1813,6 +1815,7 @@ void testIndividual() { sp.setTrfrRules(trfr); sp.setMortParams(mort); + */ } // Correlated random walk (CRW) From 971b48462fc1890efbb61a07467dcd3381c48f0f Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 11 Jun 2024 16:12:12 +0100 Subject: [PATCH 139/332] disable tests for debugging --- Landscape.cpp | 5 +++-- Population.cpp | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index 773955c..ffe0a49 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -2668,11 +2668,12 @@ Landscape createLandscapeFromCells(vector cells, const landParams& lp, Sp void testLandscape() { // test coordinate system + /* Landscape ls; landParams ls_params; ls_params.dimX = ls_params.dimY = 100; - ls.setLandParams(ls_params, true); - + ls.setLandParams(ls_params, true) + */ } #endif // RSDEBUG diff --git a/Population.cpp b/Population.cpp index 1c0b299..5ee8dda 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1978,6 +1978,7 @@ void Population::outputGeneValues(ofstream& ofsGenes, const int& yr, const int& #if RSDEBUG void testPopulation() { + /* int resol{ 1 }; int nInds{ 10 }; Species* pSpecies; @@ -1986,7 +1987,6 @@ void testPopulation() assert(p.getNInds() == 0); // disperser disp; // p.extractDisperser - /* short nStages; // 0 short nSexes; // 0 Species *pSpecies; // NULL // pointer to the species @@ -1994,7 +1994,7 @@ void testPopulation() int nInds[NSTAGES][NSEXES]; // undef // no. of individuals in each stage/sex std::vector inds; // undef // all individuals in population except ... std::vector juvs; // undef - */ cout << "All tests for Population have run." << endl; + */ } #endif // RSDEBUG From 1e403dbd1d95f922a18f3740a88166623c917f16 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 11 Jun 2024 16:15:25 +0100 Subject: [PATCH 140/332] issue is with pop or landscape test --- Individual.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index ba341b4..b1d9883 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1606,7 +1606,6 @@ void testIndividual() { // Kernel-based transfer { - /* // Simple 5*5 cell-based landscape layout landParams ls_params; ls_params.dimX = ls_params.dimY = 5; @@ -1749,6 +1748,7 @@ void testIndividual() { -oio- -ooo- ----- + */ ls.setCellArray(); // reset cells vector cells; // Set central cell and all adjacent @@ -1814,12 +1814,9 @@ void testIndividual() { mort.fixedMort = 0.0; sp.setTrfrRules(trfr); sp.setMortParams(mort); - - */ } // Correlated random walk (CRW) - /* { // Simple cell-based landscape layout landParams ls_params; @@ -2031,7 +2028,6 @@ void testIndividual() { assert(ind6.getCurrCell() == cell_vec[i * (ls_params.dimX + 1)]); } } - */ } #endif // RSDEBUG From a6e9275406c56f37b5b38b43431a254d96d6d3c4 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 11 Jun 2024 16:19:11 +0100 Subject: [PATCH 141/332] can't be the 4 lines in test_landscape can it --- Landscape.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index ffe0a49..e7ad841 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -2668,12 +2668,10 @@ Landscape createLandscapeFromCells(vector cells, const landParams& lp, Sp void testLandscape() { // test coordinate system - /* Landscape ls; landParams ls_params; ls_params.dimX = ls_params.dimY = 100; - ls.setLandParams(ls_params, true) - */ + ls.setLandParams(ls_params, true); } #endif // RSDEBUG From ee46e5fe7bce241947c8d63a9fa4b90c6dea8be4 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 11 Jun 2024 16:19:11 +0100 Subject: [PATCH 142/332] can't be the 4 lines in test_landscape can it --- Landscape.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index ffe0a49..dfcfa9a 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -2667,13 +2667,7 @@ Landscape createLandscapeFromCells(vector cells, const landParams& lp, Sp } void testLandscape() { - // test coordinate system - /* - Landscape ls; - landParams ls_params; - ls_params.dimX = ls_params.dimY = 100; - ls.setLandParams(ls_params, true) - */ + // test coordinate system... } #endif // RSDEBUG From 6074a489a15d7d7c2140dd3b215d957b69741909 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 11 Jun 2024 16:22:53 +0100 Subject: [PATCH 143/332] think I got it --- Population.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Population.cpp b/Population.cpp index 5ee8dda..336cda4 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1978,13 +1978,13 @@ void Population::outputGeneValues(ofstream& ofsGenes, const int& yr, const int& #if RSDEBUG void testPopulation() { - /* int resol{ 1 }; int nInds{ 10 }; Species* pSpecies; Patch* pPatch; Population p; assert(p.getNInds() == 0); + /* // disperser disp; // p.extractDisperser short nStages; // 0 @@ -1994,7 +1994,6 @@ void testPopulation() int nInds[NSTAGES][NSEXES]; // undef // no. of individuals in each stage/sex std::vector inds; // undef // all individuals in population except ... std::vector juvs; // undef - cout << "All tests for Population have run." << endl; */ } #endif // RSDEBUG From e69662e8434193b6e10047122e1892525f3cfd9b Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 11 Jun 2024 16:41:59 +0100 Subject: [PATCH 144/332] debug test macOS --- Individual.cpp | 7 +++++-- Population.cpp | 18 +----------------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index b1d9883..cce8a75 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1818,7 +1818,7 @@ void testIndividual() { // Correlated random walk (CRW) { - // Simple cell-based landscape layout + // Simple 5*5 cell-based landscape layout landParams ls_params; ls_params.dimX = ls_params.dimY = 5; ls_params.minX = ls_params.minY = 0; @@ -1846,7 +1846,7 @@ void testIndividual() { // Habitat codes sp.createHabK(1); - sp.setHabK(hab_index, 100.0); // one habitat with K = 10 + sp.setHabK(hab_index, 100.0); // one habitat with K = 100 // Habitat-dependent mortality sp.createHabCostMort(1); @@ -1889,6 +1889,7 @@ void testIndividual() { int isDispersing = ind0.moveStep(&ls, &sp, hab_index, false); assert(ind0.getStatus() == 0); // status didn't change assert(ind0.getCurrCell() == init_cell); // not emigrating so didn't move + assert((Patch*)init_cell->getPatch() == init_patch); // Per-step mortality m.stepMort = 1.0; // should die @@ -1902,6 +1903,8 @@ void testIndividual() { // Individual should be in a different patch Cell* first_step_cell = ind1.getCurrCell(); assert(first_step_cell != init_cell); + + assert((Patch*)init_cell->getPatch() == init_patch); assert((Patch*)first_step_cell->getPatch() != init_patch); ind1.setStatus(1); // emigrating again diff --git a/Population.cpp b/Population.cpp index 336cda4..0871a48 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1978,22 +1978,6 @@ void Population::outputGeneValues(ofstream& ofsGenes, const int& yr, const int& #if RSDEBUG void testPopulation() { - int resol{ 1 }; - int nInds{ 10 }; - Species* pSpecies; - Patch* pPatch; - Population p; - assert(p.getNInds() == 0); - /* - // disperser disp; - // p.extractDisperser - short nStages; // 0 - short nSexes; // 0 - Species *pSpecies; // NULL // pointer to the species - Patch *pPatch; // NULL // pointer to the patch - int nInds[NSTAGES][NSEXES]; // undef // no. of individuals in each stage/sex - std::vector inds; // undef // all individuals in population except ... - std::vector juvs; // undef - */ + // test population... } #endif // RSDEBUG From 9db4142050937e21ddf367bb38c7f18064370353 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 11 Jun 2024 17:28:45 +0100 Subject: [PATCH 145/332] need to see patch ids --- Individual.cpp | 8 ++++++-- Landscape.h | 6 ++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index cce8a75..f468410 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1889,7 +1889,6 @@ void testIndividual() { int isDispersing = ind0.moveStep(&ls, &sp, hab_index, false); assert(ind0.getStatus() == 0); // status didn't change assert(ind0.getCurrCell() == init_cell); // not emigrating so didn't move - assert((Patch*)init_cell->getPatch() == init_patch); // Per-step mortality m.stepMort = 1.0; // should die @@ -1904,7 +1903,12 @@ void testIndividual() { Cell* first_step_cell = ind1.getCurrCell(); assert(first_step_cell != init_cell); - assert((Patch*)init_cell->getPatch() == init_patch); + for (int i = 0; i < cell_vec.size(); i++) { + //if (i == 12) assert(cell_vec[i].) + } + + ls.printPatches(); + assert((Patch*)first_step_cell->getPatch() != init_patch); ind1.setStatus(1); // emigrating again diff --git a/Landscape.h b/Landscape.h index 00767a1..75837da 100644 --- a/Landscape.h +++ b/Landscape.h @@ -455,6 +455,12 @@ class Landscape { void resetVisits(void); void outVisits(int, int); // save SMS path visits map to raster text file + void printPatches() { + for (int x = 0; x < 5; ++x) + for (int y = 0; y < 5; ++y) + cout << cells[x][y]->getPatch() << endl; + } + private: bool generated; // artificially generated? bool patchModel; // From ea3ecad3a646d064c1a145910963820a7850ee8f Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 11 Jun 2024 17:32:57 +0100 Subject: [PATCH 146/332] funky stuff uh --- Individual.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Individual.cpp b/Individual.cpp index f468410..4c86804 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1881,6 +1881,9 @@ void testIndividual() { ls.updateCarryingCapacity(&sp, 0, 0); Patch* init_patch = (Patch*)init_cell->getPatch(); + ls.printPatches(); + + // Create and set up individual Individual ind0(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); @@ -1907,6 +1910,7 @@ void testIndividual() { //if (i == 12) assert(cell_vec[i].) } + cout << endl << "After:" << endl; ls.printPatches(); assert((Patch*)first_step_cell->getPatch() != init_patch); From bb1e750bcd053bb09000f1879d05c2bc891c9135 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 12 Jun 2024 16:56:55 +0100 Subject: [PATCH 147/332] show me --- Individual.cpp | 10 +--------- Landscape.cpp | 6 +++++- Landscape.h | 2 +- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 4c86804..7ddc6fd 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1877,13 +1877,12 @@ void testIndividual() { sp.setSteps(0, 0, steps); // Set up patches - ls.allocatePatches(&sp); + ls.allocatePatches(&sp, true); ls.updateCarryingCapacity(&sp, 0, 0); Patch* init_patch = (Patch*)init_cell->getPatch(); ls.printPatches(); - // Create and set up individual Individual ind0(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); @@ -1906,13 +1905,6 @@ void testIndividual() { Cell* first_step_cell = ind1.getCurrCell(); assert(first_step_cell != init_cell); - for (int i = 0; i < cell_vec.size(); i++) { - //if (i == 12) assert(cell_vec[i].) - } - - cout << endl << "After:" << endl; - ls.printPatches(); - assert((Patch*)first_step_cell->getPatch() != init_patch); ind1.setStatus(1); // emigrating again diff --git a/Landscape.cpp b/Landscape.cpp index dfcfa9a..9998063 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -639,7 +639,7 @@ void Landscape::generatePatches() //--------------------------------------------------------------------------- /* Create a patch for each suitable cell of a cell-based landscape (all other habitat cells are added to the matrix patch) */ -void Landscape::allocatePatches(Species* pSpecies) +void Landscape::allocatePatches(Species* pSpecies, const bool& showMe) { float habK; Patch* pPatch; @@ -669,16 +669,20 @@ void Landscape::allocatePatches(Species* pSpecies) for (int i = 0; i < nhab; i++) { habK += pSpecies->getHabK(pCell->getHabIndex(i)); } + if (showMe) cout << "K = " << habK << "\t"; if (habK > 0.0) { // cell is suitable - create a patch for it patchnums.push_back(patchnum); pPatch = newPatch(patchnum++); + if (showMe) cout << "pPatch = " << pPatch << "\t"; addCellToPatch(pCell, pPatch); } else { // cell is not suitable - add to the matrix patch + if (showMe) cout << "matrixPatch = " << matrixPatch << "\t"; addCellToPatch(pCell, matrixPatch); pPatch = 0; } } + if (showMe) cout << endl; } } break; diff --git a/Landscape.h b/Landscape.h index 75837da..a8d6020 100644 --- a/Landscape.h +++ b/Landscape.h @@ -232,7 +232,7 @@ class Landscape { void addPatchNum(int); std::vector getPatchNums() const { return patchnums; } void generatePatches(); // create an artificial landscape - void allocatePatches(Species*); // create patches for a cell-based landscape + void allocatePatches(Species*, const bool& showMe = false); // create patches for a cell-based landscape Patch* newPatch( int // patch sequential no. (id no. is set to equal sequential no.) ); From 7b74340b3e47a0c4f50bee44d44c19cd6476e019 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 12 Jun 2024 17:10:29 +0100 Subject: [PATCH 148/332] show me more --- Landscape.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Landscape.cpp b/Landscape.cpp index 9998063..1876048 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -645,6 +645,8 @@ void Landscape::allocatePatches(Species* pSpecies, const bool& showMe) Patch* pPatch; Cell* pCell; + if (showMe) cout << "we are allocating patches.\n"; + // delete all existing patches int npatches = (int)patches.size(); for (int i = 0; i < npatches; i++) { @@ -660,6 +662,7 @@ void Landscape::allocatePatches(Species* pSpecies, const bool& showMe) switch (rasterType) { case 0: // habitat codes + if (showMe) cout << "we using habitat codes.\n"; for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { if (cells[y][x] != 0) { // not no-data cell @@ -682,11 +685,15 @@ void Landscape::allocatePatches(Species* pSpecies, const bool& showMe) pPatch = 0; } } + else { + if (showMe) cout << "this cell is empty\n"; + } if (showMe) cout << endl; } } break; case 1: // habitat cover + if (showMe) cout << "we using habitat cover.\n"; for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { if (cells[y][x] != 0) { // not no-data cell @@ -711,6 +718,7 @@ void Landscape::allocatePatches(Species* pSpecies, const bool& showMe) } break; case 2: // habitat quality + if (showMe) cout << "we using habitat quality.\n"; for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { if (cells[y][x] != 0) { // not no-data cell From d8530a1df2e6f482908ddf95e28fa18fbc72cf3a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 12 Jun 2024 17:21:30 +0100 Subject: [PATCH 149/332] wcgw if I don't initialise my custom structs --- Individual.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Individual.cpp b/Individual.cpp index 7ddc6fd..1efc743 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1824,6 +1824,7 @@ void testIndividual() { ls_params.minX = ls_params.minY = 0; ls_params.maxX = ls_params.maxY = ls_params.dimX - 1; ls_params.resol = 1; + ls_params.rasterType = 0; double cellDiagLength = ls_params.resol * SQRT2; Landscape ls; From 24984680dee9c953a69422a564c129628367f21e Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 12 Jun 2024 18:17:35 +0100 Subject: [PATCH 150/332] default land params --- Individual.cpp | 27 +++++++-------------------- Landscape.cpp | 32 +++++++++++++++++++------------- Landscape.h | 9 ++------- 3 files changed, 28 insertions(+), 40 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 1efc743..3555eae 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1607,11 +1607,8 @@ void testIndividual() { // Kernel-based transfer { // Simple 5*5 cell-based landscape layout - landParams ls_params; - ls_params.dimX = ls_params.dimY = 5; - ls_params.minX = ls_params.minY = 0; - ls_params.maxX = ls_params.maxY = ls_params.dimX - 1; - ls_params.resol = 1; + int lsDim = 5; + landParams ls_params = createDefaultLandParams(lsDim); Landscape ls; ls.setLandParams(ls_params, true); @@ -1739,8 +1736,6 @@ void testIndividual() { trfr.stgDep = false; sp.setTrfrRules(trfr); - - /* Boundaries: dispersal distance overshoots Only adjacent cells are available ----- @@ -1819,12 +1814,8 @@ void testIndividual() { // Correlated random walk (CRW) { // Simple 5*5 cell-based landscape layout - landParams ls_params; - ls_params.dimX = ls_params.dimY = 5; - ls_params.minX = ls_params.minY = 0; - ls_params.maxX = ls_params.maxY = ls_params.dimX - 1; - ls_params.resol = 1; - ls_params.rasterType = 0; + int lsDim = 5; + landParams ls_params = createDefaultLandParams(lsDim); double cellDiagLength = ls_params.resol * SQRT2; Landscape ls; @@ -1878,12 +1869,10 @@ void testIndividual() { sp.setSteps(0, 0, steps); // Set up patches - ls.allocatePatches(&sp, true); + ls.allocatePatches(&sp); ls.updateCarryingCapacity(&sp, 0, 0); Patch* init_patch = (Patch*)init_cell->getPatch(); - ls.printPatches(); - // Create and set up individual Individual ind0(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); @@ -1999,10 +1988,8 @@ void testIndividual() { // Correlation parameter // If rho = 1 should move in a straight line // Many cells, all suitable - ls_params.dimX = ls_params.dimY = 10; - ls_params.minX = ls_params.minY = 0; - ls_params.maxX = ls_params.maxY = ls_params.dimX - 1; - ls_params.resol = 1; + lsDim = 10; + ls_params = createDefaultLandParams(lsDim); ls = Landscape(); ls.setLandParams(ls_params, true); cell_vec.clear(); diff --git a/Landscape.cpp b/Landscape.cpp index 1876048..05d9a9b 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -639,14 +639,12 @@ void Landscape::generatePatches() //--------------------------------------------------------------------------- /* Create a patch for each suitable cell of a cell-based landscape (all other habitat cells are added to the matrix patch) */ -void Landscape::allocatePatches(Species* pSpecies, const bool& showMe) +void Landscape::allocatePatches(Species* pSpecies) { float habK; Patch* pPatch; Cell* pCell; - if (showMe) cout << "we are allocating patches.\n"; - // delete all existing patches int npatches = (int)patches.size(); for (int i = 0; i < npatches; i++) { @@ -662,7 +660,6 @@ void Landscape::allocatePatches(Species* pSpecies, const bool& showMe) switch (rasterType) { case 0: // habitat codes - if (showMe) cout << "we using habitat codes.\n"; for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { if (cells[y][x] != 0) { // not no-data cell @@ -672,28 +669,20 @@ void Landscape::allocatePatches(Species* pSpecies, const bool& showMe) for (int i = 0; i < nhab; i++) { habK += pSpecies->getHabK(pCell->getHabIndex(i)); } - if (showMe) cout << "K = " << habK << "\t"; if (habK > 0.0) { // cell is suitable - create a patch for it patchnums.push_back(patchnum); pPatch = newPatch(patchnum++); - if (showMe) cout << "pPatch = " << pPatch << "\t"; addCellToPatch(pCell, pPatch); } else { // cell is not suitable - add to the matrix patch - if (showMe) cout << "matrixPatch = " << matrixPatch << "\t"; addCellToPatch(pCell, matrixPatch); pPatch = 0; } } - else { - if (showMe) cout << "this cell is empty\n"; - } - if (showMe) cout << endl; } } break; case 1: // habitat cover - if (showMe) cout << "we using habitat cover.\n"; for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { if (cells[y][x] != 0) { // not no-data cell @@ -718,7 +707,6 @@ void Landscape::allocatePatches(Species* pSpecies, const bool& showMe) } break; case 2: // habitat quality - if (showMe) cout << "we using habitat quality.\n"; for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { if (cells[y][x] != 0) { // not no-data cell @@ -2678,6 +2666,24 @@ Landscape createLandscapeFromCells(vector cells, const landParams& lp, Sp return ls; } +landParams createDefaultLandParams(const int& dim) { + + landParams ls_params; + ls_params.dimX = ls_params.dimY = dim; + ls_params.minX = ls_params.minY = 0; + ls_params.maxX = ls_params.maxY = ls_params.dimX - 1; + ls_params.resol = ls_params.spResol = 1; + ls_params.rasterType = 0; // habitat types + + ls_params.patchModel = false; + ls_params.spDist = false; + ls_params.generated = false; + ls_params.dynamic = false; + ls_params.landNum = 0; + ls_params.nHab = ls_params.nHabMax = 0; // irrelevant for habitat codes + return ls_params; +} + void testLandscape() { // test coordinate system... } diff --git a/Landscape.h b/Landscape.h index a8d6020..2af686d 100644 --- a/Landscape.h +++ b/Landscape.h @@ -232,7 +232,7 @@ class Landscape { void addPatchNum(int); std::vector getPatchNums() const { return patchnums; } void generatePatches(); // create an artificial landscape - void allocatePatches(Species*, const bool& showMe = false); // create patches for a cell-based landscape + void allocatePatches(Species*); // create patches for a cell-based landscape Patch* newPatch( int // patch sequential no. (id no. is set to equal sequential no.) ); @@ -455,12 +455,6 @@ class Landscape { void resetVisits(void); void outVisits(int, int); // save SMS path visits map to raster text file - void printPatches() { - for (int x = 0; x < 5; ++x) - for (int y = 0; y < 5; ++y) - cout << cells[x][y]->getPatch() << endl; - } - private: bool generated; // artificially generated? bool patchModel; // @@ -538,6 +532,7 @@ extern RSrandom* pRandom; #if RSDEBUG extern ofstream DEBUGLOG; +landParams createDefaultLandParams(const int& dim); void testLandscape(); #endif From d431346c3e84443d90fa6b15284178a44acdfe1a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 13 Jun 2024 10:59:11 +0100 Subject: [PATCH 151/332] tidy up --- Species.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/Species.cpp b/Species.cpp index 70ff4fe..65d5b24 100644 --- a/Species.cpp +++ b/Species.cpp @@ -30,12 +30,21 @@ Species::Species(void) // initialise demographic parameters repType = 0; nStages = 2; stageStruct = false; - propMales = 0.5; harem = 1.0; bc = 1.0; lambda = 1.5; probRep = 1.0; + propMales = 0.5; + harem = 1.0; + bc = 1.0; + lambda = 1.5; + probRep = 1.0; repSeasons = 1; - repInterval = 0; maxAge = 1000; survival = 1; - fecDens = false; fecStageDens = false; - devDens = false; devStageDens = false; - survDens = false; survStageDens = false; + repInterval = 0; + maxAge = 1000; + survival = 1; + fecDens = false; + fecStageDens = false; + devDens = false; + devStageDens = false; + survDens = false; + survStageDens = false; disperseOnLoss = false; for (int i = 0; i < gMaxNbStages; i++) { for (int j = 0; j < gMaxNbSexes; j++) { @@ -44,10 +53,12 @@ Species::Species(void) } } devCoeff = survCoeff = 1.0; - ddwtFec = ddwtDev = ddwtSurv = 0; ddwtFecDim = ddwtDevDim = ddwtSurvDim = 0; - habK = 0; habDimK = 0; - minRK = 1.0; maxRK = 2.0; - + ddwtFec = ddwtDev = ddwtSurv = 0; + ddwtFecDim = ddwtDevDim = ddwtSurvDim = 0; + habK = 0; + habDimK = 0; + minRK = 1.0; + maxRK = 2.0; // initialise emigration parameters densDepEmig = false; stgDepEmig = false; sexDepEmig = false; indVarEmig = false; From 69a8972d681c92cfc61b20817835e20e5c8b41c6 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 13 Jun 2024 15:35:44 +0100 Subject: [PATCH 152/332] don't think we need to pass full species just for level of ploidy --- SpeciesTrait.cpp | 8 +++----- SpeciesTrait.h | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 6ed9c3a..0fc0c44 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -9,7 +9,7 @@ SpeciesTrait::SpeciesTrait( const DistributionType& dominanceDist, const map dominanceParams, bool isInherited, const float& mutRate, const DistributionType& mutationDist, const map mutationParams, - Species* pSpecies) : + const int nPloidy) : traitType{ trType }, sex{ sx }, genePositions{ pos }, @@ -21,11 +21,9 @@ SpeciesTrait::SpeciesTrait( inherited{ isInherited }, mutationDistribution{ mutationDist }, mutationParameters{ mutationParams }, - mutationRate{ mutRate } + mutationRate{ mutRate }, + ploidy{ nPloidy } { - // Initialise ploidy only once per species - if (ploidy == NULL) this->ploidy = pSpecies->isDiploid() ? 2 : 1; - // Check distribution parameters // Initial distribution for (auto [paramType, paramVal] : initParams) { diff --git a/SpeciesTrait.h b/SpeciesTrait.h index ef68e9a..ca8ca94 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -28,7 +28,7 @@ class SpeciesTrait { const float& mutationRate, const DistributionType& mutationDist, const map mutationParams, - Species* pSpecies + const int ploidy ); bool isValidTraitVal(const float& val) const; @@ -52,7 +52,7 @@ class SpeciesTrait { private: - inline static int ploidy = 0; + int ploidy; float mutationRate; TraitType traitType; sex_t sex; From bbf343542bcf08a59364f8c7047717794de690b8 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 13 Jun 2024 16:17:45 +0100 Subject: [PATCH 153/332] test recombination progress --- CMakeLists.txt | 2 +- Individual.cpp | 419 ------------------------------ unit_tests/testIndividual.cpp | 476 ++++++++++++++++++++++++++++++++++ 3 files changed, 477 insertions(+), 420 deletions(-) create mode 100644 unit_tests/testIndividual.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a20ab8b..68ba970 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ if (NOT batchmode) # that is, RScore as a standalone # specify the C++ standard set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) - add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) + add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp "unit_tests/testIndividual.cpp") else() # that is, RScore compiled as library within RangeShifter_batch add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) endif() diff --git a/Individual.cpp b/Individual.cpp index 3555eae..660a848 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1601,424 +1601,5 @@ void Individual::setInitAngle(const float angle) { pCRW->prevdrn = angle; } - -void testIndividual() { - - // Kernel-based transfer - { - // Simple 5*5 cell-based landscape layout - int lsDim = 5; - landParams ls_params = createDefaultLandParams(lsDim); - - Landscape ls; - ls.setLandParams(ls_params, true); - - // Two suitable cells in opposite corners - Cell* init_cell = new Cell(0, 0, 0, 0); - Cell* final_cell = new Cell(ls_params.dimX - 1, ls_params.dimY - 1, 0, 0); - ls.setCellArray(); - ls.addCellToLand(init_cell); - ls.addCellToLand(final_cell); - - // Set up species - Species sp; - // Habitat codes - sp.createHabK(1); - sp.setHabK(0, 100.0); // one habitat with K = 100 - // Demography - demogrParams d; - d.stageStruct = false; - sp.setDemogr(d); - // Transfer rules - transferRules trfr; - trfr.indVar = trfr.sexDep = trfr.stgDep = false; - trfr.twinKern = trfr.distMort = false; - sp.setTrfrRules(trfr); - sp.setFullKernel(false); - // Transfer traits - trfrKernelParams kern; - kern.meanDist1 = static_cast(ls_params.dimX); // can reach destination cell reasonably often - sp.setSpKernTraits(0, 0, kern, ls_params.resol); - // Transfer mortality params - trfrMortParams mort; - mort.fixedMort = 0.0; - sp.setMortParams(mort); - // Settlement - settleRules sett; - sett.wait = false; - sp.setSettRules(0, 0, sett); - - // Set up patches - ls.allocatePatches(&sp); - ls.updateCarryingCapacity(&sp, 0, 0); - Patch* init_patch = (Patch*)init_cell->getPatch(); - - // Create and set up individual - Individual ind1(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); - int isDispersing = ind1.moveKernel(&ls, &sp, false); - - // After moving, individual should be in the only available cell - Cell* curr_cell = ind1.getCurrCell(); - assert(curr_cell != init_cell); - assert(curr_cell == final_cell); - assert(ind1.getStatus() == 2); // potential settler - - // If no cell within reasonable dispersal reach, individual does not move and dies - kern.meanDist1 = 1.0; - sp.setSpKernTraits(0, 0, kern, ls_params.resol); - Individual ind2(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual - isDispersing = ind2.moveKernel(&ls, &sp, false); - curr_cell = ind2.getCurrCell(); - assert(ind2.getStatus() == 6); // RIP in peace - assert(curr_cell == init_cell); - - // Twin kernels - trfr.twinKern = true; - sp.setTrfrRules(trfr); - kern.meanDist1 = 1.0; // very unlikely to reach suitable cell - kern.meanDist2 = 5.0; // easily reaches suitable cell... - kern.probKern1 = 1.0; // ... but never used - sp.setSpKernTraits(0, 0, kern, ls_params.resol); - Individual ind3(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); - isDispersing = ind3.moveKernel(&ls, &sp, false); - assert(ind3.getStatus() == 6); // dead, could not reach destination cell - kern.probKern1 = 0.0; // always use second kernel - sp.setSpKernTraits(0, 0, kern, ls_params.resol); - Individual ind4(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); - isDispersing = ind4.moveKernel(&ls, &sp, false); - assert(ind4.getStatus() == 2); - // reset - trfr.twinKern = false; - sp.setTrfrRules(trfr); - kern.probKern1 = 1.0; - sp.setSpKernTraits(0, 0, kern, ls_params.resol); - - // Sex-dependent dispersal distances - trfr.sexDep = true; - sp.setTrfrRules(trfr); - trfrKernelParams kern_f = kern; - kern_f.meanDist1 = 1.0; // female very unlikely to reach suitable cell - sp.setSpKernTraits(0, 0, kern_f, ls_params.resol); - trfrKernelParams kern_m = kern; - kern_m.meanDist1 = 5.0; // male easily reaches suitable cell - sp.setSpKernTraits(0, 1, kern_m, ls_params.resol); - - Individual ind5(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // female as default - isDispersing = ind5.moveKernel(&ls, &sp, false); - assert(ind5.getStatus() == 6); // dead, could not reach destination - - Individual ind6(init_cell, init_patch, 1, 0, 0, 1.0, false, 0); // male - assert(ind6.getSex() == 1); - isDispersing = ind6.moveKernel(&ls, &sp, false); - assert(ind6.getStatus() == 2); - // reset - trfr.sexDep = false; - sp.setTrfrRules(trfr); - - // Stage-dependent - trfr.stgDep = true; - sp.setTrfrRules(trfr); - trfrKernelParams kern_juv = kern; - kern_juv.meanDist1 = 1.0; // juveniles very unlikely to reach suitable cell - sp.setSpKernTraits(0, 0, kern_juv, ls_params.resol); - trfrKernelParams kern_adult = kern; - kern_adult.meanDist1 = 5.0; // adults easily reach suitable cell - sp.setSpKernTraits(1, 0, kern_adult, ls_params.resol); - - Individual ind7(init_cell, init_patch, 0, 0, 0, 0.0, false, 0); // juvenile - isDispersing = ind7.moveKernel(&ls, &sp, false); - assert(ind7.getStatus() == 6); - - Individual ind8(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // adult by default - isDispersing = ind8.moveKernel(&ls, &sp, false); - assert(ind8.getStatus() == 2); - // reset - trfr.stgDep = false; - sp.setTrfrRules(trfr); - - /* Boundaries: dispersal distance overshoots - Only adjacent cells are available - ----- - -ooo- - -oio- - -ooo- - ----- - */ - ls.setCellArray(); // reset cells - vector cells; - // Set central cell and all adjacent - for (int x = ls_params.minX + 1; x < ls_params.maxX; ++x) { - for (int y = ls_params.minY + 1; y < ls_params.maxY; ++y) { - cells.push_back(new Cell(x, y, 0, 0)); - } - } - - for (auto c : cells) ls.addCellToLand(c); - ls.allocatePatches(&sp); - ls.updateCarryingCapacity(&sp, 0, 0); - init_cell = cells[4]; // that is, the center - init_patch = (Patch*)init_cell->getPatch(); - - kern.meanDist1 = 10; // overshoots *most* of the time... - sp.setSpKernTraits(0, 0, kern, ls_params.resol); - Individual ind9(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual - - // Non-absorbing boundaries - bool absorbing_boundaries{ false }; - isDispersing = ind9.moveKernel(&ls, &sp, absorbing_boundaries); - curr_cell = ind9.getCurrCell(); - assert(curr_cell != init_cell); // ...should be able to move eventually - assert(ind9.getStatus() == 2); - - // Absorbing boundaries - absorbing_boundaries = true; - Individual ind10(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual - isDispersing = ind10.moveKernel(&ls, &sp, absorbing_boundaries); - curr_cell = ind10.getCurrCell(); - assert(ind10.getStatus() == 6); - assert(curr_cell == 0); // out of the landscape - - // Dispersal-related mortality - // Fixed mortality - mort.fixedMort = 1.0; // Individual *will* die after any step - sp.setMortParams(mort); - trfr.distMort = false; - sp.setTrfrRules(trfr); - Individual ind11(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); - isDispersing = ind11.moveKernel(&ls, &sp, false); - assert(ind11.getStatus() == 7); - // Distance-dependent mortality - trfr.distMort = true; - sp.setTrfrRules(trfr); - mort.mortAlpha = 1000.0; // very steep threshold - mort.mortBeta = 0.5; // very small distance - sp.setMortParams(mort); - kern.meanDist1 = 5; // very likely to go over threshold - sp.setSpKernTraits(0, 0, kern, ls_params.resol); - Individual ind12(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); - isDispersing = ind12.moveKernel(&ls, &sp, false); - assert(ind12.getStatus() == 7); - mort.mortBeta = 30; // very large distance, unlikely to draw - sp.setMortParams(mort); - Individual ind13(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); - isDispersing = ind13.moveKernel(&ls, &sp, false); - assert(ind13.getStatus() != 7); - - // Reset mortality params - trfr.distMort = false; - mort.fixedMort = 0.0; - sp.setTrfrRules(trfr); - sp.setMortParams(mort); - } - - // Correlated random walk (CRW) - { - // Simple 5*5 cell-based landscape layout - int lsDim = 5; - landParams ls_params = createDefaultLandParams(lsDim); - double cellDiagLength = ls_params.resol * SQRT2; - - Landscape ls; - ls.setLandParams(ls_params, true); - - // All cells are suitable - const int hab_index = 0; - vector cell_vec; - for (int x = ls_params.minX; x < ls_params.dimX; ++x) { - for (int y = ls_params.minY; y < ls_params.dimY; ++y) { - cell_vec.push_back(new Cell(x, y, 0, hab_index)); - } - } - Cell* init_cell = cell_vec[12]; // central - ls.setCellArray(); - for (auto c : cell_vec) ls.addCellToLand(c); - - // Set up species - Species sp; - - // Habitat codes - sp.createHabK(1); - sp.setHabK(hab_index, 100.0); // one habitat with K = 100 - - // Habitat-dependent mortality - sp.createHabCostMort(1); - - // Transfer rules - transferRules trfr; - trfr.indVar = false; - trfr.habMort = false; - trfr.moveType = 2; // CRW - sp.setTrfrRules(trfr); - - // Transfer CRW traits - trfrMovtParams m; - m.stepMort = 0.0; - m.stepLength = cellDiagLength; // guaranteed to move out - m.rho = 1.0; - m.straightenPath = false; - sp.setSpMovtTraits(m); - - // Settlement rules - settleRules sett; - sett.wait = false; - sp.setSettRules(0, 0, sett); - settleSteps steps; - steps.maxSteps = 1; - steps.minSteps = 1; - steps.maxStepsYr = 1; - sp.setSteps(0, 0, steps); - - // Set up patches - ls.allocatePatches(&sp); - ls.updateCarryingCapacity(&sp, 0, 0); - Patch* init_patch = (Patch*)init_cell->getPatch(); - - // Create and set up individual - Individual ind0(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); - - // Set status - assert(ind0.getStatus() == 0); // default status, not emigrating - int isDispersing = ind0.moveStep(&ls, &sp, hab_index, false); - assert(ind0.getStatus() == 0); // status didn't change - assert(ind0.getCurrCell() == init_cell); // not emigrating so didn't move - - // Per-step mortality - m.stepMort = 1.0; // should die - sp.setSpMovtTraits(m); - Individual ind1(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); - // force set path bc for some reason path gets deallocated upon exiting constructor?? - ind1.setStatus(1); - isDispersing = ind1.moveStep(&ls, &sp, hab_index, false); - // Individual begins in natal patch so mortality is disabled - assert(ind1.getStatus() != 7); - // Individual should be in a different patch - Cell* first_step_cell = ind1.getCurrCell(); - assert(first_step_cell != init_cell); - - assert((Patch*)first_step_cell->getPatch() != init_patch); - ind1.setStatus(1); // emigrating again - - // Individual should die on second step - isDispersing = ind1.moveStep(&ls, &sp, hab_index, false); - assert(ind1.getCurrCell() == first_step_cell); // shouldn't have moved - assert(ind1.getStatus() == 7); // died by transfer - m.stepMort = 0.0; // not dying - sp.setSpMovtTraits(m); - - // Habitat-dep mortality - // ... - - // Step size - - ls = Landscape(); - ls.setLandParams(ls_params, true); - sp.createHabK(2); - const int hab_suitable = 0; - const int hab_unsuitable = 1; - sp.setHabK(hab_suitable, 100.0); - sp.setHabK(hab_unsuitable, 0.0); - - // Initial cell unsuitable, suitable cell in opposite corner - init_cell = new Cell(0, 0, 0, hab_unsuitable); - Cell* final_cell = new Cell(ls_params.dimX - 1, ls_params.dimY - 1, 0, hab_suitable); - ls.setCellArray(); - ls.addCellToLand(init_cell); - ls.addCellToLand(final_cell); - ls.allocatePatches(&sp); - ls.updateCarryingCapacity(&sp, 0, 0); - // Init cell is NOT in natal patch - Patch* natalPatch = new Patch(0, 0); - init_patch = (Patch*)init_cell->getPatch(); - - // Step length too short - m.stepLength = 0.1; // will not reach final cell - m.rho = 0.0; // random angle - sp.setSpMovtTraits(m); - steps.minSteps = 1; - steps.maxStepsYr = 2; - steps.maxSteps = 3; - sp.setSteps(0, 0, steps); - Individual ind2(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); - ind2.setStatus(1); // dispersing - // First step - still in unsuitable cell so still dispersing - isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); - assert(ind2.getCurrCell() == init_cell); - assert(ind2.getStatus() == 1); - // Second step - reaching max steps this year, wait next year - isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); - assert(ind2.getCurrCell() == init_cell); - assert(ind2.getStatus() == 3); - ind2.setStatus(1); // dispersing again - // Third step - reaching max steps, dies in unsuitable cell - isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); - assert(ind2.getCurrCell() == init_cell); - assert(ind2.getStatus() == 6); - - // Step length too long - m.stepLength = ls_params.dimX * SQRT2 * 1.5; // overshoots - sp.setSpMovtTraits(m); - Individual ind3(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); - ind3.setStatus(1); // dispersing - steps.minSteps = 1; - steps.maxStepsYr = 1; - steps.maxSteps = 1; // no need to test more than one step this time - sp.setSteps(0, 0, steps); - isDispersing = ind3.moveStep(&ls, &sp, hab_index, false); - assert(ind3.getCurrCell() == init_cell); - assert(ind3.getStatus() == 6); - - // Adequate step length - m.stepLength = (ls_params.dimX - 1) * SQRT2; - sp.setSpMovtTraits(m); - Individual ind4(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); - ind4.setStatus(1); // dispersing - // Initial angle still random but should eventually reach the suitable cell - isDispersing = ind4.moveStep(&ls, &sp, hab_index, false); - assert(ind4.getStatus() == 2); - assert(ind4.getCurrCell() == final_cell); - - // If boundaries are absorbing however, most likely to die - Individual ind5(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); - ind5.setStatus(1); // dispersing - bool absorbing_boundaries = true; - isDispersing = ind5.moveStep(&ls, &sp, hab_index, absorbing_boundaries); - assert(ind5.getStatus() == 6); - assert(ind5.getCurrCell() == 0); // deref apparently - - // Correlation parameter - // If rho = 1 should move in a straight line - // Many cells, all suitable - lsDim = 10; - ls_params = createDefaultLandParams(lsDim); - ls = Landscape(); - ls.setLandParams(ls_params, true); - cell_vec.clear(); - for (int x = ls_params.minX; x < ls_params.dimX; ++x) { - for (int y = ls_params.minY; y < ls_params.dimY; ++y) { - cell_vec.push_back(new Cell(x, y, 0, hab_suitable)); - } - } - ls.setCellArray(); - for (auto c : cell_vec) ls.addCellToLand(c); - ls.allocatePatches(&sp); - ls.updateCarryingCapacity(&sp, 0, 0); - // Individual moves by 1 along the diagonal - m.stepLength = cellDiagLength; // 1 diagonal cell - m.rho = 1; // angle = previous angle - sp.setSpMovtTraits(m); - steps.maxStepsYr = steps.maxSteps = ls_params.dimX; - sp.setSteps(0, 0, steps); - Individual ind6(cell_vec[0], natalPatch, 0, 0, 0, 0.0, true, 2); - const float diag_angle = PI / 4.0; // 45 degrees - ind6.setInitAngle(diag_angle); - // Individual moves only along diagonal cells - for (int i = 1; i < ls_params.dimX; ++i) { - ind6.setStatus(1); // dispersing - isDispersing = ind6.moveStep(&ls, &sp, hab_index, false); - assert(ind6.getStatus() == 2); - assert(ind6.getCurrCell() == cell_vec[i * (ls_params.dimX + 1)]); - } - } -} #endif // RSDEBUG diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp new file mode 100644 index 0000000..dc471b8 --- /dev/null +++ b/unit_tests/testIndividual.cpp @@ -0,0 +1,476 @@ +#if RSDEBUG + +#include "../Individual.h" + +void testTransferKernels() { + // Simple 5*5 cell-based landscape layout + int lsDim = 5; + landParams ls_params = createDefaultLandParams(lsDim); + + Landscape ls; + ls.setLandParams(ls_params, true); + + // Two suitable cells in opposite corners + Cell* init_cell = new Cell(0, 0, 0, 0); + Cell* final_cell = new Cell(ls_params.dimX - 1, ls_params.dimY - 1, 0, 0); + ls.setCellArray(); + ls.addCellToLand(init_cell); + ls.addCellToLand(final_cell); + + // Set up species + Species sp; + // Habitat codes + sp.createHabK(1); + sp.setHabK(0, 100.0); // one habitat with K = 100 + // Demography + demogrParams d; + d.stageStruct = false; + sp.setDemogr(d); + // Transfer rules + transferRules trfr; + trfr.indVar = trfr.sexDep = trfr.stgDep = false; + trfr.twinKern = trfr.distMort = false; + sp.setTrfrRules(trfr); + sp.setFullKernel(false); + // Transfer traits + trfrKernelParams kern; + kern.meanDist1 = static_cast(ls_params.dimX); // can reach destination cell reasonably often + sp.setSpKernTraits(0, 0, kern, ls_params.resol); + // Transfer mortality params + trfrMortParams mort; + mort.fixedMort = 0.0; + sp.setMortParams(mort); + // Settlement + settleRules sett; + sett.wait = false; + sp.setSettRules(0, 0, sett); + + // Set up patches + ls.allocatePatches(&sp); + ls.updateCarryingCapacity(&sp, 0, 0); + Patch* init_patch = (Patch*)init_cell->getPatch(); + + // Create and set up individual + Individual ind1(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + int isDispersing = ind1.moveKernel(&ls, &sp, false); + + // After moving, individual should be in the only available cell + Cell* curr_cell = ind1.getCurrCell(); + assert(curr_cell != init_cell); + assert(curr_cell == final_cell); + assert(ind1.getStatus() == 2); // potential settler + + // If no cell within reasonable dispersal reach, individual does not move and dies + kern.meanDist1 = 1.0; + sp.setSpKernTraits(0, 0, kern, ls_params.resol); + Individual ind2(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual + isDispersing = ind2.moveKernel(&ls, &sp, false); + curr_cell = ind2.getCurrCell(); + assert(ind2.getStatus() == 6); // RIP in peace + assert(curr_cell == init_cell); + + // Twin kernels + trfr.twinKern = true; + sp.setTrfrRules(trfr); + kern.meanDist1 = 1.0; // very unlikely to reach suitable cell + kern.meanDist2 = 5.0; // easily reaches suitable cell... + kern.probKern1 = 1.0; // ... but never used + sp.setSpKernTraits(0, 0, kern, ls_params.resol); + Individual ind3(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + isDispersing = ind3.moveKernel(&ls, &sp, false); + assert(ind3.getStatus() == 6); // dead, could not reach destination cell + kern.probKern1 = 0.0; // always use second kernel + sp.setSpKernTraits(0, 0, kern, ls_params.resol); + Individual ind4(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + isDispersing = ind4.moveKernel(&ls, &sp, false); + assert(ind4.getStatus() == 2); + // reset + trfr.twinKern = false; + sp.setTrfrRules(trfr); + kern.probKern1 = 1.0; + sp.setSpKernTraits(0, 0, kern, ls_params.resol); + + // Sex-dependent dispersal distances + trfr.sexDep = true; + sp.setTrfrRules(trfr); + trfrKernelParams kern_f = kern; + kern_f.meanDist1 = 1.0; // female very unlikely to reach suitable cell + sp.setSpKernTraits(0, 0, kern_f, ls_params.resol); + trfrKernelParams kern_m = kern; + kern_m.meanDist1 = 5.0; // male easily reaches suitable cell + sp.setSpKernTraits(0, 1, kern_m, ls_params.resol); + + Individual ind5(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // female as default + isDispersing = ind5.moveKernel(&ls, &sp, false); + assert(ind5.getStatus() == 6); // dead, could not reach destination + + Individual ind6(init_cell, init_patch, 1, 0, 0, 1.0, false, 0); // male + assert(ind6.getSex() == 1); + isDispersing = ind6.moveKernel(&ls, &sp, false); + assert(ind6.getStatus() == 2); + // reset + trfr.sexDep = false; + sp.setTrfrRules(trfr); + + // Stage-dependent + trfr.stgDep = true; + sp.setTrfrRules(trfr); + trfrKernelParams kern_juv = kern; + kern_juv.meanDist1 = 1.0; // juveniles very unlikely to reach suitable cell + sp.setSpKernTraits(0, 0, kern_juv, ls_params.resol); + trfrKernelParams kern_adult = kern; + kern_adult.meanDist1 = 5.0; // adults easily reach suitable cell + sp.setSpKernTraits(1, 0, kern_adult, ls_params.resol); + + Individual ind7(init_cell, init_patch, 0, 0, 0, 0.0, false, 0); // juvenile + isDispersing = ind7.moveKernel(&ls, &sp, false); + assert(ind7.getStatus() == 6); + + Individual ind8(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // adult by default + isDispersing = ind8.moveKernel(&ls, &sp, false); + assert(ind8.getStatus() == 2); + // reset + trfr.stgDep = false; + sp.setTrfrRules(trfr); + + /* Boundaries: dispersal distance overshoots + Only adjacent cells are available + ----- + -ooo- + -oio- + -ooo- + ----- + */ + ls.setCellArray(); // reset cells + vector cells; + // Set central cell and all adjacent + for (int x = ls_params.minX + 1; x < ls_params.maxX; ++x) { + for (int y = ls_params.minY + 1; y < ls_params.maxY; ++y) { + cells.push_back(new Cell(x, y, 0, 0)); + } + } + + for (auto c : cells) ls.addCellToLand(c); + ls.allocatePatches(&sp); + ls.updateCarryingCapacity(&sp, 0, 0); + init_cell = cells[4]; // that is, the center + init_patch = (Patch*)init_cell->getPatch(); + + kern.meanDist1 = 10; // overshoots *most* of the time... + sp.setSpKernTraits(0, 0, kern, ls_params.resol); + Individual ind9(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual + + // Non-absorbing boundaries + bool absorbing_boundaries{ false }; + isDispersing = ind9.moveKernel(&ls, &sp, absorbing_boundaries); + curr_cell = ind9.getCurrCell(); + assert(curr_cell != init_cell); // ...should be able to move eventually + assert(ind9.getStatus() == 2); + + // Absorbing boundaries + absorbing_boundaries = true; + Individual ind10(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual + isDispersing = ind10.moveKernel(&ls, &sp, absorbing_boundaries); + curr_cell = ind10.getCurrCell(); + assert(ind10.getStatus() == 6); + assert(curr_cell == 0); // out of the landscape + + // Dispersal-related mortality + // Fixed mortality + mort.fixedMort = 1.0; // Individual *will* die after any step + sp.setMortParams(mort); + trfr.distMort = false; + sp.setTrfrRules(trfr); + Individual ind11(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + isDispersing = ind11.moveKernel(&ls, &sp, false); + assert(ind11.getStatus() == 7); + // Distance-dependent mortality + trfr.distMort = true; + sp.setTrfrRules(trfr); + mort.mortAlpha = 1000.0; // very steep threshold + mort.mortBeta = 0.5; // very small distance + sp.setMortParams(mort); + kern.meanDist1 = 5; // very likely to go over threshold + sp.setSpKernTraits(0, 0, kern, ls_params.resol); + Individual ind12(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + isDispersing = ind12.moveKernel(&ls, &sp, false); + assert(ind12.getStatus() == 7); + mort.mortBeta = 30; // very large distance, unlikely to draw + sp.setMortParams(mort); + Individual ind13(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + isDispersing = ind13.moveKernel(&ls, &sp, false); + assert(ind13.getStatus() != 7); + + // Reset mortality params + trfr.distMort = false; + mort.fixedMort = 0.0; + sp.setTrfrRules(trfr); + sp.setMortParams(mort); +} + +void testTransferCRW() { + // Simple 5*5 cell-based landscape layout + int lsDim = 5; + landParams ls_params = createDefaultLandParams(lsDim); + double cellDiagLength = ls_params.resol * SQRT2; + + Landscape ls; + ls.setLandParams(ls_params, true); + + // All cells are suitable + const int hab_index = 0; + vector cell_vec; + for (int x = ls_params.minX; x < ls_params.dimX; ++x) { + for (int y = ls_params.minY; y < ls_params.dimY; ++y) { + cell_vec.push_back(new Cell(x, y, 0, hab_index)); + } + } + Cell* init_cell = cell_vec[12]; // central + ls.setCellArray(); + for (auto c : cell_vec) ls.addCellToLand(c); + + // Set up species + Species sp; + + // Habitat codes + sp.createHabK(1); + sp.setHabK(hab_index, 100.0); // one habitat with K = 100 + + // Habitat-dependent mortality + sp.createHabCostMort(1); + + // Transfer rules + transferRules trfr; + trfr.indVar = false; + trfr.habMort = false; + trfr.moveType = 2; // CRW + sp.setTrfrRules(trfr); + + // Transfer CRW traits + trfrMovtParams m; + m.stepMort = 0.0; + m.stepLength = cellDiagLength; // guaranteed to move out + m.rho = 1.0; + m.straightenPath = false; + sp.setSpMovtTraits(m); + + // Settlement rules + settleRules sett; + sett.wait = false; + sp.setSettRules(0, 0, sett); + settleSteps steps; + steps.maxSteps = 1; + steps.minSteps = 1; + steps.maxStepsYr = 1; + sp.setSteps(0, 0, steps); + + // Set up patches + ls.allocatePatches(&sp); + ls.updateCarryingCapacity(&sp, 0, 0); + Patch* init_patch = (Patch*)init_cell->getPatch(); + + // Create and set up individual + Individual ind0(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); + + // Set status + assert(ind0.getStatus() == 0); // default status, not emigrating + int isDispersing = ind0.moveStep(&ls, &sp, hab_index, false); + assert(ind0.getStatus() == 0); // status didn't change + assert(ind0.getCurrCell() == init_cell); // not emigrating so didn't move + + // Per-step mortality + m.stepMort = 1.0; // should die + sp.setSpMovtTraits(m); + Individual ind1(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + // force set path bc for some reason path gets deallocated upon exiting constructor?? + ind1.setStatus(1); + isDispersing = ind1.moveStep(&ls, &sp, hab_index, false); + // Individual begins in natal patch so mortality is disabled + assert(ind1.getStatus() != 7); + // Individual should be in a different patch + Cell* first_step_cell = ind1.getCurrCell(); + assert(first_step_cell != init_cell); + + assert((Patch*)first_step_cell->getPatch() != init_patch); + ind1.setStatus(1); // emigrating again + + // Individual should die on second step + isDispersing = ind1.moveStep(&ls, &sp, hab_index, false); + assert(ind1.getCurrCell() == first_step_cell); // shouldn't have moved + assert(ind1.getStatus() == 7); // died by transfer + m.stepMort = 0.0; // not dying + sp.setSpMovtTraits(m); + + // Habitat-dep mortality + // ... + + // Step size + + ls = Landscape(); + ls.setLandParams(ls_params, true); + sp.createHabK(2); + const int hab_suitable = 0; + const int hab_unsuitable = 1; + sp.setHabK(hab_suitable, 100.0); + sp.setHabK(hab_unsuitable, 0.0); + + // Initial cell unsuitable, suitable cell in opposite corner + init_cell = new Cell(0, 0, 0, hab_unsuitable); + Cell* final_cell = new Cell(ls_params.dimX - 1, ls_params.dimY - 1, 0, hab_suitable); + ls.setCellArray(); + ls.addCellToLand(init_cell); + ls.addCellToLand(final_cell); + ls.allocatePatches(&sp); + ls.updateCarryingCapacity(&sp, 0, 0); + // Init cell is NOT in natal patch + Patch* natalPatch = new Patch(0, 0); + init_patch = (Patch*)init_cell->getPatch(); + + // Step length too short + m.stepLength = 0.1; // will not reach final cell + m.rho = 0.0; // random angle + sp.setSpMovtTraits(m); + steps.minSteps = 1; + steps.maxStepsYr = 2; + steps.maxSteps = 3; + sp.setSteps(0, 0, steps); + Individual ind2(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); + ind2.setStatus(1); // dispersing + // First step - still in unsuitable cell so still dispersing + isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); + assert(ind2.getCurrCell() == init_cell); + assert(ind2.getStatus() == 1); + // Second step - reaching max steps this year, wait next year + isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); + assert(ind2.getCurrCell() == init_cell); + assert(ind2.getStatus() == 3); + ind2.setStatus(1); // dispersing again + // Third step - reaching max steps, dies in unsuitable cell + isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); + assert(ind2.getCurrCell() == init_cell); + assert(ind2.getStatus() == 6); + + // Step length too long + m.stepLength = ls_params.dimX * SQRT2 * 1.5; // overshoots + sp.setSpMovtTraits(m); + Individual ind3(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + ind3.setStatus(1); // dispersing + steps.minSteps = 1; + steps.maxStepsYr = 1; + steps.maxSteps = 1; // no need to test more than one step this time + sp.setSteps(0, 0, steps); + isDispersing = ind3.moveStep(&ls, &sp, hab_index, false); + assert(ind3.getCurrCell() == init_cell); + assert(ind3.getStatus() == 6); + + // Adequate step length + m.stepLength = (ls_params.dimX - 1) * SQRT2; + sp.setSpMovtTraits(m); + Individual ind4(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); + ind4.setStatus(1); // dispersing + // Initial angle still random but should eventually reach the suitable cell + isDispersing = ind4.moveStep(&ls, &sp, hab_index, false); + assert(ind4.getStatus() == 2); + assert(ind4.getCurrCell() == final_cell); + + // If boundaries are absorbing however, most likely to die + Individual ind5(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); + ind5.setStatus(1); // dispersing + bool absorbing_boundaries = true; + isDispersing = ind5.moveStep(&ls, &sp, hab_index, absorbing_boundaries); + assert(ind5.getStatus() == 6); + assert(ind5.getCurrCell() == 0); // deref apparently + + // Correlation parameter + // If rho = 1 should move in a straight line + // Many cells, all suitable + lsDim = 10; + ls_params = createDefaultLandParams(lsDim); + ls = Landscape(); + ls.setLandParams(ls_params, true); + cell_vec.clear(); + for (int x = ls_params.minX; x < ls_params.dimX; ++x) { + for (int y = ls_params.minY; y < ls_params.dimY; ++y) { + cell_vec.push_back(new Cell(x, y, 0, hab_suitable)); + } + } + ls.setCellArray(); + for (auto c : cell_vec) ls.addCellToLand(c); + ls.allocatePatches(&sp); + ls.updateCarryingCapacity(&sp, 0, 0); + // Individual moves by 1 along the diagonal + m.stepLength = cellDiagLength; // 1 diagonal cell + m.rho = 1; // angle = previous angle + sp.setSpMovtTraits(m); + steps.maxStepsYr = steps.maxSteps = ls_params.dimX; + sp.setSteps(0, 0, steps); + Individual ind6(cell_vec[0], natalPatch, 0, 0, 0, 0.0, true, 2); + const float diag_angle = PI / 4.0; // 45 degrees + ind6.setInitAngle(diag_angle); + // Individual moves only along diagonal cells + for (int i = 1; i < ls_params.dimX; ++i) { + ind6.setStatus(1); // dispersing + isDispersing = ind6.moveStep(&ls, &sp, hab_index, false); + assert(ind6.getStatus() == 2); + assert(ind6.getCurrCell() == cell_vec[i * (ls_params.dimX + 1)]); + } +} + +void testGenetics() { + + + + const int genomeSz = 6; // arbitrary + const set pos{}; + + + SpeciesTrait spTr( + TraitType::E_D0, + sex_t::NA, + + ) + + SpeciesTrait( + const TraitType & traitType, + const sex_t & sex, + const set&pos, + const ExpressionType & expr, + const DistributionType & initDist, + const map initParams, + const DistributionType & dominanceDist, + const map dominanceParams, + bool isInherited, + const float& mutationRate, + const DistributionType & mutationDist, + const map mutationParams, + const int ploidy + ); + + const bool fromMother{ true }; + const int parentChr{ strandA }; + const float valA(1.0); + const float valB(0.0); + const float domCoef(0.0); + vector> gene; + + map>> parentGenes; + for (int i = 0; i < genomeSz; i++) { + gene = { make_shared(valA, domCoef), make_shared(valB, domCoef) }; + parentGenes.emplace(i, gene); + } + + const set recomPositions{ 3 }; + trait.inheritDiploid(fromMother, parentGenes, recomPositions, parentChr); +} +void testIndividual() { + + // Kernel-based transfer + testTransferKernels(); + + // Correlated random walk (CRW) + testTransferCRW(); + + testGenetics(); +} + +#endif //RSDEBUG \ No newline at end of file From 03c47995d0cc2ce62f0f7f16b229a1c829dfb41c Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 14 Jun 2024 15:49:45 +0100 Subject: [PATCH 154/332] testing traits is a logistical nightmare --- DispersalTrait.cpp | 7 +++-- DispersalTrait.h | 14 +++++++++ unit_tests/testIndividual.cpp | 55 +++++++++++++++++------------------ 3 files changed, 46 insertions(+), 30 deletions(-) diff --git a/DispersalTrait.cpp b/DispersalTrait.cpp index 912e8ce..f636943 100644 --- a/DispersalTrait.cpp +++ b/DispersalTrait.cpp @@ -105,8 +105,11 @@ DispersalTrait::DispersalTrait(SpeciesTrait* P) // Copies immutable features from a parent trait // Only called via clone() // ---------------------------------------------------------------------------------------- -DispersalTrait::DispersalTrait(const DispersalTrait& T) : pSpeciesTrait(T.pSpeciesTrait), _mutate_func_ptr(T._mutate_func_ptr), _inherit_func_ptr(T._inherit_func_ptr), _express_func_ptr(T._express_func_ptr) -{} +DispersalTrait::DispersalTrait(const DispersalTrait& T) : + pSpeciesTrait(T.pSpeciesTrait), + _mutate_func_ptr(T._mutate_func_ptr), + _inherit_func_ptr(T._inherit_func_ptr), + _express_func_ptr(T._express_func_ptr) {} // ---------------------------------------------------------------------------------------- // Sample and apply mutations from a uniform distribution diff --git a/DispersalTrait.h b/DispersalTrait.h index 846fbea..3221039 100644 --- a/DispersalTrait.h +++ b/DispersalTrait.h @@ -45,6 +45,20 @@ class DispersalTrait : public QuantitativeTrait { int countHeterozygoteLoci() const; bool isHeterozygoteAtLocus(int locus) const override; +#if RSDEBUG // for testing only + void overwriteGenes(map>> genSeq) { + genes = genSeq; + } + void triggerInherit( + // inheritGenes requires passing a QuantitativeTrait, unfeasible in tests + const bool& fromMother, + map>> const& parentGenes, + set const& recomPositions, + int startChr) { + (this->*_inherit_func_ptr)(fromMother, parentGenes, recomPositions, startChr); + } +#endif + private: const double dispDominanceFactor = 1.0; // no dominance for Dispersal traits (yet?) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index dc471b8..8f47232 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -418,41 +418,39 @@ void testTransferCRW() { void testGenetics() { - - const int genomeSz = 6; // arbitrary - const set pos{}; - - - SpeciesTrait spTr( - TraitType::E_D0, - sex_t::NA, - - ) - - SpeciesTrait( - const TraitType & traitType, - const sex_t & sex, - const set&pos, - const ExpressionType & expr, - const DistributionType & initDist, - const map initParams, - const DistributionType & dominanceDist, - const map dominanceParams, - bool isInherited, - const float& mutationRate, - const DistributionType & mutationDist, - const map mutationParams, - const int ploidy + set pos; + for (int i = 0; i < genomeSz; i++) pos.insert(i); + + const map distParams{ + pair{GenParamType::MIN, 0.0}, + pair{GenParamType::MAX, 1.0} + }; + + SpeciesTrait* spTr = new SpeciesTrait( + TraitType::E_D0, + sex_t::NA, + pos, + ExpressionType::ADDITIVE, + DistributionType::UNIFORM, + distParams, + DistributionType::NONE, + distParams, + true, //isInherited + 0.0, + DistributionType::UNIFORM, + distParams, + 2 ); + DispersalTrait dispTrParent(spTr); + DispersalTrait dispTrChild(dispTrParent); const bool fromMother{ true }; - const int parentChr{ strandA }; + const int parentChr{ 0 }; const float valA(1.0); const float valB(0.0); const float domCoef(0.0); vector> gene; - map>> parentGenes; for (int i = 0; i < genomeSz; i++) { gene = { make_shared(valA, domCoef), make_shared(valB, domCoef) }; @@ -460,8 +458,9 @@ void testGenetics() { } const set recomPositions{ 3 }; - trait.inheritDiploid(fromMother, parentGenes, recomPositions, parentChr); + dispTrChild.triggerInherit(fromMother, parentGenes, recomPositions, parentChr); } + void testIndividual() { // Kernel-based transfer From 1f0283e7a3d0541818b82db9aacad652bcae4bce Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 14 Jun 2024 17:34:41 +0100 Subject: [PATCH 155/332] fix bug looking for breakpoint at end iterator, fix test recombination; fix #27 --- DispersalTrait.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/DispersalTrait.cpp b/DispersalTrait.cpp index f636943..0b69050 100644 --- a/DispersalTrait.cpp +++ b/DispersalTrait.cpp @@ -210,6 +210,7 @@ void DispersalTrait::inheritGenes(const bool& fromMother, QuantitativeTrait* par // ---------------------------------------------------------------------------------------- void DispersalTrait::inheritDiploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { + const int lastPosition = parentGenes.rbegin()->first; auto it = recomPositions.lower_bound(parentGenes.begin()->first); int nextBreakpoint = *it; // Is the first parent gene position already recombinant? @@ -223,7 +224,13 @@ void DispersalTrait::inheritDiploid(const bool& fromMother, map nextBreakpoint) { parentChromosome = 1 - parentChromosome; std::advance(it, 1); // go to next recombination site - nextBreakpoint = *it; + if (it == recomPositions.end()) { + // no more recombinations + nextBreakpoint = lastPosition; + } + else { + nextBreakpoint = *it; + } } if (locus <= nextBreakpoint) { From 99b3ae080baa2bfb4bb6eaf41cbf10640fb119af Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Sat, 15 Jun 2024 13:47:53 +0100 Subject: [PATCH 156/332] pass recombination test; fix #27 --- unit_tests/testIndividual.cpp | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 8f47232..c2c1692 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -418,6 +418,7 @@ void testTransferCRW() { void testGenetics() { + // Recombination occurs just after recombination site const int genomeSz = 6; // arbitrary set pos; for (int i = 0; i < genomeSz; i++) pos.insert(i); @@ -445,20 +446,33 @@ void testGenetics() { DispersalTrait dispTrParent(spTr); DispersalTrait dispTrChild(dispTrParent); - const bool fromMother{ true }; - const int parentChr{ 0 }; - const float valA(1.0); - const float valB(0.0); - const float domCoef(0.0); + const int startingChr{ 0 }; // Chromosome A + const float valChrA(0.0); + const float valChrB(1.0); + const float domCoef(0.0); // no dominance for dispersal traits vector> gene; - map>> parentGenes; + map>> motherGenes; for (int i = 0; i < genomeSz; i++) { - gene = { make_shared(valA, domCoef), make_shared(valB, domCoef) }; - parentGenes.emplace(i, gene); + // Mother genotype is + // 000000 + // 111111 + gene = { + make_shared(valChrA, domCoef), + make_shared(valChrB, domCoef) + }; + motherGenes.emplace(i, gene); } + const int recombinationSite{ 3 }; + // Trigger inheritance from mother + dispTrChild.triggerInherit(true, motherGenes, set{recombinationSite}, startingChr); + // for this test we ignore inheritance from father - const set recomPositions{ 3 }; - dispTrChild.triggerInherit(fromMother, parentGenes, recomPositions, parentChr); + float valMotherChr; + for (int i = 0; i < genomeSz; i++) { + valMotherChr = dispTrChild.getAlleleValueAtLocus(0, i); + assert(valMotherChr == (i <= recombinationSite ? valChrA : valChrB)); + // don't check other chromosome, empty bc we did not resolve father inheritance + } } void testIndividual() { From 27d31118a2f588876b4c356d26ca5123a826ae14 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Sat, 15 Jun 2024 13:58:32 +0100 Subject: [PATCH 157/332] clean up recombination test --- unit_tests/testIndividual.cpp | 88 +++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index c2c1692..ad81acd 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -419,59 +419,65 @@ void testTransferCRW() { void testGenetics() { // Recombination occurs just after recombination site - const int genomeSz = 6; // arbitrary - set pos; - for (int i = 0; i < genomeSz; i++) pos.insert(i); + { - const map distParams{ - pair{GenParamType::MIN, 0.0}, - pair{GenParamType::MAX, 1.0} - }; + const int genomeSz = 6; + set genePositions; for (int i = 0; i < genomeSz; i++) genePositions.insert(i); - SpeciesTrait* spTr = new SpeciesTrait( + // Create species trait + const map distParams{ + pair{GenParamType::MIN, 0.0}, + pair{GenParamType::MAX, 1.0} + }; + SpeciesTrait* spTr = new SpeciesTrait( TraitType::E_D0, sex_t::NA, - pos, + genePositions, ExpressionType::ADDITIVE, DistributionType::UNIFORM, distParams, - DistributionType::NONE, + DistributionType::NONE, // no dominance distParams, - true, //isInherited + true, // isInherited 0.0, DistributionType::UNIFORM, distParams, - 2 + 2 // ploidy ); - DispersalTrait dispTrParent(spTr); - DispersalTrait dispTrChild(dispTrParent); - - const int startingChr{ 0 }; // Chromosome A - const float valChrA(0.0); - const float valChrB(1.0); - const float domCoef(0.0); // no dominance for dispersal traits - vector> gene; - map>> motherGenes; - for (int i = 0; i < genomeSz; i++) { - // Mother genotype is - // 000000 - // 111111 - gene = { - make_shared(valChrA, domCoef), - make_shared(valChrB, domCoef) - }; - motherGenes.emplace(i, gene); - } - const int recombinationSite{ 3 }; - // Trigger inheritance from mother - dispTrChild.triggerInherit(true, motherGenes, set{recombinationSite}, startingChr); - // for this test we ignore inheritance from father - - float valMotherChr; - for (int i = 0; i < genomeSz; i++) { - valMotherChr = dispTrChild.getAlleleValueAtLocus(0, i); - assert(valMotherChr == (i <= recombinationSite ? valChrA : valChrB)); - // don't check other chromosome, empty bc we did not resolve father inheritance + + // Create individual trait objects + DispersalTrait dispTrParent(spTr); // initialisation constructor + DispersalTrait dispTrChild(dispTrParent); // inheritance constructor + + // Fill mother gene sequence + const float valChrA(0.0), valChrB(1.0); + const float domCoef(0.0); // no dominance for dispersal traits + vector> gene; + map>> motherGenes; + for (int i = 0; i < genomeSz; i++) { + // Mother genotype: + // 000000 + // 111111 + gene = { + make_shared(valChrA, domCoef), + make_shared(valChrB, domCoef) + }; + motherGenes.emplace(i, gene); + } + + // Trigger inheritance from mother + const int recombinationSite{3}; + const int startingChr{0}; // Chromosome A + dispTrChild.triggerInherit(true, motherGenes, set{recombinationSite}, startingChr); + // for this test we ignore inheritance from father + + // Mother-inherited alleles should have value of chr A before recombination site, chr B after + float valMotherChr; + for (int i = 0; i < genomeSz; i++) { + valMotherChr = dispTrChild.getAlleleValueAtLocus(0, i); + assert(valMotherChr == (i <= recombinationSite ? valChrA : valChrB)); + // don't check other chromosome, empty bc we did not resolve father inheritance + } } } From bfffc12e4d7a3809acaa2905ca7124bc2c2f2d51 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Sat, 15 Jun 2024 14:03:17 +0100 Subject: [PATCH 158/332] randomise test recombination site --- unit_tests/testIndividual.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index ad81acd..c1fd9e2 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -420,7 +420,6 @@ void testGenetics() { // Recombination occurs just after recombination site { - const int genomeSz = 6; set genePositions; for (int i = 0; i < genomeSz; i++) genePositions.insert(i); @@ -466,7 +465,7 @@ void testGenetics() { } // Trigger inheritance from mother - const int recombinationSite{3}; + const unsigned int recombinationSite = pRandom->IRandom(0, genomeSz); // should work for any position const int startingChr{0}; // Chromosome A dispTrChild.triggerInherit(true, motherGenes, set{recombinationSite}, startingChr); // for this test we ignore inheritance from father From a3b90b4ed60a6a7730f3a2f7694791036cd68c3b Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 17 Jun 2024 10:32:49 +0100 Subject: [PATCH 159/332] streamlined creation of test objects --- DispersalTrait.cpp | 27 ++++++++++++++- DispersalTrait.h | 10 ++++++ SpeciesTrait.cpp | 34 ++++++++++++++++++ SpeciesTrait.h | 11 +++++- unit_tests/testIndividual.cpp | 65 +++++++++++++---------------------- 5 files changed, 104 insertions(+), 43 deletions(-) diff --git a/DispersalTrait.cpp b/DispersalTrait.cpp index 0b69050..bbb99ad 100644 --- a/DispersalTrait.cpp +++ b/DispersalTrait.cpp @@ -451,4 +451,29 @@ float DispersalTrait::getAlleleValueAtLocus(short whichChromosome, int position) if (it == genes.end()) throw runtime_error("The Dispersal locus queried for its allele value does not exist."); return it->second[whichChromosome].get()->getAlleleValue(); -} \ No newline at end of file +} + +#if RSDEBUG // Testing only +// Create a default set of alleles for testing +map>> createTestEmigTrGenotype( + const int genomeSz, + const bool isDiploid, + const float valAlleleA, + const float valAlleleB +) { + const float domCoef(0.0); // no dominance for dispersal traits + vector> gene(isDiploid ? 2 : 1); + if (isDiploid) { + gene[0] = make_shared(valAlleleA, domCoef); + gene[1] = make_shared(valAlleleB, domCoef); + } + else { + gene[0] = make_shared(valAlleleA, domCoef); + } + map>> genotype; + for (int i = 0; i < genomeSz; i++) { + genotype.emplace(i, gene); + } + return genotype; +} +#endif // RSDEBUG \ No newline at end of file diff --git a/DispersalTrait.h b/DispersalTrait.h index 3221039..b2bf721 100644 --- a/DispersalTrait.h +++ b/DispersalTrait.h @@ -93,4 +93,14 @@ class DispersalTrait : public QuantitativeTrait { float expressAdditive(); }; +#if RSDEBUG +// Create a default set of alleles for testing +map>> createTestEmigTrGenotype( + const int genomeSz, + const bool isDiploid, + const float valChrA, + const float valChrB = -99.9 // allow to not use if haploid +); +#endif RSDEBUG + #endif // DISPTRAITH \ No newline at end of file diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 0fc0c44..6008beb 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -174,3 +174,37 @@ bool SpeciesTrait::isValidTraitVal(const float& val) const { } } +#if RSDEBUG +// Testing only + +// Create a default set of gene positions ranging from zero to genome size +set createTestGenePositions(const int genomeSz) { + set genePositions; + for (int i = 0; i < genomeSz; i++) genePositions.insert(i); + return genePositions; +} + +SpeciesTrait* createTestSpTrait(set genePositions, const bool& isDiploid) { + // Create species trait + const map distParams{ + pair{GenParamType::MIN, 0.0}, + pair{GenParamType::MAX, 1.0} + }; + SpeciesTrait* spTr = new SpeciesTrait( + TraitType::E_D0, + sex_t::NA, + genePositions, + ExpressionType::ADDITIVE, + DistributionType::UNIFORM, + distParams, + DistributionType::NONE, // no dominance + distParams, + true, // isInherited + 0.0, // mutation rate + DistributionType::UNIFORM, + distParams, + isDiploid ? 2 : 1 + ); + return spTr; +} +#endif // RSDEBUG diff --git a/SpeciesTrait.h b/SpeciesTrait.h index ca8ca94..20b41c4 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -70,4 +70,13 @@ class SpeciesTrait { DistributionType mutationDistribution; map mutationParameters; }; -#endif \ No newline at end of file + +#if RSDEBUG // Testing only + +// Create a default set of gene positions ranging from zero to genome size +set createTestGenePositions(const int genomeSz); +SpeciesTrait* createTestSpTrait(set genePositions, const bool& isDiploid); + +#endif // RSDEBUG + +#endif // SPECIESTRAITH \ No newline at end of file diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index c1fd9e2..67ecab1 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -418,63 +418,46 @@ void testTransferCRW() { void testGenetics() { + // Individuals inherit alleles from their parents + { + const int genomeSz = 5; + // Diploid case, 2 parents with diff. alleles + const bool isDiploid{ true }; + SpeciesTrait* spTr = createTestSpTrait(createTestGenePositions(genomeSz), isDiploid); + + + // Haploid case, simply copy parent + + } + // Recombination occurs just after recombination site { - const int genomeSz = 6; - set genePositions; for (int i = 0; i < genomeSz; i++) genePositions.insert(i); - - // Create species trait - const map distParams{ - pair{GenParamType::MIN, 0.0}, - pair{GenParamType::MAX, 1.0} - }; - SpeciesTrait* spTr = new SpeciesTrait( - TraitType::E_D0, - sex_t::NA, - genePositions, - ExpressionType::ADDITIVE, - DistributionType::UNIFORM, - distParams, - DistributionType::NONE, // no dominance - distParams, - true, // isInherited - 0.0, - DistributionType::UNIFORM, - distParams, - 2 // ploidy - ); + const int genomeSz = 5; + const bool isDiploid{ true }; + SpeciesTrait* spTr = createTestSpTrait(createTestGenePositions(genomeSz), isDiploid); // Create individual trait objects DispersalTrait dispTrParent(spTr); // initialisation constructor DispersalTrait dispTrChild(dispTrParent); // inheritance constructor // Fill mother gene sequence - const float valChrA(0.0), valChrB(1.0); - const float domCoef(0.0); // no dominance for dispersal traits - vector> gene; - map>> motherGenes; - for (int i = 0; i < genomeSz; i++) { - // Mother genotype: - // 000000 - // 111111 - gene = { - make_shared(valChrA, domCoef), - make_shared(valChrB, domCoef) - }; - motherGenes.emplace(i, gene); - } + const float valAlleleA(0.0), valAlleleB(1.0); + // Mother genotype: + // 000000 + // 111111 + auto motherGenotype = createTestEmigTrGenotype(genomeSz, isDiploid, valAlleleA, valAlleleB); // Trigger inheritance from mother const unsigned int recombinationSite = pRandom->IRandom(0, genomeSz); // should work for any position const int startingChr{0}; // Chromosome A - dispTrChild.triggerInherit(true, motherGenes, set{recombinationSite}, startingChr); + dispTrChild.triggerInherit(true, motherGenotype, set{recombinationSite}, startingChr); // for this test we ignore inheritance from father // Mother-inherited alleles should have value of chr A before recombination site, chr B after - float valMotherChr; + float valMotherAllele; for (int i = 0; i < genomeSz; i++) { - valMotherChr = dispTrChild.getAlleleValueAtLocus(0, i); - assert(valMotherChr == (i <= recombinationSite ? valChrA : valChrB)); + valMotherAllele = dispTrChild.getAlleleValueAtLocus(0, i); + assert(valMotherAllele == (i <= recombinationSite ? valAlleleA : valAlleleB)); // don't check other chromosome, empty bc we did not resolve father inheritance } } From 125e490c2e5228923a1d6a0cd55c83cdc88abc7f Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 17 Jun 2024 11:37:59 +0100 Subject: [PATCH 160/332] test simple inheritance, fix issue #37 --- unit_tests/testIndividual.cpp | 69 +++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 7 deletions(-) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 67ecab1..442487d 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -420,14 +420,69 @@ void testGenetics() { // Individuals inherit alleles from their parents { - const int genomeSz = 5; - // Diploid case, 2 parents with diff. alleles - const bool isDiploid{ true }; - SpeciesTrait* spTr = createTestSpTrait(createTestGenePositions(genomeSz), isDiploid); - - - // Haploid case, simply copy parent + // 1 - Diploid case, 2 parents with diff. alleles + { + const int genomeSz = 5; + const bool isDiploid{ true }; + SpeciesTrait* spTr = createTestSpTrait(createTestGenePositions(genomeSz), isDiploid); + + // Heterozygote parent genotypes + const float valAlleleMotherA(1.0), valAlleleMotherB(2.0); + const float valAlleleFatherA(3.0), valAlleleFatherB(4.0); + auto motherGenotype = createTestEmigTrGenotype(genomeSz, isDiploid, valAlleleMotherA, valAlleleMotherB); + auto fatherGenotype = createTestEmigTrGenotype(genomeSz, isDiploid, valAlleleFatherA, valAlleleFatherB); + const int startMotherChr = 0; // Strand A + const int startFatherChr = 1; // Strand B + + // Create individual trait objects + DispersalTrait dispTrParent(spTr); // initialisation constructor + DispersalTrait dispTrChild(dispTrParent); // inheritance constructor + + set recomSites{}; // no recombination + // End of genome always recombines + recomSites.insert(genomeSz - 1); + + dispTrChild.triggerInherit(true, motherGenotype, recomSites, startMotherChr); + dispTrChild.triggerInherit(false, fatherGenotype, recomSites, startFatherChr); + + // Child should have inherited strand A from mother and strand B from father + float valChildAlleleA, valChildAlleleB; + for (int i = 0; i < genomeSz; i++) { + valChildAlleleA = dispTrChild.getAlleleValueAtLocus(0, i); + assert(valChildAlleleA == valAlleleMotherA); + valChildAlleleB = dispTrChild.getAlleleValueAtLocus(1, i); + assert(valChildAlleleB == valAlleleFatherB); + } + } + // 2 - Haploid case, simply copy parent + { + const int genomeSz = 5; + const bool isDiploid{ false }; + SpeciesTrait* spTr = createTestSpTrait(createTestGenePositions(genomeSz), isDiploid); + + // Heterozygote parent genotypes + const float valAlleleMother(5.0); + auto motherGenotype = createTestEmigTrGenotype(genomeSz, isDiploid, valAlleleMother); + const int startMotherChr = 999; // doesn't matter, not used + + // Create individual trait objects + DispersalTrait dispTrParent(spTr); // initialisation constructor + DispersalTrait dispTrChild(dispTrParent); // inheritance constructor + + set recomSites; + for (unsigned int i = 0; i < genomeSz; i++) + recomSites.insert(i); // recombination should be ignored + + dispTrChild.triggerInherit(true, motherGenotype, recomSites, startMotherChr); + + // Child should have inherited strand B from mother + float valChildAllele; + for (int i = 0; i < genomeSz; i++) { + valChildAllele = dispTrChild.getAlleleValueAtLocus(0, i); + assert(valChildAllele == valAlleleMother); + } + } } // Recombination occurs just after recombination site From 7a955f3cf60685b8cd06e992681ce6c89426b2d8 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 17 Jun 2024 11:52:34 +0100 Subject: [PATCH 161/332] deal with no recombination inside inherit function --- DispersalTrait.cpp | 13 +++++-------- Individual.cpp | 4 ---- unit_tests/testIndividual.cpp | 2 -- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/DispersalTrait.cpp b/DispersalTrait.cpp index bbb99ad..f62a560 100644 --- a/DispersalTrait.cpp +++ b/DispersalTrait.cpp @@ -212,7 +212,10 @@ void DispersalTrait::inheritDiploid(const bool& fromMother, mapfirst; auto it = recomPositions.lower_bound(parentGenes.begin()->first); - int nextBreakpoint = *it; + // If no recombination sites, only breakpoint is last position + // i.e., no recombination occurs + int nextBreakpoint = it == recomPositions.end() ? lastPosition : *it; + // Is the first parent gene position already recombinant? auto distance = std::distance(recomPositions.begin(), it); if (distance % 2 != 0) // odd positions = switch, even = switch back @@ -224,13 +227,7 @@ void DispersalTrait::inheritDiploid(const bool& fromMother, map nextBreakpoint) { parentChromosome = 1 - parentChromosome; std::advance(it, 1); // go to next recombination site - if (it == recomPositions.end()) { - // no more recombinations - nextBreakpoint = lastPosition; - } - else { - nextBreakpoint = *it; - } + int nextBreakpoint = it == recomPositions.end() ? lastPosition : *it; } if (locus <= nextBreakpoint) { diff --git a/Individual.cpp b/Individual.cpp index 660a848..7fb28f6 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -157,10 +157,6 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi paternalRecomPositions.insert(pRandom->IRandom(0, genomeSize)); } - // End of genome always recombines - maternalRecomPositions.insert(genomeSize - 1); - paternalRecomPositions.insert(genomeSize - 1); - // Inherit genes for each gene const auto& spTraits = pSpecies->getTraitTypes(); for (auto const& trait : spTraits) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 442487d..3d38d42 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -439,8 +439,6 @@ void testGenetics() { DispersalTrait dispTrChild(dispTrParent); // inheritance constructor set recomSites{}; // no recombination - // End of genome always recombines - recomSites.insert(genomeSz - 1); dispTrChild.triggerInherit(true, motherGenotype, recomSites, startMotherChr); dispTrChild.triggerInherit(false, fatherGenotype, recomSites, startFatherChr); From ee326ad70116e3765f706d598a437a2c3ba8a075 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 18 Jun 2024 18:35:45 +0100 Subject: [PATCH 162/332] template for setting genes of individuals for testing, progress #30 --- unit_tests/testIndividual.cpp | 93 +++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 3d38d42..e030465 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -514,6 +514,49 @@ void testGenetics() { // don't check other chromosome, empty bc we did not resolve father inheritance } } + + // Genetic linkage does occur + { + // Should also test for interactions with chromosome breaks? + // + // Sample X vectors of recombination sites + // Create traits and resolve inheritance for each vector + // Count times c1 = A & B; c2 = B & C have same alleles + // Assert c1 > c2 + /* + const int genomeSz = 100; + // Genes A, B, C with dist(A,B) << dist(B,C); + const set genePositions = {0, 1, genomeSz - 1 }; + const bool isDiploid{ true }; + SpeciesTrait* spTr = createTestSpTrait(genePositions, isDiploid); + // All genes heterozygote with same alleles for each gene + const float valAlleleA(0.0), valAlleleB(1.0); + const int startingChr{ 0 }; // Chromosome A + + set recombinationSites; + const int nbDraws = 10; + + for (int i = 0; i < nbDraws; i++) { + + if (i > 0) recombinationSites.clear(); + drawRecombinantSites(recombinationSites); + + // Create individual trait objects + DispersalTrait dispTrParent(spTr); // initialisation constructor + DispersalTrait dispTrChild(dispTrParent); // inheritance constructor + auto motherGenotype = createTestEmigTrGenotype(genomeSz, isDiploid, valAlleleA, valAlleleB); + + // Trigger inheritance from mother + dispTrChild.triggerInherit(true, motherGenotype, recombinationSites, startingChr); + // inheritance from father not needed + + // Check linked genes have same alleles more often + // ... + + } + */ + + } } void testIndividual() { @@ -525,6 +568,56 @@ void testIndividual() { testTransferCRW(); testGenetics(); + + // Genetic linkage does occur + // Should also test for interactions with chromosome breaks? + // + // Sample X vectors of recombination sites + // Create traits and resolve inheritance for each vector + // Count times c1 = A & B; c2 = B & C have same alleles + // Assert c1 > c2 + { + + Patch* pPatch = new Patch(0, 0); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + + const float recombinationRate = 0.1; + const int genomeSz = 10; + Species* pSpecies = new Species(); + + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // a single chromosome + genomeSz, + recombinationRate, + set{}, "none", set{}, 0 // no output so no sampling + ); + const set genePositions = {0, 1, genomeSz - 1}; + const bool isDiploid{ true }; + SpeciesTrait* spTr = createTestSpTrait(genePositions, isDiploid); + pSpecies->addTrait(TraitType::E_D0, *spTr); + + Individual indMother = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + Individual indFather = Individual(pCell, pPatch, 0, 0, 0, 1.0, false, 0); + + DispersalTrait dispTrParent(spTr); // initialisation constructor + // All genes heterozygote with same alleles for each gene + const float valAlleleA(0.0), valAlleleB(1.0); + const float domCoef(0.0); // no dominance for dispersal traits + vector> gene(2); + gene[0] = make_shared(valAlleleA, domCoef); + gene[1] = make_shared(valAlleleB, domCoef); + + map>> genotype; + for (int i : genePositions) { + genotype.emplace(i, gene); + } + dispTrParent.overwriteGenes(genotype); + indMother.insertIndDispTrait(TraitType::E_D0, dispTrParent); + indFather.insertIndDispTrait(TraitType::E_D0, dispTrParent); + + Individual indChild = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + indChild.inheritTraits(pSpecies, &indMother, &indFather, 1.0); + } } #endif //RSDEBUG \ No newline at end of file From 743cb1ffbd78646fe2f8f8e5e6243b6c77c369d2 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 19 Jun 2024 15:21:54 +0100 Subject: [PATCH 163/332] finally figured out to set up individual with genes for testing --- DispersalTrait.cpp | 21 ++++++++----- Individual.cpp | 2 +- Individual.h | 3 ++ Species.cpp | 1 - TraitFactory.h | 8 ++--- unit_tests/testIndividual.cpp | 55 ++++++++++++++--------------------- 6 files changed, 43 insertions(+), 47 deletions(-) diff --git a/DispersalTrait.cpp b/DispersalTrait.cpp index f62a560..fa881d9 100644 --- a/DispersalTrait.cpp +++ b/DispersalTrait.cpp @@ -204,20 +204,25 @@ void DispersalTrait::inheritGenes(const bool& fromMother, QuantitativeTrait* par // ---------------------------------------------------------------------------------------- // Inheritance for diploid, sexual species -// Called once for each parent. Given a list of recombinant sites, -// populates offspring genes with appropriate parent alleles -// Assumes mother genes are inherited first +// Called once for each parent. +// Pass the correct parental strand, resolving crossing-overs +// after each recombinant site e.g. if parent genotype is +// 0000 +// 1111 +// and position 2 is selected to recombine, then offspring inherits +// 0001 +// Assumes mother genes are inherited first. // ---------------------------------------------------------------------------------------- void DispersalTrait::inheritDiploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { const int lastPosition = parentGenes.rbegin()->first; - auto it = recomPositions.lower_bound(parentGenes.begin()->first); + auto recomIt = recomPositions.lower_bound(parentGenes.begin()->first); // If no recombination sites, only breakpoint is last position // i.e., no recombination occurs - int nextBreakpoint = it == recomPositions.end() ? lastPosition : *it; + int nextBreakpoint = recomIt == recomPositions.end() ? lastPosition : *recomIt; // Is the first parent gene position already recombinant? - auto distance = std::distance(recomPositions.begin(), it); + auto distance = std::distance(recomPositions.begin(), recomIt); if (distance % 2 != 0) // odd positions = switch, even = switch back parentChromosome = 1 - parentChromosome; //switch chromosome @@ -226,8 +231,8 @@ void DispersalTrait::inheritDiploid(const bool& fromMother, map nextBreakpoint) { parentChromosome = 1 - parentChromosome; - std::advance(it, 1); // go to next recombination site - int nextBreakpoint = it == recomPositions.end() ? lastPosition : *it; + std::advance(recomIt, 1); // go to next recombination site + nextBreakpoint = recomIt == recomPositions.end() ? lastPosition : *recomIt; } if (locus <= nextBreakpoint) { diff --git a/Individual.cpp b/Individual.cpp index 7fb28f6..3d09b7e 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -157,7 +157,7 @@ void Individual::inherit(Species* pSpecies, const Individual* mother, const Indi paternalRecomPositions.insert(pRandom->IRandom(0, genomeSize)); } - // Inherit genes for each gene + // Inherit genes for each trait const auto& spTraits = pSpecies->getTraitTypes(); for (auto const& trait : spTraits) { diff --git a/Individual.h b/Individual.h index d63d799..cb6f40b 100644 --- a/Individual.h +++ b/Individual.h @@ -346,6 +346,9 @@ class Individual { // Testing utilities Cell* getCurrCell() const; void setInitAngle(const float angle); + void insertIndDispTrait(TraitType trType, DispersalTrait tr) { + spTraitTable.insert(make_pair(trType, make_unique(tr))); + }; #endif private: diff --git a/Species.cpp b/Species.cpp index 65d5b24..48e4d11 100644 --- a/Species.cpp +++ b/Species.cpp @@ -499,7 +499,6 @@ void Species::setEmigRules(const emigRules e) { sexDepEmig = e.sexDep; indVarEmig = e.indVar; if (e.emigStage >= 0) emigStage = e.emigStage; -//setGenome(); } emigRules Species::getEmigRules(void) { diff --git a/TraitFactory.h b/TraitFactory.h index f5fc601..5a9bba0 100644 --- a/TraitFactory.h +++ b/TraitFactory.h @@ -14,20 +14,20 @@ class TraitFactory public: TraitFactory() {}; - unique_ptr Create(const TraitType traitType, SpeciesTrait* protoTrait) + unique_ptr Create(const TraitType traitType, SpeciesTrait* pSpTrait) { if (traitType == NEUTRAL) { - return make_unique(protoTrait); + return make_unique(pSpTrait); } else if (traitType == GENETIC_LOAD1 || traitType == GENETIC_LOAD2 || traitType == GENETIC_LOAD3 || traitType == GENETIC_LOAD4 || traitType == GENETIC_LOAD5) { - return make_unique(protoTrait); + return make_unique(pSpTrait); } else { - return make_unique(protoTrait); + return make_unique(pSpTrait); } } }; diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index e030465..3863198 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -483,35 +483,38 @@ void testGenetics() { } } - // Recombination occurs just after recombination site + // Recombination occurs just after selected recombination site { - const int genomeSz = 5; + const int genomeSz = 3; const bool isDiploid{ true }; SpeciesTrait* spTr = createTestSpTrait(createTestGenePositions(genomeSz), isDiploid); // Create individual trait objects DispersalTrait dispTrParent(spTr); // initialisation constructor - DispersalTrait dispTrChild(dispTrParent); // inheritance constructor // Fill mother gene sequence const float valAlleleA(0.0), valAlleleB(1.0); // Mother genotype: - // 000000 - // 111111 + // 000 + // 111 auto motherGenotype = createTestEmigTrGenotype(genomeSz, isDiploid, valAlleleA, valAlleleB); // Trigger inheritance from mother - const unsigned int recombinationSite = pRandom->IRandom(0, genomeSz); // should work for any position + const vector recombinationSites{0, 1, genomeSz - 1}; // should work for any position const int startingChr{0}; // Chromosome A - dispTrChild.triggerInherit(true, motherGenotype, set{recombinationSite}, startingChr); - // for this test we ignore inheritance from father - - // Mother-inherited alleles should have value of chr A before recombination site, chr B after - float valMotherAllele; - for (int i = 0; i < genomeSz; i++) { - valMotherAllele = dispTrChild.getAlleleValueAtLocus(0, i); - assert(valMotherAllele == (i <= recombinationSite ? valAlleleA : valAlleleB)); - // don't check other chromosome, empty bc we did not resolve father inheritance + + for (unsigned int site : recombinationSites) { + DispersalTrait dispTrChild(dispTrParent); // inheritance constructor + dispTrChild.triggerInherit(true, motherGenotype, set{site}, startingChr); + // for this test we ignore inheritance from father + + // Mother-inherited alleles should have value of chr A before recombination site, chr B after + float valMotherAllele; + for (int i = 0; i < genomeSz; i++) { + valMotherAllele = dispTrChild.getAlleleValueAtLocus(0, i); + assert(valMotherAllele == (i <= site ? valAlleleA : valAlleleB)); + // don't check other chromosome, empty bc we did not resolve father inheritance + } } } @@ -598,25 +601,11 @@ void testIndividual() { Individual indMother = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); Individual indFather = Individual(pCell, pPatch, 0, 0, 0, 1.0, false, 0); - - DispersalTrait dispTrParent(spTr); // initialisation constructor - // All genes heterozygote with same alleles for each gene - const float valAlleleA(0.0), valAlleleB(1.0); - const float domCoef(0.0); // no dominance for dispersal traits - vector> gene(2); - gene[0] = make_shared(valAlleleA, domCoef); - gene[1] = make_shared(valAlleleB, domCoef); - - map>> genotype; - for (int i : genePositions) { - genotype.emplace(i, gene); - } - dispTrParent.overwriteGenes(genotype); - indMother.insertIndDispTrait(TraitType::E_D0, dispTrParent); - indFather.insertIndDispTrait(TraitType::E_D0, dispTrParent); - + indMother.setUpGenes(pSpecies, 1.0); + indFather.setUpGenes(pSpecies, 1.0); Individual indChild = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); - indChild.inheritTraits(pSpecies, &indMother, &indFather, 1.0); + + indChild.inheritTraits(pSpecies, &indMother, &indFather, 1.0); cout << endl; } } From 9d9508a699bba492498dbed78b704d082a00ca94 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 19 Jun 2024 16:48:43 +0100 Subject: [PATCH 164/332] progress test #30 --- DispersalTrait.cpp | 9 +++++++++ DispersalTrait.h | 1 + unit_tests/testIndividual.cpp | 24 ++++++++++++++++++++++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/DispersalTrait.cpp b/DispersalTrait.cpp index fa881d9..03b0e61 100644 --- a/DispersalTrait.cpp +++ b/DispersalTrait.cpp @@ -456,6 +456,15 @@ float DispersalTrait::getAlleleValueAtLocus(short whichChromosome, int position) } #if RSDEBUG // Testing only + +// Get allele ID at locus +float DispersalTrait::getAlleleIDAtLocus(short whichChromosome, int position) const { + auto it = genes.find(position); + if (it == genes.end()) + throw runtime_error("The Dispersal locus queried for its allele value does not exist."); + return it->second[whichChromosome].get()->getAlleleValue(); +} + // Create a default set of alleles for testing map>> createTestEmigTrGenotype( const int genomeSz, diff --git a/DispersalTrait.h b/DispersalTrait.h index b2bf721..aac5087 100644 --- a/DispersalTrait.h +++ b/DispersalTrait.h @@ -57,6 +57,7 @@ class DispersalTrait : public QuantitativeTrait { int startChr) { (this->*_inherit_func_ptr)(fromMother, parentGenes, recomPositions, startChr); } + float getAlleleIDAtLocus(short whichChromosome, int position) const; #endif private: diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 3863198..07e5e65 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -562,6 +562,11 @@ void testGenetics() { } } +bool haveSameEmigD0Allele(const Individual& indA, const Individual& indB, const int& position, short whichHaplo = 0) { + return indA.getTrait(E_D0)->getAlleleValueAtLocus(whichHaplo, position) + == indB.getTrait(E_D0)->getAlleleValueAtLocus(whichHaplo, position); +} + void testIndividual() { // Kernel-based transfer @@ -580,7 +585,6 @@ void testIndividual() { // Count times c1 = A & B; c2 = B & C have same alleles // Assert c1 > c2 { - Patch* pPatch = new Patch(0, 0); Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); @@ -605,7 +609,23 @@ void testIndividual() { indFather.setUpGenes(pSpecies, 1.0); Individual indChild = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); - indChild.inheritTraits(pSpecies, &indMother, &indFather, 1.0); cout << endl; + indChild.inheritTraits(pSpecies, &indMother, &indFather, 1.0); + + int countRecombineTogetherAB = 0; + int countRecombineTogetherAC = 0; + + // for i in ... + { + bool hasInheritedA0 = haveSameEmigD0Allele(indChild, indMother, 0); + bool hasInheritedB0 = haveSameEmigD0Allele(indChild, indMother, 1); + bool hasInheritedC0 = haveSameEmigD0Allele(indChild, indMother, 2); + + countRecombineTogetherAB += (hasInheritedA0 && hasInheritedB0) + || (!hasInheritedA0 && !hasInheritedB0); + countRecombineTogetherAC += (hasInheritedA0 && hasInheritedC0) + || (!hasInheritedA0 && !hasInheritedC0); + } + assert(countRecombineTogetherAB > countRecombineTogetherAC); } } From 74a6ab7ff1465a001109ff14c824eff4e4bf7990 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 19 Jun 2024 19:24:37 +0100 Subject: [PATCH 165/332] genetic linkage works, fix test #30 --- DispersalTrait.cpp | 4 ++-- DispersalTrait.h | 2 +- GeneticFitnessTrait.cpp | 12 +++++++++++- GeneticFitnessTrait.h | 3 +++ NeutralTrait.cpp | 11 ++++++++++- NeutralTrait.h | 3 +++ QuantitativeTrait.h | 3 +++ unit_tests/testIndividual.cpp | 17 +++++++++-------- 8 files changed, 42 insertions(+), 13 deletions(-) diff --git a/DispersalTrait.cpp b/DispersalTrait.cpp index 03b0e61..ab68815 100644 --- a/DispersalTrait.cpp +++ b/DispersalTrait.cpp @@ -458,11 +458,11 @@ float DispersalTrait::getAlleleValueAtLocus(short whichChromosome, int position) #if RSDEBUG // Testing only // Get allele ID at locus -float DispersalTrait::getAlleleIDAtLocus(short whichChromosome, int position) const { +int DispersalTrait::getAlleleIDAtLocus(short whichChromosome, int position) const { auto it = genes.find(position); if (it == genes.end()) throw runtime_error("The Dispersal locus queried for its allele value does not exist."); - return it->second[whichChromosome].get()->getAlleleValue(); + return it->second[whichChromosome].get()->getId(); } // Create a default set of alleles for testing diff --git a/DispersalTrait.h b/DispersalTrait.h index aac5087..0947148 100644 --- a/DispersalTrait.h +++ b/DispersalTrait.h @@ -57,7 +57,7 @@ class DispersalTrait : public QuantitativeTrait { int startChr) { (this->*_inherit_func_ptr)(fromMother, parentGenes, recomPositions, startChr); } - float getAlleleIDAtLocus(short whichChromosome, int position) const; + int getAlleleIDAtLocus(short whichChromosome, int position) const; #endif private: diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index 1625966..62346e1 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -419,4 +419,14 @@ float GeneticFitnessTrait::getAlleleValueAtLocus(short whichChromosome, int posi if (it == genes.end()) throw runtime_error("The genetic load locus queried for its allele value does not exist."); return it->second[whichChromosome] == 0 ? wildType->getAlleleValue() : it->second[whichChromosome]->getAlleleValue(); -} \ No newline at end of file +} + +#if RSDEBUG // Testing only +// Get allele ID at locus +int GeneticFitnessTrait::getAlleleIDAtLocus(short whichChromosome, int position) const { + auto it = genes.find(position); + if (it == genes.end()) + throw runtime_error("The Dispersal locus queried for its allele value does not exist."); + return it->second[whichChromosome].get()->getId(); +} +#endif // RSDEBUG \ No newline at end of file diff --git a/GeneticFitnessTrait.h b/GeneticFitnessTrait.h index 26f4e44..02a87ad 100644 --- a/GeneticFitnessTrait.h +++ b/GeneticFitnessTrait.h @@ -48,6 +48,9 @@ class GeneticFitnessTrait : public QuantitativeTrait { virtual float getAlleleValueAtLocus(short chromosome, int position) const override; virtual int countHeterozygoteLoci() const; virtual bool isHeterozygoteAtLocus(int locus) const override; +#if RSDEBUG // for testing only + int getAlleleIDAtLocus(short whichChromosome, int position) const; +#endif private: diff --git a/NeutralTrait.cpp b/NeutralTrait.cpp index 7c55c0c..3e278d5 100644 --- a/NeutralTrait.cpp +++ b/NeutralTrait.cpp @@ -283,4 +283,13 @@ float NeutralTrait::getAlleleValueAtLocus(short whichChromosome, int position) c if (it == genes.end()) //no mutations there throw runtime_error("The neutral locus queried for its allele value does not exist."); return it->second[whichChromosome]; -} \ No newline at end of file +} + +#if RSDEBUG // Testing only +// Get allele ID at locus +int NeutralTrait::getAlleleIDAtLocus(short whichChromosome, int position) const { + // for neutral genes this is the same as the allele value + // need this declaration for quanti trait that use an actual ID + return getAlleleValueAtLocus(whichChromosome, position); +} +#endif // RSDEBUG \ No newline at end of file diff --git a/NeutralTrait.h b/NeutralTrait.h index 4581433..e2a0e6d 100644 --- a/NeutralTrait.h +++ b/NeutralTrait.h @@ -49,6 +49,9 @@ class NeutralTrait : public QuantitativeTrait { virtual float getAlleleValueAtLocus(short chromosome, int position) const override; virtual int countHeterozygoteLoci() const; virtual bool isHeterozygoteAtLocus(int locus) const override; +#if RSDEBUG // for testing only + int getAlleleIDAtLocus(short whichChromosome, int position) const; +#endif private: diff --git a/QuantitativeTrait.h b/QuantitativeTrait.h index aab4966..e19a9bf 100644 --- a/QuantitativeTrait.h +++ b/QuantitativeTrait.h @@ -25,6 +25,9 @@ class QuantitativeTrait { virtual bool isHeterozygoteAtLocus(int loci) const = 0; virtual float express() = 0; virtual ~QuantitativeTrait() { } +#if RSDEBUG // for testing only + virtual int getAlleleIDAtLocus(short whichChromosome, int position) const = 0; +#endif }; extern RSrandom* pRandom; diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 07e5e65..5d23fa5 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -563,8 +563,8 @@ void testGenetics() { } bool haveSameEmigD0Allele(const Individual& indA, const Individual& indB, const int& position, short whichHaplo = 0) { - return indA.getTrait(E_D0)->getAlleleValueAtLocus(whichHaplo, position) - == indB.getTrait(E_D0)->getAlleleValueAtLocus(whichHaplo, position); + return indA.getTrait(E_D0)->getAlleleIDAtLocus(whichHaplo, position) + == indB.getTrait(E_D0)->getAlleleIDAtLocus(whichHaplo, position); } void testIndividual() { @@ -588,7 +588,7 @@ void testIndividual() { Patch* pPatch = new Patch(0, 0); Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); - const float recombinationRate = 0.1; + const float recombinationRate = 0.01; const int genomeSz = 10; Species* pSpecies = new Species(); @@ -607,18 +607,19 @@ void testIndividual() { Individual indFather = Individual(pCell, pPatch, 0, 0, 0, 1.0, false, 0); indMother.setUpGenes(pSpecies, 1.0); indFather.setUpGenes(pSpecies, 1.0); - Individual indChild = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); - - indChild.inheritTraits(pSpecies, &indMother, &indFather, 1.0); int countRecombineTogetherAB = 0; int countRecombineTogetherAC = 0; - // for i in ... + const int nbTrials = 100; + for (int i = 0; i < nbTrials; ++i) { + Individual indChild = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + indChild.inheritTraits(pSpecies, &indMother, &indFather, 1.0); + bool hasInheritedA0 = haveSameEmigD0Allele(indChild, indMother, 0); bool hasInheritedB0 = haveSameEmigD0Allele(indChild, indMother, 1); - bool hasInheritedC0 = haveSameEmigD0Allele(indChild, indMother, 2); + bool hasInheritedC0 = haveSameEmigD0Allele(indChild, indMother, genomeSz -1); countRecombineTogetherAB += (hasInheritedA0 && hasInheritedB0) || (!hasInheritedA0 && !hasInheritedB0); From 8c081074296989246c2278a6a4e7919fbfb874ca Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 20 Jun 2024 14:40:54 +0100 Subject: [PATCH 166/332] adding (non) interaction with chromosome breaks --- unit_tests/testIndividual.cpp | 39 +++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 5d23fa5..994229f 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -577,28 +577,36 @@ void testIndividual() { testGenetics(); - // Genetic linkage does occur - // Should also test for interactions with chromosome breaks? - // - // Sample X vectors of recombination sites - // Create traits and resolve inheritance for each vector - // Count times c1 = A & B; c2 = B & C have same alleles - // Assert c1 > c2 + // Genetic linkage + Chromosome breaks + // Considering diallelic genes A, B, C, D with: + // A, B, C sit on chr.1, D sits on chr.2 + // A, B are adjacent, C sits on the other end of chr.1 + // C, D have adjacent positions in genome (but are on separate chr.) + // AB------------C//D + // We simulate 100 inheritance + recombination processes and expect that: + // 1. freq(A,B have same alleles) >> freq(A,C have same alleles) + // 2. 0.65 > freq(C,D have same alleles) > 0.35 despite being adjacent because of chrom. break + // (both freq. have p < 0.001 from a binomial with p 0.5 and 100 trials) { Patch* pPatch = new Patch(0, 0); Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); const float recombinationRate = 0.01; const int genomeSz = 10; + Species* pSpecies = new Species(); - pSpecies->setGeneticParameters( - set{genomeSz - 1}, // a single chromosome + set{genomeSz-2, genomeSz - 1}, // two chromosomes genomeSz, recombinationRate, set{}, "none", set{}, 0 // no output so no sampling ); - const set genePositions = {0, 1, genomeSz - 1}; + + int posA = 0; + int posB = 1; + int posC = genomeSz - 2; + int posD = genomeSz - 1; + const set genePositions = {posA, posB, posC, posD}; const bool isDiploid{ true }; SpeciesTrait* spTr = createTestSpTrait(genePositions, isDiploid); pSpecies->addTrait(TraitType::E_D0, *spTr); @@ -610,6 +618,7 @@ void testIndividual() { int countRecombineTogetherAB = 0; int countRecombineTogetherAC = 0; + int countRecombineTogetherCD = 0; const int nbTrials = 100; for (int i = 0; i < nbTrials; ++i) @@ -617,16 +626,20 @@ void testIndividual() { Individual indChild = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); indChild.inheritTraits(pSpecies, &indMother, &indFather, 1.0); - bool hasInheritedA0 = haveSameEmigD0Allele(indChild, indMother, 0); - bool hasInheritedB0 = haveSameEmigD0Allele(indChild, indMother, 1); - bool hasInheritedC0 = haveSameEmigD0Allele(indChild, indMother, genomeSz -1); + bool hasInheritedA0 = haveSameEmigD0Allele(indChild, indMother, posA); + bool hasInheritedB0 = haveSameEmigD0Allele(indChild, indMother, posB); + bool hasInheritedC0 = haveSameEmigD0Allele(indChild, indMother, posC); + bool hasInheritedD0 = haveSameEmigD0Allele(indChild, indMother, posD); countRecombineTogetherAB += (hasInheritedA0 && hasInheritedB0) || (!hasInheritedA0 && !hasInheritedB0); countRecombineTogetherAC += (hasInheritedA0 && hasInheritedC0) || (!hasInheritedA0 && !hasInheritedC0); + countRecombineTogetherCD += (hasInheritedC0 && hasInheritedD0) + || (!hasInheritedC0 && !hasInheritedD0); } assert(countRecombineTogetherAB > countRecombineTogetherAC); + assert(35 < countRecombineTogetherCD && countRecombineTogetherCD < 65); } } From 184baa26db4c4247f305de3d4e15ae307db5a85c Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 20 Jun 2024 17:04:58 +0100 Subject: [PATCH 167/332] progress on #46 --- CMakeLists.txt | 2 +- SpeciesTrait.cpp | 37 +++++++++++++++++++---- SpeciesTrait.h | 4 +-- unit_tests/testIndividual.cpp | 53 ++++----------------------------- unit_tests/testNeutralStats.cpp | 43 ++++++++++++++++++++++++++ 5 files changed, 84 insertions(+), 55 deletions(-) create mode 100644 unit_tests/testNeutralStats.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 68ba970..0caf9a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ if (NOT batchmode) # that is, RScore as a standalone # specify the C++ standard set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) - add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp "unit_tests/testIndividual.cpp") + add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp "unit_tests/testIndividual.cpp" "unit_tests/testNeutralStats.cpp") else() # that is, RScore compiled as library within RangeShifter_batch add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) endif() diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 6008beb..5c03b0b 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -4,11 +4,15 @@ // Species trait constructor SpeciesTrait::SpeciesTrait( const TraitType& trType, const sex_t& sx, - const set& pos, const ExpressionType& expr, - const DistributionType& initDist, const map initParams, - const DistributionType& dominanceDist, const map dominanceParams, + const set& pos, + const ExpressionType& expr, + const DistributionType& initDist, + const map initParams, + const DistributionType& dominanceDist, + const map dominanceParams, bool isInherited, const float& mutRate, - const DistributionType& mutationDist, const map mutationParams, + const DistributionType& mutationDist, + const map mutationParams, const int nPloidy) : traitType{ trType }, sex{ sx }, @@ -184,7 +188,7 @@ set createTestGenePositions(const int genomeSz) { return genePositions; } -SpeciesTrait* createTestSpTrait(set genePositions, const bool& isDiploid) { +SpeciesTrait* createTestEmigSpTrait(set genePositions, const bool& isDiploid) { // Create species trait const map distParams{ pair{GenParamType::MIN, 0.0}, @@ -207,4 +211,27 @@ SpeciesTrait* createTestSpTrait(set genePositions, const bool& isDiploid) { ); return spTr; } + +SpeciesTrait* createTestNeutralSpTrait(set genePositions, const bool& isDiploid) { + + const map distParams{ + // Set max allele value + pair{GenParamType::MAX, 1.0} + }; + SpeciesTrait* spTr = new SpeciesTrait( + TraitType::NEUTRAL, + sex_t::NA, + genePositions, + ExpressionType::NOTEXPR, + DistributionType::NONE, map{}, // no initial dist specified. all start at max + DistributionType::NONE, map{}, // no dominance + true, // isInherited + 0.0, // mutation rate + DistributionType::SSM, + distParams, + isDiploid ? 2 : 1 + ); + return spTr; +} + #endif // RSDEBUG diff --git a/SpeciesTrait.h b/SpeciesTrait.h index 20b41c4..85f0f53 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -75,8 +75,8 @@ class SpeciesTrait { // Create a default set of gene positions ranging from zero to genome size set createTestGenePositions(const int genomeSz); -SpeciesTrait* createTestSpTrait(set genePositions, const bool& isDiploid); - +SpeciesTrait* createTestEmigSpTrait(set genePositions, const bool& isDiploid); +SpeciesTrait* createTestNeutralSpTrait(set genePositions, const bool& isDiploid); #endif // RSDEBUG #endif // SPECIESTRAITH \ No newline at end of file diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 994229f..b9ffc71 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -424,7 +424,7 @@ void testGenetics() { { const int genomeSz = 5; const bool isDiploid{ true }; - SpeciesTrait* spTr = createTestSpTrait(createTestGenePositions(genomeSz), isDiploid); + SpeciesTrait* spTr = createTestEmigSpTrait(createTestGenePositions(genomeSz), isDiploid); // Heterozygote parent genotypes const float valAlleleMotherA(1.0), valAlleleMotherB(2.0); @@ -457,7 +457,7 @@ void testGenetics() { { const int genomeSz = 5; const bool isDiploid{ false }; - SpeciesTrait* spTr = createTestSpTrait(createTestGenePositions(genomeSz), isDiploid); + SpeciesTrait* spTr = createTestEmigSpTrait(createTestGenePositions(genomeSz), isDiploid); // Heterozygote parent genotypes const float valAlleleMother(5.0); @@ -487,7 +487,7 @@ void testGenetics() { { const int genomeSz = 3; const bool isDiploid{ true }; - SpeciesTrait* spTr = createTestSpTrait(createTestGenePositions(genomeSz), isDiploid); + SpeciesTrait* spTr = createTestEmigSpTrait(createTestGenePositions(genomeSz), isDiploid); // Create individual trait objects DispersalTrait dispTrParent(spTr); // initialisation constructor @@ -517,49 +517,6 @@ void testGenetics() { } } } - - // Genetic linkage does occur - { - // Should also test for interactions with chromosome breaks? - // - // Sample X vectors of recombination sites - // Create traits and resolve inheritance for each vector - // Count times c1 = A & B; c2 = B & C have same alleles - // Assert c1 > c2 - /* - const int genomeSz = 100; - // Genes A, B, C with dist(A,B) << dist(B,C); - const set genePositions = {0, 1, genomeSz - 1 }; - const bool isDiploid{ true }; - SpeciesTrait* spTr = createTestSpTrait(genePositions, isDiploid); - // All genes heterozygote with same alleles for each gene - const float valAlleleA(0.0), valAlleleB(1.0); - const int startingChr{ 0 }; // Chromosome A - - set recombinationSites; - const int nbDraws = 10; - - for (int i = 0; i < nbDraws; i++) { - - if (i > 0) recombinationSites.clear(); - drawRecombinantSites(recombinationSites); - - // Create individual trait objects - DispersalTrait dispTrParent(spTr); // initialisation constructor - DispersalTrait dispTrChild(dispTrParent); // inheritance constructor - auto motherGenotype = createTestEmigTrGenotype(genomeSz, isDiploid, valAlleleA, valAlleleB); - - // Trigger inheritance from mother - dispTrChild.triggerInherit(true, motherGenotype, recombinationSites, startingChr); - // inheritance from father not needed - - // Check linked genes have same alleles more often - // ... - - } - */ - - } } bool haveSameEmigD0Allele(const Individual& indA, const Individual& indB, const int& position, short whichHaplo = 0) { @@ -608,7 +565,7 @@ void testIndividual() { int posD = genomeSz - 1; const set genePositions = {posA, posB, posC, posD}; const bool isDiploid{ true }; - SpeciesTrait* spTr = createTestSpTrait(genePositions, isDiploid); + SpeciesTrait* spTr = createTestEmigSpTrait(genePositions, isDiploid); pSpecies->addTrait(TraitType::E_D0, *spTr); Individual indMother = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); @@ -641,6 +598,8 @@ void testIndividual() { assert(countRecombineTogetherAB > countRecombineTogetherAC); assert(35 < countRecombineTogetherCD && countRecombineTogetherCD < 65); } + + testNeutralStats(); } #endif //RSDEBUG \ No newline at end of file diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp new file mode 100644 index 0000000..5b26cb7 --- /dev/null +++ b/unit_tests/testNeutralStats.cpp @@ -0,0 +1,43 @@ +#if RSDEBUG + +#include "../Community.h" + +void testNeutralStats() { + + // In haploid settings, Ho is always zero + { + const int genomeSz = 4; + Species* pSpecies = new Species(); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + set{}, "none", set{}, 0 // no output so no sampling + ); + const set genePositions = { 0, 1, 3 }; // arbitrary + const bool isDiploid{ false }; + SpeciesTrait* spTr = createTestNeutralSpTrait(genePositions, isDiploid); + pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + + const int nbInds = 2; + for (int i = 0; i < nbInds; i++) { + Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + ind.setUpGenes(pSpecies, 1.0); + pPop->recruit(&ind); + } + + // create a patch with populations with individuals with traits + + auto pNeutralStatistics = make_unique(patchList.size(), nLoci); + pNeutralStatistics->calculateHo( + //set const& patchList, + //const int nbInds, + //const int nbrLoci, + //Species * pSpecies, + //Landscape * pLandscape + ); + assert(pNeutralStatistics->getHo() == 0.0); + } +} + +#endif //RSDEBUG \ No newline at end of file From 4cb66f2a5c1908cc4f5a336a4a93d438ba6dbb7d Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 21 Jun 2024 12:25:00 +0100 Subject: [PATCH 168/332] progress on #46, created a population of 2 with same alleles --- Individual.h | 4 ---- Main.cpp | 4 ++++ NeutralTrait.cpp | 12 ++++++------ SpeciesTrait.cpp | 15 +++++++++------ SpeciesTrait.h | 4 ++-- unit_tests/testIndividual.cpp | 2 -- unit_tests/testNeutralStats.cpp | 13 ++++++++++--- 7 files changed, 31 insertions(+), 23 deletions(-) diff --git a/Individual.h b/Individual.h index cb6f40b..c6378ab 100644 --- a/Individual.h +++ b/Individual.h @@ -400,9 +400,5 @@ extern ofstream DEBUGLOG; extern ofstream outMovePaths; #endif -#if RSDEBUG -void testIndividual(); -#endif - //--------------------------------------------------------------------------- #endif // IndividualH diff --git a/Main.cpp b/Main.cpp index 63faf8a..cf35bdf 100644 --- a/Main.cpp +++ b/Main.cpp @@ -41,12 +41,16 @@ using namespace std; +void testIndividual(); +void testNeutralStats(); + void run_unit_tests() { cout << "******* Unit test output *******" << endl; testRSrandom(); testLandscape(); testIndividual(); testPopulation(); + testNeutralStats(); cout << endl << "************************" << endl; } diff --git a/NeutralTrait.cpp b/NeutralTrait.cpp index 3e278d5..aca83e0 100644 --- a/NeutralTrait.cpp +++ b/NeutralTrait.cpp @@ -16,7 +16,7 @@ NeutralTrait::NeutralTrait(SpeciesTrait* P) // Set default value to user-specified max wildType = (int)mutationParameters.find(MAX)->second - 1; if (wildType > NeutralValUpperBound) - throw logic_error("Error:: max number of alleles cannot exceed " + to_string(NeutralValUpperBound) + ".\n"); + throw logic_error("max number of alleles cannot exceed " + to_string(NeutralValUpperBound) + ".\n"); _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &NeutralTrait::inheritHaploid : &NeutralTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance @@ -27,26 +27,26 @@ NeutralTrait::NeutralTrait(SpeciesTrait* P) _mutate_func_ptr = &NeutralTrait::mutate_KAM; if (mutationDistribution != SSM && mutationDistribution != KAM) - throw logic_error("Error:: wrong mutation distribution for neutral markers, must be KAM or SSM \n"); + throw logic_error("wrong mutation distribution for neutral markers, must be KAM or SSM \n"); if (mutationParameters.count(MAX) != 1) - throw logic_error("Error:: KAM or SSM mutation distribution parameter must contain max value (e.g. max= ), max cannot exceed 256 \n"); + throw logic_error("KAM or SSM mutation distribution parameter must contain max value (e.g. max= ), max cannot exceed 256 \n"); DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); map initialParameters = pSpeciesTrait->getInitialParameters(); if (mutationDistribution == SSM && initialDistribution != UNIFORM) - throw logic_error("Error:: If using SSM mutation model must initialise genome with alleles (microsats) \n"); + throw logic_error("If using SSM mutation model for neutral trait, must use uniform initial distribution.\n"); switch (initialDistribution) { case UNIFORM: { if (initialParameters.count(MAX) != 1) - throw logic_error("Error:: initial distribution parameter must contain one max value if set to UNIFORM (e.g. max= ), max cannot exceed " + to_string(NeutralValUpperBound) + "\n"); + throw logic_error("initial distribution parameter must contain one max value if set to UNIFORM (e.g. max= ), max cannot exceed " + to_string(NeutralValUpperBound) + "\n"); float maxNeutralVal = initialParameters.find(MAX)->second; if (maxNeutralVal > NeutralValUpperBound) { - throw logic_error("Warning:: initial distribution parameter max cannot exceed " + to_string(NeutralValUpperBound) + ", resetting to " + to_string(NeutralValUpperBound) + "\n"); + throw logic_error("initial distribution parameter max cannot exceed " + to_string(NeutralValUpperBound) + ", resetting to " + to_string(NeutralValUpperBound) + "\n"); maxNeutralVal = NeutralValUpperBound; //reserve 255 for wildtype } initialiseUniform(maxNeutralVal); diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 5c03b0b..05b1abd 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -188,7 +188,7 @@ set createTestGenePositions(const int genomeSz) { return genePositions; } -SpeciesTrait* createTestEmigSpTrait(set genePositions, const bool& isDiploid) { +SpeciesTrait* createTestEmigSpTrait(const set& genePositions, const bool& isDiploid) { // Create species trait const map distParams{ pair{GenParamType::MIN, 0.0}, @@ -212,22 +212,25 @@ SpeciesTrait* createTestEmigSpTrait(set genePositions, const bool& isDiploi return spTr; } -SpeciesTrait* createTestNeutralSpTrait(set genePositions, const bool& isDiploid) { +SpeciesTrait* createTestNeutralSpTrait(const float& maxAlleleVal, const set& genePositions, const bool& isDiploid) { const map distParams{ // Set max allele value - pair{GenParamType::MAX, 1.0} + pair{GenParamType::MAX, maxAlleleVal} }; SpeciesTrait* spTr = new SpeciesTrait( TraitType::NEUTRAL, sex_t::NA, genePositions, ExpressionType::NOTEXPR, - DistributionType::NONE, map{}, // no initial dist specified. all start at max - DistributionType::NONE, map{}, // no dominance + // Sample initial values from uniform(0, max) + DistributionType::UNIFORM, distParams, + // No dominance + DistributionType::NONE, map{}, true, // isInherited 0.0, // mutation rate - DistributionType::SSM, + // Mutation sampled from a uniform(0, max) + DistributionType::KAM, distParams, isDiploid ? 2 : 1 ); diff --git a/SpeciesTrait.h b/SpeciesTrait.h index 85f0f53..dc4704f 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -75,8 +75,8 @@ class SpeciesTrait { // Create a default set of gene positions ranging from zero to genome size set createTestGenePositions(const int genomeSz); -SpeciesTrait* createTestEmigSpTrait(set genePositions, const bool& isDiploid); -SpeciesTrait* createTestNeutralSpTrait(set genePositions, const bool& isDiploid); +SpeciesTrait* createTestEmigSpTrait(const set& genePositions, const bool& isDiploid); +SpeciesTrait* createTestNeutralSpTrait(const float& maxAlleleVal, const set& genePositions, const bool& isDiploid); #endif // RSDEBUG #endif // SPECIESTRAITH \ No newline at end of file diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index b9ffc71..0a0d621 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -598,8 +598,6 @@ void testIndividual() { assert(countRecombineTogetherAB > countRecombineTogetherAC); assert(35 < countRecombineTogetherCD && countRecombineTogetherCD < 65); } - - testNeutralStats(); } #endif //RSDEBUG \ No newline at end of file diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index 5b26cb7..cd3aa69 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -16,18 +16,24 @@ void testNeutralStats() { ); const set genePositions = { 0, 1, 3 }; // arbitrary const bool isDiploid{ false }; - SpeciesTrait* spTr = createTestNeutralSpTrait(genePositions, isDiploid); + const float maxAlleleVal = 0.0; // sample from zero to zero, i.e. all same allele + SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + // not sure if patch zero (matrix) is ok + Patch* pPatch = new Patch(0, 0); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + pPatch->addCell(pCell, 0, 0); + const int nbInds = 2; + Population* pPop = new Population(pSpecies, pPatch, nbInds, 1); + /* for (int i = 0; i < nbInds; i++) { Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); ind.setUpGenes(pSpecies, 1.0); pPop->recruit(&ind); } - // create a patch with populations with individuals with traits - auto pNeutralStatistics = make_unique(patchList.size(), nLoci); pNeutralStatistics->calculateHo( //set const& patchList, @@ -37,6 +43,7 @@ void testNeutralStats() { //Landscape * pLandscape ); assert(pNeutralStatistics->getHo() == 0.0); + */ } } From 09e986cc54c29fc61c225532153f40dfce57efe3 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 21 Jun 2024 13:52:10 +0100 Subject: [PATCH 169/332] fix test #47, heterosigozity is zero in haploid systems --- unit_tests/testNeutralStats.cpp | 62 ++++++++++++++++----------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index cd3aa69..b32e6b7 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -6,44 +6,42 @@ void testNeutralStats() { // In haploid settings, Ho is always zero { - const int genomeSz = 4; - Species* pSpecies = new Species(); - pSpecies->setGeneticParameters( - set{genomeSz - 1}, // single chromosome - genomeSz, - 0.0, // no recombination - set{}, "none", set{}, 0 // no output so no sampling - ); - const set genePositions = { 0, 1, 3 }; // arbitrary - const bool isDiploid{ false }; - const float maxAlleleVal = 0.0; // sample from zero to zero, i.e. all same allele - SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); - pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + // Create genetic structure + const int genomeSz = 4; + Species* pSpecies = new Species(); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + set{}, "none", set{}, 0 // no output so no sampling + ); + const set genePositions = { 0, 1, 3 }; // arbitrary + const bool isDiploid{ false }; + const float maxAlleleVal = 255; // arbitrary + SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); + pSpecies->addTrait(TraitType::NEUTRAL, *spTr); - // not sure if patch zero (matrix) is ok - Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); - pPatch->addCell(pCell, 0, 0); + // Create empty 1-patch, 1-cell landscape + Landscape* pLandscape = new Landscape; + Patch* pPatch = pLandscape->newPatch(0); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + pPatch->addCell(pCell, 0, 0); - const int nbInds = 2; - Population* pPop = new Population(pSpecies, pPatch, nbInds, 1); - /* - for (int i = 0; i < nbInds; i++) { - Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); - ind.setUpGenes(pSpecies, 1.0); - pPop->recruit(&ind); - } + // Initialise population + const int nbInds = 2; + Population* pPop = new Population(pSpecies, pPatch, nbInds, 1); - auto pNeutralStatistics = make_unique(patchList.size(), nLoci); + // Calculate heterozygosity + set patchList{ pPatch->getPatchNum()}; + auto pNeutralStatistics = make_unique(patchList.size(), genePositions.size()); pNeutralStatistics->calculateHo( - //set const& patchList, - //const int nbInds, - //const int nbrLoci, - //Species * pSpecies, - //Landscape * pLandscape + patchList, + nbInds, + genePositions.size(), + pSpecies, + pLandscape ); assert(pNeutralStatistics->getHo() == 0.0); - */ } } From 387b745e1c3561c0b243c30151a2a7ce97acc238 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 21 Jun 2024 14:47:59 +0100 Subject: [PATCH 170/332] write test for #47, that was easy --- unit_tests/testNeutralStats.cpp | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index b32e6b7..ee8ab25 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -43,6 +43,46 @@ void testNeutralStats() { ); assert(pNeutralStatistics->getHo() == 0.0); } + + // If every individual in a sample is homozygote, Ho is zero + { + // Create genetic structure + const int genomeSz = 4; + Species* pSpecies = new Species(); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + set{}, "none", set{}, 0 // no output so no sampling + ); + const set genePositions = { 0, 1, 3 }; // arbitrary + const bool isDiploid{ true }; + const float maxAlleleVal = 0; // sample in uniform(0,0) so every individual is homozygote + SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); + pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + + // Create empty 1-patch, 1-cell landscape + Landscape* pLandscape = new Landscape; + Patch* pPatch = pLandscape->newPatch(0); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + pPatch->addCell(pCell, 0, 0); + + // Initialise population + const int nbInds = 2; + Population* pPop = new Population(pSpecies, pPatch, nbInds, 1); + + // Calculate heterozygosity + set patchList{ pPatch->getPatchNum() }; + auto pNeutralStatistics = make_unique(patchList.size(), genePositions.size()); + pNeutralStatistics->calculateHo( + patchList, + nbInds, + genePositions.size(), + pSpecies, + pLandscape + ); + assert(pNeutralStatistics->getHo() == 0.0); + } } #endif //RSDEBUG \ No newline at end of file From 7ea78c06fffa8556898816ba1a4603fbedfd1a18 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 21 Jun 2024 16:20:40 +0100 Subject: [PATCH 171/332] fix #47, sampling did not happen and test was insufficient --- Species.cpp | 3 +- unit_tests/testNeutralStats.cpp | 121 ++++++++++++++++++++++++++++---- 2 files changed, 109 insertions(+), 15 deletions(-) diff --git a/Species.cpp b/Species.cpp index 48e4d11..1e5a75f 100644 --- a/Species.cpp +++ b/Species.cpp @@ -121,7 +121,8 @@ short Species::getSpNum(void) { return spNum; } void Species::setDemogr(const demogrParams d) { if (d.repType >= 0 && d.repType <= 2) repType = d.repType; - if (d.repType >= 1) diploid = true; + if (d.repType == 1 || d.repType == 2) diploid = true; + else diploid = false; if (d.repSeasons >= 1) repSeasons = d.repSeasons; stageStruct = d.stageStruct; if (d.propMales > 0.0 && d.propMales < 1.0) propMales = d.propMales; diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index ee8ab25..9e1b5c5 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -2,43 +2,74 @@ #include "../Community.h" +demogrParams createDefltHaploidDemogrParams() { + demogrParams d; + d.repType = 0; + d.repSeasons = 1; + d.stageStruct = false; + d.propMales = 0.5; + d.harem = 1.0; + d.bc = 1.0; + d.lambda = 1.0; + return d; +} + +demogrParams createDefltDiploidDemogrParams() { + demogrParams d; + d.repType = 1; + d.repSeasons = 1; + d.stageStruct = false; + d.propMales = 0.5; + d.harem = 1.0; + d.bc = 1.0; + d.lambda = 1.0; + return d; +} + void testNeutralStats() { // In haploid settings, Ho is always zero { + // Create empty 1-patch, 1-cell landscape + Landscape* pLandscape = new Landscape; + Patch* pPatch = pLandscape->newPatch(0); + const set patchList{ pPatch->getPatchNum() }; + const string indSampling = "all"; + const set stgToSample = { 1 }; + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + pPatch->addCell(pCell, 0, 0); + // Create genetic structure const int genomeSz = 4; Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefltHaploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome genomeSz, 0.0, // no recombination - set{}, "none", set{}, 0 // no output so no sampling + patchList, + indSampling, + stgToSample, + 1 ); const set genePositions = { 0, 1, 3 }; // arbitrary const bool isDiploid{ false }; - const float maxAlleleVal = 255; // arbitrary + const float maxAlleleVal = 0; // sample in uniform(0,0) so every individual is homozygote SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); pSpecies->addTrait(TraitType::NEUTRAL, *spTr); - // Create empty 1-patch, 1-cell landscape - Landscape* pLandscape = new Landscape; - Patch* pPatch = pLandscape->newPatch(0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); - pPatch->addCell(pCell, 0, 0); - // Initialise population const int nbInds = 2; Population* pPop = new Population(pSpecies, pPatch, nbInds, 1); + pPop->sampleIndsWithoutReplacement(indSampling, stgToSample); // Calculate heterozygosity - set patchList{ pPatch->getPatchNum()}; auto pNeutralStatistics = make_unique(patchList.size(), genePositions.size()); pNeutralStatistics->calculateHo( patchList, - nbInds, + nbInds, genePositions.size(), - pSpecies, + pSpecies, pLandscape ); assert(pNeutralStatistics->getHo() == 0.0); @@ -46,14 +77,27 @@ void testNeutralStats() { // If every individual in a sample is homozygote, Ho is zero { + // Create empty 1-patch, 1-cell landscape + Landscape* pLandscape = new Landscape; + Patch* pPatch = pLandscape->newPatch(0); + const set patchList{ pPatch->getPatchNum() }; + const string indSampling = "all"; + const set stgToSample = { 1 }; + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + pPatch->addCell(pCell, 0, 0); + // Create genetic structure const int genomeSz = 4; Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefltDiploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome genomeSz, 0.0, // no recombination - set{}, "none", set{}, 0 // no output so no sampling + patchList, + indSampling, + stgToSample, + 1 ); const set genePositions = { 0, 1, 3 }; // arbitrary const bool isDiploid{ true }; @@ -61,18 +105,59 @@ void testNeutralStats() { SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + // Initialise population + const int nbInds = 2; + Population* pPop = new Population(pSpecies, pPatch, nbInds, 1); + pPop->sampleIndsWithoutReplacement(indSampling, stgToSample); + + // Calculate heterozygosity + auto pNeutralStatistics = make_unique(patchList.size(), genePositions.size()); + pNeutralStatistics->calculateHo( + patchList, + nbInds, + genePositions.size(), + pSpecies, + pLandscape + ); + assert(pNeutralStatistics->getHo() == 0.0); + } + + // If every individual in a sample is heterozygote, Ho is one. + { // Create empty 1-patch, 1-cell landscape Landscape* pLandscape = new Landscape; Patch* pPatch = pLandscape->newPatch(0); + const set patchList{ pPatch->getPatchNum() }; + const string indSampling = "all"; + const set stgToSample = { 1 }; Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); pPatch->addCell(pCell, 0, 0); + // Create genetic structure + const int genomeSz = 4; + Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefltDiploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + patchList, + indSampling, + stgToSample, + 1 + ); + const set genePositions = { 0, 1, 3 }; // arbitrary + const bool isDiploid{ true }; + const float maxAlleleVal = 255; // highly unlikely that same value sampled twice + SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); + pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + // Initialise population const int nbInds = 2; Population* pPop = new Population(pSpecies, pPatch, nbInds, 1); + pPop->sampleIndsWithoutReplacement(indSampling, stgToSample); // Calculate heterozygosity - set patchList{ pPatch->getPatchNum() }; auto pNeutralStatistics = make_unique(patchList.size(), genePositions.size()); pNeutralStatistics->calculateHo( patchList, @@ -81,7 +166,15 @@ void testNeutralStats() { pSpecies, pLandscape ); - assert(pNeutralStatistics->getHo() == 0.0); + assert(pNeutralStatistics->getHo() == 1.0); + } + + // If two sampled pops have zero allele in common, Fst is 1 + // - global Fst + // - per-locus Fst + // - pairwise per-patch Fst + { + } } From 060d1f5b7c777e52855b71d74dfa9c88a13cc7bc Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 21 Jun 2024 17:14:14 +0100 Subject: [PATCH 172/332] set up two patches landscape, progress on #44 --- Community.cpp | 10 +++--- NeutralStatsManager.cpp | 6 ++-- NeutralStatsManager.h | 2 +- unit_tests/testNeutralStats.cpp | 57 +++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 9 deletions(-) diff --git a/Community.cpp b/Community.cpp index b31a235..5f7a181 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1845,7 +1845,7 @@ void Community::writePairwiseFSTFile(Species* pSpecies, const int yr, const int void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool fstat, bool perLocus, bool pairwise) { - const int nAlleles = (int)(pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second); + const int maxNbNeutralAlleles = (int)(pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second); const int nLoci = (int)pSpecies->getNPositionsForTrait(NEUTRAL); const set patchList = pSpecies->getSamplePatches(); int nInds = 0; @@ -1869,19 +1869,19 @@ void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, if (fstat) { pNeutralStatistics->calculateHo(patchList, nInds, nLoci, pSpecies, pLandscape); pNeutralStatistics->calcAllelicDiversityMetrics(patchList, nInds, pSpecies, pLandscape); - pNeutralStatistics->calculateFstatWC(patchList, nInds, nLoci, nAlleles, pSpecies, pLandscape); + pNeutralStatistics->calculateFstatWC(patchList, nInds, nLoci, maxNbNeutralAlleles, pSpecies, pLandscape); writeWCFstatFile(rep, yr, gen); } if (perLocus) { - pNeutralStatistics->calcPerLocusMeanSquaresFst(patchList, nInds, nLoci, nAlleles, pSpecies, pLandscape); + pNeutralStatistics->calcPerLocusMeanSquaresFst(patchList, nInds, nLoci, maxNbNeutralAlleles, pSpecies, pLandscape); pNeutralStatistics->calculatePerLocusHo(patchList, nInds, nLoci, pSpecies, pLandscape); - writeWCPerLocusFstatFile(pSpecies, yr, gen, nAlleles, nLoci, patchList); + writeWCPerLocusFstatFile(pSpecies, yr, gen, maxNbNeutralAlleles, nLoci, patchList); } if (pairwise) { pNeutralStatistics->calcPairwiseWeightedFst(patchList, nInds, nLoci, pSpecies, pLandscape); - writePairwiseFSTFile(pSpecies, yr, gen, nAlleles, nLoci, patchList); + writePairwiseFSTFile(pSpecies, yr, gen, maxNbNeutralAlleles, nLoci, patchList); } } diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 307bce3..f64f023 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -39,7 +39,7 @@ NeutralStatsManager::NeutralStatsManager(const int& nbSampledPatches, const int void NeutralStatsManager::updateAllNeutralTables(Species* pSpecies, Landscape* pLandscape, set const& patchList) { const int nLoci = pSpecies->getNPositionsForTrait(NEUTRAL); - const int nAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second; + const int maxNbNeutralAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second; const int ploidy = pSpecies->isDiploid() ? 2 : 1; // Create / Update community-level NEUTRAL counts table @@ -48,7 +48,7 @@ void NeutralStatsManager::updateAllNeutralTables(Species* pSpecies, Landscape* p } else { // populate the tables with default values for (int thisLocus = 0; thisLocus < nLoci; thisLocus++) { - NeutralCountsTable newNeutralTbl = NeutralCountsTable(nAlleles); + NeutralCountsTable newNeutralTbl = NeutralCountsTable(maxNbNeutralAlleles); commNeutralCountTables.push_back(newNeutralTbl); } } @@ -67,7 +67,7 @@ void NeutralStatsManager::updateAllNeutralTables(Species* pSpecies, Landscape* p } // Add population-level counts to community-level counts for (int thisLocus = 0; thisLocus < nLoci; thisLocus++) { - for (int allele = 0; allele < nAlleles; allele++) { + for (int allele = 0; allele < maxNbNeutralAlleles; allele++) { if (pPop != 0) { patchAlleleCount = pPop->getAlleleTally(thisLocus, allele); diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index ee0fdf4..10e1594 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -50,7 +50,7 @@ struct PatchMatrix struct NeutralCountsTable { public: - NeutralCountsTable(int nAllele) : alleleTallies(nAllele), alleleFrequencies(nAllele), alleleHeterozygoteTallies(nAllele) {}; + NeutralCountsTable(int maxNbNeutralAlleles) : alleleTallies(maxNbNeutralAlleles), alleleFrequencies(maxNbNeutralAlleles), alleleHeterozygoteTallies(maxNbNeutralAlleles) {}; void reset() { fill(alleleTallies.begin(), alleleTallies.end(), 0); fill(alleleFrequencies.begin(), alleleFrequencies.end(), 0); diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index 9e1b5c5..604d504 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -174,7 +174,64 @@ void testNeutralStats() { // - per-locus Fst // - pairwise per-patch Fst { + // Create two-patches landscape + Landscape* pLandscape = new Landscape; + const int nbPatches = 2; + vector patches(nbPatches); + set patchList; + for (int i = 0; i < nbPatches; i++) { + patches[i] = pLandscape->newPatch(i); + Cell* pCell = new Cell(0, 0, (intptr)patches[i], 0); + patches[i]->addCell(pCell, 0, 0); + patchList.insert(patches[i]->getPatchNum()); + } + const string indSampling = "all"; + const set stgToSample = { 1 }; + + // Create genetic structure + const int genomeSz = 4; + Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefltDiploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + patchList, + indSampling, + stgToSample, + 1 + ); + const set genePositions = { 0, 1, 3 }; // arbitrary + const int nbLoci = genePositions.size(); + const bool isDiploid{ true }; + const float maxAlleleVal = 255; // highly unlikely that same value sampled twice + SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); + pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + // Initialise populations + const int nbIndsPerPop = 2; + for (auto p : patches) { + Population* pPop = new Population(pSpecies, p, nbIndsPerPop, 1); + pPop->sampleIndsWithoutReplacement(indSampling, stgToSample); + } + + // Calculate heterozygosity + auto pNeutralStatistics = make_unique(nbPatches, nbLoci); + pNeutralStatistics->updateAllNeutralTables( + pSpecies, + pLandscape, + patchList + ); + const int maxNbNeutralAlleles = static_cast(maxAlleleVal); + pNeutralStatistics->calculateFstatWC( + patchList, + nbIndsPerPop, + nbLoci, + maxNbNeutralAlleles, + pSpecies, + pLandscape + ); + assert(pNeutralStatistics->getFstWC() == 1.0); } } From 6b1048328c59e30f185b50757dac50bed6dde79c Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Wed, 3 Jul 2024 11:21:16 +0200 Subject: [PATCH 173/332] Manually updating files (removing comments and unnecessary outputs) due to error when using git subtree push command -> maybe I am doing it in a wrong order and first do a git subtree push and the a git push? --- Genome.cpp | 2 -- Individual.cpp | 4 ---- Population.cpp | 19 ------------------- 3 files changed, 25 deletions(-) diff --git a/Genome.cpp b/Genome.cpp index 4550e5b..59a68b1 100644 --- a/Genome.cpp +++ b/Genome.cpp @@ -124,14 +124,12 @@ void Chromosome::inherit(const Chromosome* parentChr, const short posn, const sh for (int i = 0; i < nloc; i++) { if (diploid) { pLoci[i].allele[posn] = parentChr->pLoci[i].allele[ix]; - if (probcross >1) Rcpp::Rcout << "Crossover probability: " << probcross << std::endl; if (pRandom->Bernoulli(probcross)) { // crossover occurs if (ix == 0) ix = 1; else ix = 0; } } else pLoci[i].allele[posn] = parentChr->pLoci[i].allele[0]; - if (probmutn >1) Rcpp::Rcout << "Mutation probability: " << probmutn << std::endl; if (pRandom->Bernoulli(probmutn)) { // mutation occurs double intbase = INTBASE; #if RSDEBUG diff --git a/Individual.cpp b/Individual.cpp index e1ab257..76eff15 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -37,7 +37,6 @@ Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short rep indCounter++; // unique identifier for each individual stage = stg; - if (probmale > 1) Rcpp::Rcout << "probmale = " << probmale << std::endl; if (probmale <= 0.0) sex = 0; else sex = pRandom->Bernoulli(probmale); age = a; @@ -922,7 +921,6 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, // scale the appropriate kernel mean to the cell size if (trfr.twinKern) { - if (kern.probKern1 > 1) Rcpp::Rcout << "probKern1 = " << kern.probKern1<< std::endl; if (pRandom->Bernoulli(kern.probKern1)) meandist = kern.meanDist1 / (float)land.resol; else @@ -1051,7 +1049,6 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, else { dispmort = mort.fixedMort; } - if(dispmort > 1) Rcpp::Rcout << "dispmort = " << dispmort << std::endl; if (pRandom->Bernoulli(dispmort)) { status = 7; // dies dispersing = 0; @@ -1113,7 +1110,6 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, if (pPatch == pNatalPatch && path->out == 0 && path->year == path->total) { mortprob = 0.0; } - if (mortprob > 1) Rcpp::Rcout << "mortprob = " << mortprob << std::endl; if (pRandom->Bernoulli(mortprob)) { // individual dies status = 7; dispersing = 0; diff --git a/Population.cpp b/Population.cpp index 9960075..4c6f524 100644 --- a/Population.cpp +++ b/Population.cpp @@ -475,7 +475,6 @@ void Population::reproduction(const float localK, const float envval, const int // determine whether she must miss current breeding attempt ind = inds[i]->getStats(); if (ind.fallow >= sstruct.repInterval) { - if(sstruct.probRep > 1) Rcpp::Rcout << "probRep: " << sstruct.probRep << std::endl; if (pRandom->Bernoulli(sstruct.probRep)) skipbreeding = false; else skipbreeding = true; } @@ -540,7 +539,6 @@ void Population::reproduction(const float localK, const float envval, const int // determine whether she must miss current breeding attempt ind = inds[i]->getStats(); if (ind.fallow >= sstruct.repInterval) { - if(sstruct.probRep > 1) Rcpp::Rcout << "probRep: " << sstruct.probRep << std::endl; if (pRandom->Bernoulli(sstruct.probRep)) skipbreeding = false; else skipbreeding = true; } @@ -757,7 +755,6 @@ void Population::emigration(float localK) } // end of no individual variability - if (disp > 1) Rcpp::Rcout << "disp: " << disp << std::endl; disp = pRandom->Bernoulli(Pdisp); if (disp == 1) { // emigrant @@ -955,8 +952,6 @@ int Population::transfer(Landscape* pLandscape, short landIx) settprob = settDD.s0 / (1.0 + exp(-(popsize / localK - (double)settDD.beta) * (double)settDD.alpha)); - if (settprob > 1) Rcpp::Rcout << "settprob: " << settprob << std::endl; - if (pRandom->Bernoulli(settprob)) { // settlement allowed densdepOK = true; settle.settleStatus = 2; @@ -1238,13 +1233,11 @@ void Population::survival0(float localK, short option0, short option1) if (ind.status < 6 || ind.status == 10) { // not already doomed double probsurv = surv[ind.stage][ind.sex]; // does the individual survive? - if (probsurv > 1) Rcpp::Rcout << "probsurv at stage: " << ind.stage << " and sex " << ind.sex << " : " << probsurv << std::endl; if (pRandom->Bernoulli(probsurv)) { // survives // does the individual develop? double probdev = dev[ind.stage][ind.sex]; if (ind.stage < nStages - 1) { // not final stage if (ind.age >= minAge[ind.stage + 1][ind.sex]) { // old enough to enter next stage - if (probdev > 1) Rcpp::Rcout << "probdev: " << probdev << std::endl; if (pRandom->Bernoulli(probdev)) { inds[i]->developing(); } @@ -1833,18 +1826,6 @@ Individual* Population::catchIndividual( // Translocate a set of individuals wit } } -// --------------------------------------------------------------------------- -// // Add a specified individual to the new or current population of a patch -// void Population::recruitTranslocated(Individual* catched_individual) { -// Rcpp::Rcout << "Recruit translocated individual" << endl; -// Rcpp::Rcout << "Individual ID: " << catched_individual->getId() << endl; -// Rcpp::Rcout << "Size of population" << getNInds() << endl; -// inds.push_back(catched_individual); -// Rcpp::Rcout << "Size of population after translocation" << getNInds() << endl; -// indStats ind = catched_individual->getStats(); -// nInds[ind.stage][ind.sex]++; -// } - // --------------------------------------------------------------------------- bool Population::getSizeSampledInds( ){ From e340dd721fec34c89149e9ca9b2d9de598a97b3d Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 3 Jul 2024 13:18:22 +0100 Subject: [PATCH 174/332] progress debugging #44 --- NeutralStatsManager.cpp | 5 ++--- unit_tests/testNeutralStats.cpp | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index f64f023..89dc413 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -302,7 +302,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int // Calculate F stats nBar = static_cast(totalSampleSize) / nbPopulatedPatches; // average sample size, cannot be less than 1 - nC = (totalSampleSize - sumWeights) / nbPopulatedPatches - 1; + nC = (totalSampleSize - sumWeights) / (nbPopulatedPatches - 1); double nBarMinusOne = (nBar == 1.0) ? 1.0 : nBar - 1.0; // avoid / 0 if exactly 1 ind per pop inverseNbar = 1.0 / nBarMinusOne; inverseNtotal = 1.0 / nbSampledIndsInComm; @@ -311,7 +311,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int double s2, pBar, hBar; double s2Denom = 1.0 / ((nbPopulatedPatches - 1) * nBar); double rTerm = static_cast(nbPopulatedPatches - 1) / nbPopulatedPatches; - double hBarFactor = (2 * nBarMinusOne) / (4 * nBar); + double hBarFactor = (2 * nBar - 1) / (4 * nBar); double a = 0, b = 0, c = 0, intermediateTerm; for (int thisLocus = 0; thisLocus < nLoci; ++thisLocus) { @@ -319,7 +319,6 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int s2 = hBar = 0; pBar = commNeutralCountTables[thisLocus].getFrequency(allele); - for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index 604d504..4a5c47c 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -225,13 +225,13 @@ void testNeutralStats() { const int maxNbNeutralAlleles = static_cast(maxAlleleVal); pNeutralStatistics->calculateFstatWC( patchList, - nbIndsPerPop, + nbIndsPerPop * patchList.size(), nbLoci, maxNbNeutralAlleles, pSpecies, pLandscape ); - assert(pNeutralStatistics->getFstWC() == 1.0); + // assert(pNeutralStatistics->getFstWC() == 0.4); } } From 89eaf9de52984349c89011e64e54b7f6f3c2da3e Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 3 Jul 2024 17:30:46 +0100 Subject: [PATCH 175/332] progress on test for #35 --- Individual.cpp | 12 +++-- Individual.h | 1 + SpeciesTrait.cpp | 7 ++- unit_tests/testIndividual.cpp | 83 +++++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 4 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 3d09b7e..79a501f 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -188,9 +188,9 @@ void Individual::inherit(Species* pSpecies, const Individual* mother) { set recomPositions; //not used here cos haploid but need it for inherit function, not ideal int startingChromosome = 0; - const auto& mumTraits = getTraitTypes(); + const auto& motherTraits = getTraitTypes(); - for (auto const& trait : mumTraits) + for (auto const& trait : motherTraits) { const auto motherTrait = mother->getTrait(trait); auto newTrait = motherTrait->clone(); // shallow copy, pointer to species trait initialised and empty sequence @@ -1591,11 +1591,17 @@ Cell* Individual::getCurrCell() const { return pCurrCell; } - void Individual::setInitAngle(const float angle) { auto pCRW = dynamic_cast(pTrfrData.get()); pCRW->prevdrn = angle; } +// Force mutations to trigger for all traits +void Individual::triggerMutations() { + for (auto const& [trType, indTrait] : spTraitTable) { + indTrait->mutate(); + } +} + #endif // RSDEBUG diff --git a/Individual.h b/Individual.h index c6378ab..3d29cb7 100644 --- a/Individual.h +++ b/Individual.h @@ -349,6 +349,7 @@ class Individual { void insertIndDispTrait(TraitType trType, DispersalTrait tr) { spTraitTable.insert(make_pair(trType, make_unique(tr))); }; + void triggerMutations(); #endif private: diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 05b1abd..b222335 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -51,7 +51,12 @@ SpeciesTrait::SpeciesTrait( switch (paramType) { case MIN: case MAX: case MEAN: - if (!isValidTraitVal(paramVal)) + if ( + (trType == NEUTRAL || trType == GENETIC_LOAD || trType == GENETIC_LOAD1 || + trType == GENETIC_LOAD2 || trType == GENETIC_LOAD3 || trType == GENETIC_LOAD4 || trType == GENETIC_LOAD5) + && !isValidTraitVal(paramVal) + // dispersal traits are cumulative so no value is invalid + ) throw logic_error("Invalid parameter value: mutation parameter " + to_string(paramType) + " must have a valid value for trait" + to_string(traitType) + "."); break; case SD: case SHAPE: case SCALE: diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 0a0d621..c4a7f90 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -598,6 +598,89 @@ void testIndividual() { assert(countRecombineTogetherAB > countRecombineTogetherAC); assert(35 < countRecombineTogetherCD && countRecombineTogetherCD < 65); } + + // Traits can be sex-specific + { + Patch* pPatch = new Patch(0, 0); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + + const int genomeSz = 6; + Species* pSpecies = new Species(); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // one chromosome + genomeSz, + 0.0, // no recombination + set{}, "none", set{}, 0 // no output so no sampling + ); + emigRules emig; + emig.indVar = true; + emig.sexDep = true; + emig.densDep = false; + pSpecies->setEmigRules(emig); + + // Create species trait + //// Shared params + const map initParams{ + // all values are 1 + pair{GenParamType::MIN, 1.0}, + pair{GenParamType::MAX, 1.0} + }; + const map mutationParams{ + // reduction of emigration probability + pair{GenParamType::MIN, -0.5}, + pair{GenParamType::MAX, -0.25} + }; + const bool isDiploid{ true }; + + //// Sex-specific params + const set maleGenePositions = { 0, 2, 4 }; + const set femaleGenePositions = { 1, 3, 5 }; + const float maleMutationRate = 0.0; + const float femaleMutationRate = 1.0; + + SpeciesTrait* spTrM = new SpeciesTrait( + TraitType::E_D0_M, + sex_t::MAL, + maleGenePositions, + ExpressionType::AVERAGE, + // Set all initial alleles values to 1 + DistributionType::UNIFORM, initParams, + DistributionType::NONE, initParams, // no dominance, params are ignored + true, // isInherited + maleMutationRate, // does not mutate + DistributionType::UNIFORM, mutationParams, // not used + isDiploid ? 2 : 1 + ); + + pSpecies->addTrait(TraitType::E_D0_M, *spTrM); + + SpeciesTrait* spTrF = new SpeciesTrait( + TraitType::E_D0_F, + sex_t::FEM, + femaleGenePositions, + ExpressionType::AVERAGE, + // Set all initial alleles values to 1 + DistributionType::UNIFORM, initParams, + DistributionType::NONE, initParams, // no dominance, params are ignored + true, // isInherited + femaleMutationRate, // does not mutate + DistributionType::UNIFORM, mutationParams, // not used + isDiploid ? 2 : 1 + ); + pSpecies->addTrait(TraitType::E_D0_F, *spTrF); + + Individual indFemale = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + Individual indMale = Individual(pCell, pPatch, 0, 0, 0, 1.0, false, 0); + indFemale.setUpGenes(pSpecies, 1.0); + indMale.setUpGenes(pSpecies, 1.0); + indFemale.triggerMutations(); + indMale.triggerMutations(); + + emigTraits femaleEmig = indFemale.getIndEmigTraits(); + emigTraits maleEmig = indMale.getIndEmigTraits(); + assert(femaleEmig.d0 != 1.0); + assert(maleEmig.d0 == 1.0); + } } #endif //RSDEBUG \ No newline at end of file From 25030af208fd85a2b0e4205dfee8b3760e025c49 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 4 Jul 2024 16:09:05 +0100 Subject: [PATCH 176/332] fix test #35, sex-dept traits function --- Individual.cpp | 3 ++- Individual.h | 2 +- unit_tests/testIndividual.cpp | 17 +++++++++++------ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 79a501f..8476497 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1597,10 +1597,11 @@ void Individual::setInitAngle(const float angle) { } // Force mutations to trigger for all traits -void Individual::triggerMutations() { +void Individual::triggerMutations(Species* pSp) { for (auto const& [trType, indTrait] : spTraitTable) { indTrait->mutate(); } + this->setDispersalPhenotypes(pSp, 1.0); } #endif // RSDEBUG diff --git a/Individual.h b/Individual.h index 3d29cb7..f2f3339 100644 --- a/Individual.h +++ b/Individual.h @@ -349,7 +349,7 @@ class Individual { void insertIndDispTrait(TraitType trType, DispersalTrait tr) { spTraitTable.insert(make_pair(trType, make_unique(tr))); }; - void triggerMutations(); + void triggerMutations(Species* pSp); #endif private: diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index c4a7f90..e9e2b2b 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -599,11 +599,14 @@ void testIndividual() { assert(35 < countRecombineTogetherCD && countRecombineTogetherCD < 65); } - // Traits can be sex-specific + // Sex-specific traits use the correct genes + /// Set up a sex-dependent emigration probability with male and female loci + /// Emigration probability is 1 initially, but female trait mutates. { Patch* pPatch = new Patch(0, 0); Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + // Species-level paramters const int genomeSz = 6; Species* pSpecies = new Species(); pSpecies->setGeneticParameters( @@ -651,7 +654,6 @@ void testIndividual() { DistributionType::UNIFORM, mutationParams, // not used isDiploid ? 2 : 1 ); - pSpecies->addTrait(TraitType::E_D0_M, *spTrM); SpeciesTrait* spTrF = new SpeciesTrait( @@ -663,19 +665,22 @@ void testIndividual() { DistributionType::UNIFORM, initParams, DistributionType::NONE, initParams, // no dominance, params are ignored true, // isInherited - femaleMutationRate, // does not mutate + femaleMutationRate, // does mutate DistributionType::UNIFORM, mutationParams, // not used isDiploid ? 2 : 1 ); pSpecies->addTrait(TraitType::E_D0_F, *spTrF); + // Set up male and female individuals, trigger mutations Individual indFemale = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); Individual indMale = Individual(pCell, pPatch, 0, 0, 0, 1.0, false, 0); indFemale.setUpGenes(pSpecies, 1.0); indMale.setUpGenes(pSpecies, 1.0); - indFemale.triggerMutations(); - indMale.triggerMutations(); - + indFemale.triggerMutations(pSpecies); + indMale.triggerMutations(pSpecies); + + // Male should use male trait, still 1 + // Female should use female trait, has mutated emigTraits femaleEmig = indFemale.getIndEmigTraits(); emigTraits maleEmig = indMale.getIndEmigTraits(); assert(femaleEmig.d0 != 1.0); From bc82ac91e8da78ed0aa5618964836eb0cdab22bd Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 8 Jul 2024 17:11:51 +0100 Subject: [PATCH 177/332] use the correct ind var trait, fix #36 --- Individual.h | 14 +++---- Population.cpp | 1 - Population.h | 5 +++ unit_tests/testIndividual.cpp | 74 +++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 8 deletions(-) diff --git a/Individual.h b/Individual.h index f2f3339..fec5a3f 100644 --- a/Individual.h +++ b/Individual.h @@ -366,18 +366,18 @@ class Individual { // 4 = completed settlement // 5 = completed settlement in a suitable neighbouring cell // 6 = died during transfer by failing to find a suitable patch - // (includes exceeding maximum number of steps or crossing - // absorbing boundary) + // (includes exceeding maximum number of steps or crossing + // absorbing boundary) // 7 = died during transfer by constant, step-dependent, - // habitat-dependent or distance-dependent mortality + // habitat-dependent or distance-dependent mortality // 8 = failed to survive annual (demographic) mortality // 9 = exceeded maximum age short fallow; // reproductive seasons since last reproduction bool isDeveloping; - Cell* pPrevCell; // pointer to previous Cell - Cell* pCurrCell; // pointer to current Cell - Patch* pNatalPatch; // pointer to natal Patch - pathData* path; // pointer to path data for movement model + Cell* pPrevCell; // pointer to previous Cell + Cell* pCurrCell; // pointer to current Cell + Patch* pNatalPatch; // pointer to natal Patch + pathData* path; // pointer to path data for movement model std::unique_ptr pEmigTraits; // pointer to emigration traits std::unique_ptr pSettleTraits; // pointer to settlement traits std::unique_ptr pTrfrData; //can be sms, kernel, crw diff --git a/Population.cpp b/Population.cpp index 0871a48..bdedaa3 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1043,7 +1043,6 @@ disperser Population::extractDisperser(int ix) { disperser Population::extractSettler(int ix) { disperser d = disperser(); Cell* pCell; -//Patch* pPatch; indStats ind = inds[ix]->getStats(); pCell = inds[ix]->getLocn(1); diff --git a/Population.h b/Population.h index c077449..40cc4b3 100644 --- a/Population.h +++ b/Population.h @@ -229,6 +229,11 @@ class Population { vector countNbHeterozygotesEachLocus(); double computeHs(); +#if RSDEBUG + // Testing only + void clearInds() { inds.clear(); } // empty inds vector to avoid deallocating individual is used separately in test +#endif // RSDEBUG + private: short nStages; short nSexes; diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index e9e2b2b..9e25ab8 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -1,6 +1,7 @@ #if RSDEBUG #include "../Individual.h" +#include "../Population.h" void testTransferKernels() { // Simple 5*5 cell-based landscape layout @@ -686,6 +687,79 @@ void testIndividual() { assert(femaleEmig.d0 != 1.0); assert(maleEmig.d0 == 1.0); } + + // Individuals use species-level trait when not individual variable, + // and individual-level trait when trait is individual variable + { + float spEmigProb = 1.0; + float indEmigProb = 0.0; + + Patch* pPatch = new Patch(0, 0); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + + // Species-level paramters + const int genomeSz = 1; + Species* pSpecies = new Species(); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // one chromosome + genomeSz, + 0.0, // no recombination + set{}, "none", set{}, 0 // no output so no sampling + ); + emigRules emig; + emig.indVar = false; + emig.stgDep = false; emig.sexDep = false; emig.densDep = false; + pSpecies->setEmigRules(emig); + + emigTraits spEmigTraits; spEmigTraits.d0 = spEmigProb; + pSpecies->setSpEmigTraits(0, 0, spEmigTraits); + + // Create species trait + const map initParams{ + // Emigration probability is always 0 + pair{GenParamType::MIN, indEmigProb}, + pair{GenParamType::MAX, indEmigProb} + }; + const map mutationParams = initParams; // doesn't matter, not used + SpeciesTrait* spTr = new SpeciesTrait( + TraitType::E_D0, + sex_t::NA, + set{ 0 }, // only one locus + ExpressionType::AVERAGE, + // Set all initial alleles values to 1 + DistributionType::UNIFORM, initParams, + DistributionType::NONE, initParams, // no dominance, params are ignored + true, // isInherited + 0.0, // no mutation + DistributionType::UNIFORM, mutationParams, // not used + 2 // diploid + ); + pSpecies->addTrait(TraitType::E_D0, *spTr); + + Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + ind.setUpGenes(pSpecies, 1.0); + + // Create population to trigger emigration selection + Population pop(pSpecies, pPatch, 0, 1.0); + pop.recruit(&ind); + assert(ind.getStatus() == 0); + pop.emigration(100.0); + + // Individual is using the species-wide emigration prob, + // so should be selected to emigrate (status 1) + assert(ind.getStatus() == 1); + + // Change rules to use individual-variable trait + ind.setStatus(0); + emig.indVar = true; + pSpecies->setEmigRules(emig); + pop.emigration(100.0); + + // Individual-level emig prob is zero, must not be emigrating; + assert(ind.getStatus() == 0); + + pop.clearInds(); // empty inds vector to not deallocate individual twice + } } #endif //RSDEBUG \ No newline at end of file From 65d5ac4deb950b8d78d32221aa732f216978e2bd Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 9 Jul 2024 14:28:04 +0100 Subject: [PATCH 178/332] make viability check inside individual for easier tests --- Individual.cpp | 5 +++++ Individual.h | 1 + Population.cpp | 9 +++------ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 8476497..69d6d50 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -307,6 +307,11 @@ int Individual::getStatus(void) { return status; } float Individual::getGeneticFitness(void) { return geneticFitness; } +bool Individual::isViable() const { + float probViability = geneticFitness <= 1.0 ? geneticFitness : 1.0; + return probViability < pRandom->Random(); +} + indStats Individual::getStats(void) { indStats s; s.stage = stage; s.sex = sex; s.age = age; s.status = status; s.fallow = fallow; diff --git a/Individual.h b/Individual.h index fec5a3f..9b5209c 100644 --- a/Individual.h +++ b/Individual.h @@ -268,6 +268,7 @@ class Individual { sex_t getSex(void); int getStatus(void); float getGeneticFitness(void); + bool isViable() const; indStats getStats(void); Cell* getLocn( // Return location (as pointer to Cell) const short // option: 0 = get natal locn, 1 = get current locn diff --git a/Population.cpp b/Population.cpp index bdedaa3..c55edcf 100644 --- a/Population.cpp +++ b/Population.cpp @@ -686,9 +686,7 @@ void Population::reproduction(const float localK, const float envval, const int newJuv->inheritTraits(pSpecies, inds[i], father, resol); } - float probViability = newJuv->getGeneticFitness(); - if (probViability > 1.0) probViability = 1.0; - if (probViability < pRandom->Random()) { + if (!newJuv->isViable()) { delete newJuv; } else { @@ -768,9 +766,8 @@ void Population::reproduction(const float localK, const float envval, const int if (pSpecies->getNTraits() > 0) { newJuv->inheritTraits(pSpecies, inds[i], father, resol); } - float probViability = newJuv->getGeneticFitness(); - if (probViability > 1.0) probViability = 1.0; - if (probViability < pRandom->Random()) { + + if (!newJuv->isViable()) { delete newJuv; } else { From c70733df015775a8a1324ec717dc84ce25458cbc Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 9 Jul 2024 14:53:36 +0100 Subject: [PATCH 179/332] enable shorthand test genotype for gneetic fitness traits --- DispersalTrait.cpp | 24 ++++++++++------ DispersalTrait.h | 14 ++++----- unit_tests/testIndividual.cpp | 53 ++++++++++++++++++++++++++++++++--- 3 files changed, 70 insertions(+), 21 deletions(-) diff --git a/DispersalTrait.cpp b/DispersalTrait.cpp index ab68815..1cf59df 100644 --- a/DispersalTrait.cpp +++ b/DispersalTrait.cpp @@ -465,21 +465,26 @@ int DispersalTrait::getAlleleIDAtLocus(short whichChromosome, int position) cons return it->second[whichChromosome].get()->getId(); } +#if RSDEBUG + // Create a default set of alleles for testing -map>> createTestEmigTrGenotype( - const int genomeSz, - const bool isDiploid, - const float valAlleleA, - const float valAlleleB +// +// Shorthand function to manually set genotypes for dispersal and +// genetic fitness traits, instead of having to manipulate mutations. +map>> createTestGenotype( + const int genomeSz, const bool isDiploid, + const float valAlleleA, + const float valAlleleB, + const float domCoeffA, + const float domCoeffB ) { - const float domCoef(0.0); // no dominance for dispersal traits vector> gene(isDiploid ? 2 : 1); if (isDiploid) { - gene[0] = make_shared(valAlleleA, domCoef); - gene[1] = make_shared(valAlleleB, domCoef); + gene[0] = make_shared(valAlleleA, domCoeffA); + gene[1] = make_shared(valAlleleB, domCoeffB); } else { - gene[0] = make_shared(valAlleleA, domCoef); + gene[0] = make_shared(valAlleleA, domCoeffA); } map>> genotype; for (int i = 0; i < genomeSz; i++) { @@ -487,4 +492,5 @@ map>> createTestEmigTrGenotype( } return genotype; } +#endif RSDEBUG #endif // RSDEBUG \ No newline at end of file diff --git a/DispersalTrait.h b/DispersalTrait.h index 0947148..ac02bff 100644 --- a/DispersalTrait.h +++ b/DispersalTrait.h @@ -94,14 +94,12 @@ class DispersalTrait : public QuantitativeTrait { float expressAdditive(); }; -#if RSDEBUG -// Create a default set of alleles for testing -map>> createTestEmigTrGenotype( - const int genomeSz, - const bool isDiploid, - const float valChrA, - const float valChrB = -99.9 // allow to not use if haploid +map>> createTestGenotype( + const int genomeSz, const bool isDiploid, + const float valAlleleA, + const float valAlleleB = -99.9, // allow no value for haploids + const float domCoeffA = 0.0, // default for dispersal traits + const float domCoeffB = 0.0 ); -#endif RSDEBUG #endif // DISPTRAITH \ No newline at end of file diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 9e25ab8..eb8ccbf 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -430,8 +430,8 @@ void testGenetics() { // Heterozygote parent genotypes const float valAlleleMotherA(1.0), valAlleleMotherB(2.0); const float valAlleleFatherA(3.0), valAlleleFatherB(4.0); - auto motherGenotype = createTestEmigTrGenotype(genomeSz, isDiploid, valAlleleMotherA, valAlleleMotherB); - auto fatherGenotype = createTestEmigTrGenotype(genomeSz, isDiploid, valAlleleFatherA, valAlleleFatherB); + auto motherGenotype = createTestGenotype(genomeSz, isDiploid, valAlleleMotherA, valAlleleMotherB); + auto fatherGenotype = createTestGenotype(genomeSz, isDiploid, valAlleleFatherA, valAlleleFatherB); const int startMotherChr = 0; // Strand A const int startFatherChr = 1; // Strand B @@ -462,7 +462,7 @@ void testGenetics() { // Heterozygote parent genotypes const float valAlleleMother(5.0); - auto motherGenotype = createTestEmigTrGenotype(genomeSz, isDiploid, valAlleleMother); + auto motherGenotype = createTestGenotype(genomeSz, isDiploid, valAlleleMother); const int startMotherChr = 999; // doesn't matter, not used // Create individual trait objects @@ -498,7 +498,7 @@ void testGenetics() { // Mother genotype: // 000 // 111 - auto motherGenotype = createTestEmigTrGenotype(genomeSz, isDiploid, valAlleleA, valAlleleB); + auto motherGenotype = createTestGenotype(genomeSz, isDiploid, valAlleleA, valAlleleB); // Trigger inheritance from mother const vector recombinationSites{0, 1, genomeSz - 1}; // should work for any position @@ -760,6 +760,51 @@ void testIndividual() { pop.clearInds(); // empty inds vector to not deallocate individual twice } + + // Individuals with genetic fitness phenotype = 1 are unviable + { + + + Patch* pPatch = new Patch(0, 0); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + + // Species-level paramters + const int genomeSz = 1; + Species* pSpecies = new Species(); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // one chromosome + genomeSz, + 0.0, // no recombination + set{}, "none", set{}, 0 // no output so no sampling + ); + + // Create species trait + const map initParams{ + // Emigration probability is always 0 + pair{GenParamType::MIN, 0.0}, + pair{GenParamType::MAX, 0.0} + }; + const map mutationParams = initParams; // doesn't matter, not used + SpeciesTrait* spTr = new SpeciesTrait( + TraitType::GENETIC_LOAD, + sex_t::NA, + set{ 0 }, // only one locus + ExpressionType::AVERAGE, + // Set all initial alleles values to 1 + DistributionType::UNIFORM, initParams, + DistributionType::NONE, initParams, // no dominance, params are ignored + true, // isInherited + 0.0, // no mutation + DistributionType::UNIFORM, mutationParams, // not used + 2 // diploid + ); + pSpecies->addTrait(TraitType::GENETIC_LOAD, *spTr); + + Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + ind.setUpGenes(pSpecies, 1.0); + + //assert(!ind.isViable()); + } } #endif //RSDEBUG \ No newline at end of file From 146cadec6b90b8d4692f271a439ee37696573830 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 9 Jul 2024 15:09:05 +0100 Subject: [PATCH 180/332] fix test #39 --- unit_tests/testIndividual.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index eb8ccbf..1cb7113 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -763,8 +763,6 @@ void testIndividual() { // Individuals with genetic fitness phenotype = 1 are unviable { - - Patch* pPatch = new Patch(0, 0); Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); @@ -779,20 +777,22 @@ void testIndividual() { ); // Create species trait - const map initParams{ + const map mutationParams{ // Emigration probability is always 0 - pair{GenParamType::MIN, 0.0}, - pair{GenParamType::MAX, 0.0} + pair{GenParamType::MIN, 1.0}, + pair{GenParamType::MAX, 1.0} }; - const map mutationParams = initParams; // doesn't matter, not used + const map domParams = mutationParams; // all dominance parameters are equal + const map initParams = mutationParams; // doesn't matter, not used + SpeciesTrait* spTr = new SpeciesTrait( TraitType::GENETIC_LOAD, sex_t::NA, set{ 0 }, // only one locus - ExpressionType::AVERAGE, + ExpressionType::MULTIPLICATIVE, // Set all initial alleles values to 1 - DistributionType::UNIFORM, initParams, - DistributionType::NONE, initParams, // no dominance, params are ignored + DistributionType::NONE, initParams, + DistributionType::UNIFORM, domParams, // no dominance, params are ignored true, // isInherited 0.0, // no mutation DistributionType::UNIFORM, mutationParams, // not used @@ -802,8 +802,10 @@ void testIndividual() { Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); ind.setUpGenes(pSpecies, 1.0); + ind.triggerMutations(pSpecies); - //assert(!ind.isViable()); + assert(ind.getGeneticFitness() == 1.0); + assert(!ind.isViable()); } } From 717a314cdb48537e120ff3360e56f96c63abc46b Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 9 Jul 2024 16:19:04 +0100 Subject: [PATCH 181/332] fix error in #39, add test for #40; genetic fitness determines viability correctly --- Individual.cpp | 10 ++++++++-- unit_tests/testIndividual.cpp | 21 ++++++++++++++------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 69d6d50..52fbe33 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -308,8 +308,8 @@ int Individual::getStatus(void) { return status; } float Individual::getGeneticFitness(void) { return geneticFitness; } bool Individual::isViable() const { - float probViability = geneticFitness <= 1.0 ? geneticFitness : 1.0; - return probViability < pRandom->Random(); + float probViability = geneticFitness > 1.0 ? 1.0 : geneticFitness; + return probViability >= pRandom->Random(); } indStats Individual::getStats(void) { @@ -1605,6 +1605,12 @@ void Individual::setInitAngle(const float angle) { void Individual::triggerMutations(Species* pSp) { for (auto const& [trType, indTrait] : spTraitTable) { indTrait->mutate(); + if (trType == GENETIC_LOAD1 + || trType == GENETIC_LOAD2 + || trType == GENETIC_LOAD3 + || trType == GENETIC_LOAD4 + || trType == GENETIC_LOAD5) + geneticFitness *= indTrait->express(); } this->setDispersalPhenotypes(pSp, 1.0); } diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 1cb7113..834bbb3 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -761,7 +761,8 @@ void testIndividual() { pop.clearInds(); // empty inds vector to not deallocate individual twice } - // Individuals with genetic fitness phenotype = 1 are unviable + // Individuals with genetic fitness = 1 are always viable + // Individuals with genetic fitness = 0 are never viable { Patch* pPatch = new Patch(0, 0); Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); @@ -778,7 +779,7 @@ void testIndividual() { // Create species trait const map mutationParams{ - // Emigration probability is always 0 + // Always sample 1 = a lethal mutation pair{GenParamType::MIN, 1.0}, pair{GenParamType::MAX, 1.0} }; @@ -786,7 +787,7 @@ void testIndividual() { const map initParams = mutationParams; // doesn't matter, not used SpeciesTrait* spTr = new SpeciesTrait( - TraitType::GENETIC_LOAD, + TraitType::GENETIC_LOAD1, sex_t::NA, set{ 0 }, // only one locus ExpressionType::MULTIPLICATIVE, @@ -794,17 +795,23 @@ void testIndividual() { DistributionType::NONE, initParams, DistributionType::UNIFORM, domParams, // no dominance, params are ignored true, // isInherited - 0.0, // no mutation - DistributionType::UNIFORM, mutationParams, // not used + 1.0, // will mutate + DistributionType::UNIFORM, mutationParams, // lethal mutation 2 // diploid ); - pSpecies->addTrait(TraitType::GENETIC_LOAD, *spTr); + pSpecies->addTrait(TraitType::GENETIC_LOAD1, *spTr); Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); ind.setUpGenes(pSpecies, 1.0); - ind.triggerMutations(pSpecies); + // By default, all loci are initialised at 0 so individual is viable assert(ind.getGeneticFitness() == 1.0); + assert(ind.isViable()); + + ind.triggerMutations(pSpecies); + + // Individual now bears a lethal allele + assert(ind.getGeneticFitness() == 0.0); assert(!ind.isViable()); } } From 37afae5b67bc158f2622803765cba25f0dc514de Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 9 Jul 2024 18:22:33 +0100 Subject: [PATCH 182/332] check allele dominance works, fix #48 --- DispersalTrait.h | 4 +++ Individual.cpp | 32 ++++++++++++++++++++ Individual.h | 2 ++ unit_tests/testIndividual.cpp | 56 +++++++++++++++++++++++++++++++++-- 4 files changed, 92 insertions(+), 2 deletions(-) diff --git a/DispersalTrait.h b/DispersalTrait.h index ac02bff..0c3a7e6 100644 --- a/DispersalTrait.h +++ b/DispersalTrait.h @@ -94,6 +94,9 @@ class DispersalTrait : public QuantitativeTrait { float expressAdditive(); }; +#if RSDEBUG +// Test utilities + map>> createTestGenotype( const int genomeSz, const bool isDiploid, const float valAlleleA, @@ -101,5 +104,6 @@ map>> createTestGenotype( const float domCoeffA = 0.0, // default for dispersal traits const float domCoeffB = 0.0 ); +#endif //RSDEBUG #endif // DISPTRAITH \ No newline at end of file diff --git a/Individual.cpp b/Individual.cpp index 52fbe33..a4579e4 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1615,5 +1615,37 @@ void Individual::triggerMutations(Species* pSp) { this->setDispersalPhenotypes(pSp, 1.0); } +// Shorthand function to edit a genotype with custom values +void Individual::overrideGenotype(TraitType whichTrait, const map>>& newGenotype) { + + GeneticFitnessTrait* pGenFitTrait; + DispersalTrait* pDispTrait; + + switch (whichTrait) + { + case GENETIC_LOAD1: case GENETIC_LOAD2: case GENETIC_LOAD3: case GENETIC_LOAD4: case GENETIC_LOAD5: + pGenFitTrait = dynamic_cast(this->getTrait(whichTrait)); + pGenFitTrait->getGenes() = newGenotype; + break; + case E_D0: case E_ALPHA: case E_BETA: + case S_S0: case S_ALPHA: case S_BETA: + case E_D0_F: case E_ALPHA_F: case E_BETA_F: + case S_S0_F: case S_ALPHA_F: case S_BETA_F: + case E_D0_M: case E_ALPHA_M: case E_BETA_M: + case S_S0_M: case S_ALPHA_M: case S_BETA_M: + case CRW_STEPLENGTH: case CRW_STEPCORRELATION: + case KERNEL_MEANDIST_1: case KERNEL_MEANDIST_2: case KERNEL_PROBABILITY: + case KERNEL_MEANDIST_1_F: case KERNEL_MEANDIST_2_F: case KERNEL_PROBABILITY_F: + case KERNEL_MEANDIST_1_M: case KERNEL_MEANDIST_2_M: case KERNEL_PROBABILITY_M: + case SMS_DP: case SMS_GB: case SMS_ALPHADB: case SMS_BETADB: + pDispTrait = dynamic_cast(this->getTrait(whichTrait)); + pDispTrait->getGenes() = newGenotype; + break; + default: + throw logic_error("Wrong trait type: please choose a valid dispersal or genetic fitness trait."); + break; + } +}; + #endif // RSDEBUG diff --git a/Individual.h b/Individual.h index 9b5209c..d5072aa 100644 --- a/Individual.h +++ b/Individual.h @@ -351,6 +351,8 @@ class Individual { spTraitTable.insert(make_pair(trType, make_unique(tr))); }; void triggerMutations(Species* pSp); + // Shorthand function to edit a genotype with custom values + void overrideGenotype(TraitType whichTrait, const map>>& newGenotype); #endif private: diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 834bbb3..6663ab7 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -726,7 +726,6 @@ void testIndividual() { sex_t::NA, set{ 0 }, // only one locus ExpressionType::AVERAGE, - // Set all initial alleles values to 1 DistributionType::UNIFORM, initParams, DistributionType::NONE, initParams, // no dominance, params are ignored true, // isInherited @@ -791,7 +790,6 @@ void testIndividual() { sex_t::NA, set{ 0 }, // only one locus ExpressionType::MULTIPLICATIVE, - // Set all initial alleles values to 1 DistributionType::NONE, initParams, DistributionType::UNIFORM, domParams, // no dominance, params are ignored true, // isInherited @@ -814,6 +812,60 @@ void testIndividual() { assert(ind.getGeneticFitness() == 0.0); assert(!ind.isViable()); } + + // A largely dominant alleles overrides the expression of its homologue + { + Patch* pPatch = new Patch(0, 0); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + + // Species-level paramters + const int genomeSz = 1; + Species* pSpecies = new Species(); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // one chromosome + genomeSz, + 0.0, // no recombination + set{}, "none", set{}, 0 // no output so no sampling + ); + + // Create species trait + const map distParams{ + pair{GenParamType::MIN, 0.0}, + pair{GenParamType::MAX, 0.0} + }; + + SpeciesTrait* spTr = new SpeciesTrait( + TraitType::GENETIC_LOAD1, + sex_t::NA, + set{ 0 }, // only one locus + ExpressionType::MULTIPLICATIVE, + DistributionType::NONE, distParams, + DistributionType::UNIFORM, distParams, // no dominance, params are ignored + true, // isInherited + 0.0, // no mutation + DistributionType::UNIFORM, distParams, // lethal mutation + 2 // diploid + ); + pSpecies->addTrait(TraitType::GENETIC_LOAD1, *spTr); + + Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + ind.setUpGenes(pSpecies, 1.0); + + const float valAlleleA = 1.0; // lethal + const float valAlleleB = 0.0; // mild + float domCoefA = 0.00001; // highly recessive + float domCoefB = 1.0; + auto viableGenotype = createTestGenotype(genomeSz, true, valAlleleA, valAlleleB, domCoefA, domCoefB); + ind.overrideGenotype(GENETIC_LOAD1, viableGenotype); + ind.triggerMutations(pSpecies); // no mutations (rate = 0) but updates genetic fitness + assert(ind.isViable()); + + domCoefA = 10000.0; // oh gosh now it's lethal AND dominant + auto lethalGenotype = createTestGenotype(genomeSz, true, valAlleleA, valAlleleB, domCoefA, domCoefB); + ind.overrideGenotype(GENETIC_LOAD1, lethalGenotype); + ind.triggerMutations(pSpecies); + assert(!ind.isViable()); + } } #endif //RSDEBUG \ No newline at end of file From 0c5c1ae007196be9d28024a963340e14b98d51c0 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 11 Jul 2024 11:22:14 +0100 Subject: [PATCH 183/332] confusion over fis vs fit --- NeutralStatsManager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 89dc413..aea43de 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -345,8 +345,8 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int c *= 0.5; fst = a / (a + b + c); // theta hat in eq. 1 in WC 1984 - fis = (a + b) / (a + b + c); // F hat - fit = b / (b + c); // f hat + fit = (a + b) / (a + b + c); // F hat + fis = b / (b + c); // f hat } else { // zero or one sampled pops, cannot compute F stats fst = 0.0; @@ -499,8 +499,8 @@ void NeutralStatsManager::calcPerLocusMeanSquaresFst(set const& patchList, // Total F-stats fst = SIGA / (SIGA + SIGB + SIGW); - fis = (SIGA + SIGB) / (SIGA + SIGB + SIGW); - fit = SIGB / (SIGB + SIGW); + fit = (SIGA + SIGB) / (SIGA + SIGB + SIGW); + fis = SIGB / (SIGB + SIGW); } else { // no variation: only 1 allele (wildtype) at each locus // so don't calculate to avoid division by zero From a2ebaca2dbc9090bfc387e9f95c7ae55874f5fde Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 11 Jul 2024 11:57:46 +0100 Subject: [PATCH 184/332] test for #28, non-inherited trait are reinitialised instead --- unit_tests/testIndividual.cpp | 51 +++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 6663ab7..d41d3d2 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -518,6 +518,55 @@ void testGenetics() { } } } + + // Traits that are not inherited sample their mutations in initial distribution + { + const float initialAlleleVal = 0.5; + const float parentAlleleVal = 0.8; + const bool isInherited = false; + + const int genomeSz = 5; + const bool isDiploid{ false }; + + // Create species trait + const map distParams{ + // all alleles initialised at a single value + pair{GenParamType::MIN, initialAlleleVal}, + pair{GenParamType::MAX, initialAlleleVal} + }; + SpeciesTrait* spTr = new SpeciesTrait( + TraitType::E_D0, + sex_t::NA, + createTestGenePositions(genomeSz), + ExpressionType::ADDITIVE, + DistributionType::UNIFORM, + distParams, + DistributionType::NONE, distParams, // no dominance, not used + isInherited, + 0.0, // no mutations + DistributionType::UNIFORM, distParams, // ignored + isDiploid ? 2 : 1 + ); + + // Heterozygote parent genotypes + auto parentGenotype = createTestGenotype(genomeSz, isDiploid, parentAlleleVal); + const int startMotherChr = 999; // doesn't matter, not used + + // Create individual trait objects + DispersalTrait dispTrParent(spTr); // initialisation constructor + DispersalTrait dispTrChild(dispTrParent); // inheritance constructor + + set recomSites{genomeSz - 1}; + dispTrChild.triggerInherit(true, parentGenotype, recomSites, startMotherChr); + + // Child does not inherit from mother, + // instead allele value is initial value + float valChildAllele; + for (int i = 0; i < genomeSz; i++) { + valChildAllele = dispTrChild.getAlleleValueAtLocus(0, i); + assert(valChildAllele == initialAlleleVal); + } + } } bool haveSameEmigD0Allele(const Individual& indA, const Individual& indB, const int& position, short whichHaplo = 0) { @@ -866,6 +915,8 @@ void testIndividual() { ind.triggerMutations(pSpecies); assert(!ind.isViable()); } + + } #endif //RSDEBUG \ No newline at end of file From 31d9e1cf5b1035f6df720285849a5c9b4072359d Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 11 Jul 2024 12:03:22 +0100 Subject: [PATCH 185/332] more robust test for #28 --- unit_tests/testIndividual.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index d41d3d2..9b571c0 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -548,12 +548,13 @@ void testGenetics() { isDiploid ? 2 : 1 ); - // Heterozygote parent genotypes + // Create individual trait objects + DispersalTrait dispTrParent(spTr); // initialisation constructor auto parentGenotype = createTestGenotype(genomeSz, isDiploid, parentAlleleVal); const int startMotherChr = 999; // doesn't matter, not used + dispTrParent.overwriteGenes(parentGenotype); + assert(dispTrParent.getAlleleValueAtLocus(0, 0) == parentAlleleVal); - // Create individual trait objects - DispersalTrait dispTrParent(spTr); // initialisation constructor DispersalTrait dispTrChild(dispTrParent); // inheritance constructor set recomSites{genomeSz - 1}; From 20052372e753897813efcbb23b746743524f6a4e Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 11 Jul 2024 13:58:38 +0100 Subject: [PATCH 186/332] genetic fitness mutations are indeed constrained below 1 fix half #31 --- unit_tests/testIndividual.cpp | 39 +++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 9b571c0..5c526ea 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -568,6 +568,45 @@ void testGenetics() { assert(valChildAllele == initialAlleleVal); } } + + // Genetic fitness mutations are constrained between -1 or 1 + { + // Most likely (~96%) to sample a mutation > 1 + const float gammaMutShapeParam = 5.0; + const float gammaMutScaleParam = 1.0; + + const int genomeSz = 5; + const bool isDiploid{ false }; + + // Create species trait + const map mutationParams{ + // all alleles initialised at a single value + pair{GenParamType::SHAPE, gammaMutShapeParam}, + pair{GenParamType::SCALE, gammaMutScaleParam} + }; + const map placeholderParams = mutationParams; + + SpeciesTrait* spTr = new SpeciesTrait( + TraitType::GENETIC_LOAD1, + sex_t::NA, + createTestGenePositions(genomeSz), + ExpressionType::MULTIPLICATIVE, + DistributionType::NONE, placeholderParams, // not used for genetic load + DistributionType::GAMMA, placeholderParams, // doesn't matter for this test + true, + 1.0, // every site mutates + DistributionType::GAMMA, mutationParams, + isDiploid ? 2 : 1 + ); + + // Create individual trait object + GeneticFitnessTrait traitInd(spTr); // initialisation constructor + traitInd.mutate(); + for (int i = 0; i < genomeSz; i++) { + float valAllele = traitInd.getAlleleValueAtLocus(0, i); + assert(valAllele <= 1.0); + } + } } bool haveSameEmigD0Allele(const Individual& indA, const Individual& indB, const int& position, short whichHaplo = 0) { From f91fca72e4a25eff83fa2b93deedd462d3ce1dae Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 12 Jul 2024 11:47:08 +0100 Subject: [PATCH 187/332] fix to_string function for enum types --- Parameters.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ Parameters.h | 8 +++++ 2 files changed, 96 insertions(+) diff --git a/Parameters.cpp b/Parameters.cpp index 0c37dab..8330219 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -379,6 +379,94 @@ string paramSim::getDir(int option) { return s; } +string to_string(const TraitType& tr) { + switch (tr) + { + case NEUTRAL: return "NEUTRAL"; + case GENETIC_LOAD: return "GENETIC_LOAD"; + case GENETIC_LOAD1: return "GENETIC_LOAD1"; + case GENETIC_LOAD2: return "GENETIC_LOAD2"; + case GENETIC_LOAD3: return "GENETIC_LOAD3"; + case GENETIC_LOAD4: return "GENETIC_LOAD4"; + case GENETIC_LOAD5: return "GENETIC_LOAD5"; + + case E_D0: return "E_D0"; + case E_D0_M: return "E_D0_M"; + case E_D0_F: return "E_D0_F"; + case E_ALPHA: return "E_ALPHA"; + case E_ALPHA_M: return "E_ALPHA_M"; + case E_ALPHA_F: return "E_ALPHA_F"; + case E_BETA: return "E_BETA"; + case E_BETA_M: return "E_BETA_M"; + case E_BETA_F: return "E_BETA_F"; + + case S_S0: return "S_S0"; + case S_S0_M: return "S_S0_M"; + case S_S0_F: return "S_S0_F"; + case S_ALPHA: return "S_ALPHA"; + case S_ALPHA_M: return "S_ALPHA_M"; + case S_ALPHA_F: return "S_ALPHA_F"; + case S_BETA: return "S_BETA"; + case S_BETA_M: return "S_BETA_M"; + case S_BETA_F: return "S_BETA_F"; + + case CRW_STEPLENGTH: return "CRW_STEPLENGTH"; + case CRW_STEPCORRELATION: return "CRW_STEPCORRELATION"; + case KERNEL_MEANDIST_1: return "KERNEL_MEANDIST_1"; + case KERNEL_MEANDIST_2: return "KERNEL_MEANDIST_2"; + case KERNEL_MEANDIST_1_F: return "KERNEL_MEANDIST_1_F"; + case KERNEL_MEANDIST_2_F: return "KERNEL_MEANDIST_2_F"; + case KERNEL_MEANDIST_1_M: return "KERNEL_MEANDIST_1_M"; + case KERNEL_MEANDIST_2_M: return "KERNEL_MEANDIST_2_M"; + case KERNEL_PROBABILITY: return "KERNEL_PROBABILITY"; + case KERNEL_PROBABILITY_F: return "KERNEL_PROBABILITY_F"; + case KERNEL_PROBABILITY_M: return "KERNEL_PROBABILITY_M"; + + case SMS_DP: return "SMS_DP"; + case SMS_GB: return "SMS_GB"; + case SMS_ALPHADB: return "SMS_ALPHADB"; + case SMS_BETADB: return "SMS_BETADB"; + case INVALID_TRAIT: return "INVALID_TRAIT"; + } +} + +string to_string(const GenParamType& param) { + switch (param) + { + case MEAN: return "MEAN"; + case SD: return "SD"; + case MIN: return "MIN"; + case MAX: return "MAX"; + case SHAPE: return "SHAPE"; + case SCALE: return "SCALE"; + case INVALID: return "INVALID"; + } +} + +string to_string(const DistributionType& dist) { + switch (dist) + { + case UNIFORM: return "UNIFORM"; + case NORMAL: return "NORMAL"; + case GAMMA: return "GAMMA"; + case NEGEXP: return "NEGEXP"; + case SCALED: return "SCALED"; + case KAM: return "KAM"; + case SSM: return "SSM"; + case NONE: return "NONE"; + } +} + +string to_string(const ExpressionType& expr) { + switch (expr) + { + case AVERAGE: return "AVERAGE"; + case ADDITIVE: return "ADDITIVE"; + case NOTEXPR: return "NOTEXPR"; + case MULTIPLICATIVE: return "MULTIPLICATIVE"; + } +} + #if RS_RCPP bool paramSim::getReturnPopRaster(void) { return ReturnPopRaster; } bool paramSim::getCreatePopFile(void) { return CreatePopFile; } diff --git a/Parameters.h b/Parameters.h index e5e6d0c..afbdea9 100644 --- a/Parameters.h +++ b/Parameters.h @@ -130,6 +130,14 @@ enum GenParamType { MEAN, SD, MIN, MAX, SHAPE, SCALE, INVALID }; enum DistributionType { UNIFORM, NORMAL, GAMMA, NEGEXP, SCALED, KAM, SSM, NONE }; enum ExpressionType { AVERAGE, ADDITIVE, NOTEXPR, MULTIPLICATIVE }; +string to_string(const TraitType& tr); + +string to_string(const GenParamType& param); + +string to_string(const DistributionType& dist); + +string to_string(const ExpressionType& expr); + /** Param's types **/ typedef enum { KERNEL, SMS, CRW} movement_t; From cead5dc2cf9be8a4030aebfb2d91469c2cf7ae34 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 12 Jul 2024 11:55:40 +0100 Subject: [PATCH 188/332] fix #31; genetic fitness mutations always > -1 --- unit_tests/testIndividual.cpp | 101 ++++++++++++++++++++++++---------- 1 file changed, 71 insertions(+), 30 deletions(-) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 5c526ea..4ced6fd 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -571,42 +571,83 @@ void testGenetics() { // Genetic fitness mutations are constrained between -1 or 1 { - // Most likely (~96%) to sample a mutation > 1 - const float gammaMutShapeParam = 5.0; - const float gammaMutScaleParam = 1.0; + { + // Most likely (~96%) to sample a mutation > 1 + const float gammaMutShapeParam = 5.0; + const float gammaMutScaleParam = 1.0; - const int genomeSz = 5; - const bool isDiploid{ false }; + const int genomeSz = 5; + const bool isDiploid{ false }; - // Create species trait - const map mutationParams{ - // all alleles initialised at a single value - pair{GenParamType::SHAPE, gammaMutShapeParam}, - pair{GenParamType::SCALE, gammaMutScaleParam} - }; - const map placeholderParams = mutationParams; + // Create species trait + const map mutationParams{ + // all alleles initialised at a single value + pair{GenParamType::SHAPE, gammaMutShapeParam}, + pair{GenParamType::SCALE, gammaMutScaleParam} + }; + const map placeholderParams = mutationParams; + + SpeciesTrait* spTr = new SpeciesTrait( + TraitType::GENETIC_LOAD1, + sex_t::NA, + createTestGenePositions(genomeSz), + ExpressionType::MULTIPLICATIVE, + DistributionType::NONE, placeholderParams, // not used for genetic load + DistributionType::GAMMA, placeholderParams, // doesn't matter for this test + true, + 1.0, // every site mutates + DistributionType::GAMMA, mutationParams, + isDiploid ? 2 : 1 + ); + + // Create individual trait object + GeneticFitnessTrait traitInd(spTr); // initialisation constructor + traitInd.mutate(); + for (int i = 0; i < genomeSz; i++) { + float valAllele = traitInd.getAlleleValueAtLocus(0, i); + assert(valAllele <= 1.0); + } + } - SpeciesTrait* spTr = new SpeciesTrait( - TraitType::GENETIC_LOAD1, - sex_t::NA, - createTestGenePositions(genomeSz), - ExpressionType::MULTIPLICATIVE, - DistributionType::NONE, placeholderParams, // not used for genetic load - DistributionType::GAMMA, placeholderParams, // doesn't matter for this test - true, - 1.0, // every site mutates - DistributionType::GAMMA, mutationParams, - isDiploid ? 2 : 1 - ); + { + // 1/2 chance to sample a mutation < -1 + const float normalMutMeanParam = 0; + const float normalMutSdParam = 1.0; - // Create individual trait object - GeneticFitnessTrait traitInd(spTr); // initialisation constructor - traitInd.mutate(); - for (int i = 0; i < genomeSz; i++) { - float valAllele = traitInd.getAlleleValueAtLocus(0, i); - assert(valAllele <= 1.0); + const int genomeSz = 10; + const bool isDiploid{ false }; + + // Create species trait + const map mutationParams{ + // all alleles initialised at a single value + pair{GenParamType::MEAN, normalMutMeanParam}, + pair{GenParamType::SD, normalMutSdParam} + }; + const map placeholderParams = mutationParams; + + SpeciesTrait* spTr = new SpeciesTrait( + TraitType::GENETIC_LOAD1, + sex_t::NA, + createTestGenePositions(genomeSz), + ExpressionType::MULTIPLICATIVE, + DistributionType::NONE, placeholderParams, // not used for genetic load + DistributionType::NORMAL, placeholderParams, // doesn't matter for this test + true, + 1.0, // every site mutates + DistributionType::NORMAL, mutationParams, + isDiploid ? 2 : 1 + ); + + // Create individual trait object + GeneticFitnessTrait traitInd(spTr); // initialisation constructor + traitInd.mutate(); + for (int i = 0; i < genomeSz; i++) { + float valAllele = traitInd.getAlleleValueAtLocus(0, i); + assert(valAllele > -1.0); + } } } + } bool haveSameEmigD0Allele(const Individual& indA, const Individual& indB, const int& position, short whichHaplo = 0) { From c6f5e29f86f02431f074e18bb7614a78f94ad568 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 15 Jul 2024 13:43:15 +0100 Subject: [PATCH 189/332] test for #33 complete --- DispersalTrait.h | 4 ++-- GeneticFitnessTrait.cpp | 10 +++++++++- GeneticFitnessTrait.h | 1 + NeutralStatsManager.cpp | 2 +- unit_tests/testIndividual.cpp | 15 ++++++++++++--- 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/DispersalTrait.h b/DispersalTrait.h index 0c3a7e6..3f9815c 100644 --- a/DispersalTrait.h +++ b/DispersalTrait.h @@ -101,8 +101,8 @@ map>> createTestGenotype( const int genomeSz, const bool isDiploid, const float valAlleleA, const float valAlleleB = -99.9, // allow no value for haploids - const float domCoeffA = 0.0, // default for dispersal traits - const float domCoeffB = 0.0 + const float domCoeffA = 1.0, // default for dispersal traits + const float domCoeffB = 1.0 ); #endif //RSDEBUG diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index 62346e1..533a0ba 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -426,7 +426,15 @@ float GeneticFitnessTrait::getAlleleValueAtLocus(short whichChromosome, int posi int GeneticFitnessTrait::getAlleleIDAtLocus(short whichChromosome, int position) const { auto it = genes.find(position); if (it == genes.end()) - throw runtime_error("The Dispersal locus queried for its allele value does not exist."); + throw runtime_error("The Dispersal locus queried for its allele ID does not exist."); return it->second[whichChromosome].get()->getId(); } + +float GeneticFitnessTrait::getDomCoefAtLocus(short whichChromosome, int position) const { + auto it = genes.find(position); + if (it == genes.end()) + throw runtime_error("The genetic load locus queried for its dominance coefficient does not exist."); + return it->second[whichChromosome] == 0 ? wildType->getDominanceCoef() : it->second[whichChromosome]->getDominanceCoef(); +} + #endif // RSDEBUG \ No newline at end of file diff --git a/GeneticFitnessTrait.h b/GeneticFitnessTrait.h index 02a87ad..8bd60ac 100644 --- a/GeneticFitnessTrait.h +++ b/GeneticFitnessTrait.h @@ -50,6 +50,7 @@ class GeneticFitnessTrait : public QuantitativeTrait { virtual bool isHeterozygoteAtLocus(int locus) const override; #if RSDEBUG // for testing only int getAlleleIDAtLocus(short whichChromosome, int position) const; + float getDomCoefAtLocus(short chromosome, int position) const; #endif private: diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index aea43de..0e8537c 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -529,7 +529,7 @@ void NeutralStatsManager::calcPerLocusMeanSquaresFst(set const& patchList, // ---------------------------------------------------------------------------------------- // Patch pairwise Fst // Computes the weighted within and between patch Fst's as well as the overall Fst (Theta). -// The method used here is that of Weir& Hill 2002, Ann.Rev.Genet. 36:721 - 750. +// The method used here is that of Weir & Hill 2002, Ann.Rev.Genet. 36:721 - 750. // The weighting is done for samples(patches) of unequal sizes. // ---------------------------------------------------------------------------------------- void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape) { diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 4ced6fd..88ea1b1 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -570,21 +570,28 @@ void testGenetics() { } // Genetic fitness mutations are constrained between -1 or 1 + // + sampled dominance coefficients are always positive { { // Most likely (~96%) to sample a mutation > 1 const float gammaMutShapeParam = 5.0; const float gammaMutScaleParam = 1.0; + // Normal centered on 0 : ~50% of sampling negative dominance coefficient + const float dominanceMeanParam = 0.0; + const float dominanceSdParam = 1.0; const int genomeSz = 5; const bool isDiploid{ false }; // Create species trait const map mutationParams{ - // all alleles initialised at a single value pair{GenParamType::SHAPE, gammaMutShapeParam}, pair{GenParamType::SCALE, gammaMutScaleParam} }; + const map dominanceParams{ + pair{GenParamType::MEAN, dominanceMeanParam}, + pair{GenParamType::SD, dominanceSdParam} + }; const map placeholderParams = mutationParams; SpeciesTrait* spTr = new SpeciesTrait( @@ -593,7 +600,7 @@ void testGenetics() { createTestGenePositions(genomeSz), ExpressionType::MULTIPLICATIVE, DistributionType::NONE, placeholderParams, // not used for genetic load - DistributionType::GAMMA, placeholderParams, // doesn't matter for this test + DistributionType::NORMAL, dominanceParams, true, 1.0, // every site mutates DistributionType::GAMMA, mutationParams, @@ -606,6 +613,8 @@ void testGenetics() { for (int i = 0; i < genomeSz; i++) { float valAllele = traitInd.getAlleleValueAtLocus(0, i); assert(valAllele <= 1.0); + float domCoef = traitInd.getDomCoefAtLocus(0, i); + assert(domCoef >= 0.0); } } @@ -997,7 +1006,7 @@ void testIndividual() { assert(!ind.isViable()); } - + } #endif //RSDEBUG \ No newline at end of file From c11b3c1af95fd0e59d913702e8a6a65c2f353ef5 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Tue, 16 Jul 2024 07:50:03 +0200 Subject: [PATCH 190/332] try to fix check error (Rcpp.h should only be included for the R-pkg) --- Genome.h | 2 ++ Management.h | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Genome.h b/Genome.h index 79b163d..1b4c188 100644 --- a/Genome.h +++ b/Genome.h @@ -24,7 +24,9 @@ #include #include +#if RS_RCPP #include +#endif #include "Parameters.h" #include "Species.h" diff --git a/Management.h b/Management.h index 5148ade..2763f95 100644 --- a/Management.h +++ b/Management.h @@ -51,8 +51,9 @@ #include #include using namespace std; - +#if RS_RCPP #include // for Rcpp::Rcout +#endif #include "Parameters.h" #include "Species.h" #include "Cell.h" From 4a05004173541267970562f4a3f16f46039e5340 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Tue, 16 Jul 2024 13:24:01 +0200 Subject: [PATCH 191/332] flagged rcpp output as RS_RCPP --- Management.cpp | 34 ++++++++++++++++++++++++++++++++++ Population.cpp | 13 ++++++++++--- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/Management.cpp b/Management.cpp index c0a273b..821b493 100644 --- a/Management.cpp +++ b/Management.cpp @@ -96,7 +96,9 @@ void Management::translocate(int yr , Landscape* pLandscape , Species* pSpecies ){ +#if RS_RCPP Rcpp::Rcout << "Start translocation events in year " << yr << endl; +#endif landParams ppLand = pLandscape->getLandParams(); auto it = nb.find(yr); // the number of translocation events is determined by the number of elements of the maps at year yr auto nb_it = nb.find(yr); @@ -108,36 +110,48 @@ void Management::translocate(int yr auto sex_it = sex.find(yr); // iterate over the number of events for (int e = 0; e < it->second.size(); e++) { +#if RS_RCPP Rcpp::Rcout << "Translocation event " << e << " in year " << yr << endl; +#endif // find the source patch Patch* s_patch; Population* s_pPop; if(ppLand.patchModel){ if(pLandscape->existsPatch(source_it->second[e].x)){ +#if RS_RCPP Rcpp::Rcout << "Source patch exist." << endl; +#endif s_patch = pLandscape->findPatch(source_it->second[e].x); if (s_patch != 0) { // test if population in patch is not zero s_pPop = (Population*)s_patch->getPopn((intptr)pSpecies); // returns the population of the species in that cell if (s_pPop != 0 && s_pPop->getNInds() > 0){ } else { +#if RS_RCPP Rcpp::Rcout << "Population does not exist in source patch or is 0! skipping translocation event." << endl; +#endif return; } } else { +#if RS_RCPP Rcpp::Rcout << "Source patch was found but NULL! skipping translocation event." << endl; // not sure if this ever happens +#endif return; } // } else{ +#if RS_RCPP Rcpp::Rcout << "Source patch was not found in landscape! skipping translocation event." << endl; +#endif return; } } else{ Cell* pCell; pCell = pLandscape->findCell(source_it->second[e].x, source_it->second[e].y); if (pCell != 0) { +#if RS_RCPP Rcpp::Rcout << "Source cell was found" << endl; +#endif intptr s_ppatch = pCell->getPatch(); if (s_ppatch != 0) { s_patch = (Patch*)s_ppatch; @@ -145,15 +159,21 @@ void Management::translocate(int yr s_pPop = (Population*)s_patch->getPopn((intptr)pSpecies); // returns the population of the species in that cell if (s_pPop != 0 && s_pPop->getNInds() > 0){ } else { +#if RS_RCPP Rcpp::Rcout << "Population does not exist in source cell or is 0! skipping translocation event." << endl; +#endif return; } } else { +#if RS_RCPP Rcpp::Rcout << "Source cell does not exist! skipping translocation event." << endl; +#endif return; } } else { +#if RS_RCPP Rcpp::Rcout << "Cell does not belong to landscape! skipping translocation event." << endl; +#endif return; } } @@ -162,26 +182,36 @@ void Management::translocate(int yr Population* t_pPop; if(ppLand.patchModel){ if(pLandscape->existsPatch(target_it->second[e].x)){ +#if RS_RCPP Rcpp::Rcout << "Target patch exist." << endl; +#endif t_patch = pLandscape->findPatch(target_it->second[e].x); } else{ +#if RS_RCPP Rcpp::Rcout << "Target patch was not found in landscape! skipping translocation event." << endl; +#endif return; } } else{ Cell* pCell; pCell = pLandscape->findCell(target_it->second[e].x, target_it->second[e].y); if (pCell != 0) { +#if RS_RCPP Rcpp::Rcout << "Target cell was found" << endl; +#endif intptr t_ppatch = pCell->getPatch(); if (t_ppatch != 0) { t_patch = (Patch*)t_ppatch; } else { +#if RS_RCPP Rcpp::Rcout << "Target cell does not exist! skipping translocation event." << endl; +#endif return; } } else { +#if RS_RCPP Rcpp::Rcout << "Target cell does not belong to landscape! skipping translocation event." << endl; +#endif return; } } @@ -209,7 +239,9 @@ void Management::translocate(int yr // Check if a population of this species already exists in target patch t_patch t_pPop = (Population*)t_patch->getPopn((intptr)pSpecies); if (t_pPop == 0) { // translocated individual is the first in a previously uninhabited patch +#if RS_RCPP Rcpp::Rcout << "Population does not exist in target patch. Creating new population." << endl; +#endif // create a new population in the corresponding sub-community SubCommunity* pSubComm = (SubCommunity*)t_patch->getSubComm(); t_pPop = pSubComm->newPopn(pLandscape, pSpecies, t_patch, 0); @@ -232,7 +264,9 @@ void Management::translocate(int yr } } } +#if RS_RCPP Rcpp::Rcout << "Successfully translocated " << translocated << " out of " << nb_it->second[e] << " individuals in translocation event " << e <<"." << endl; +#endif // remove pointers to sampled individuals s_pPop->clean(); } diff --git a/Population.cpp b/Population.cpp index 4c6f524..abf48b8 100644 --- a/Population.cpp +++ b/Population.cpp @@ -552,7 +552,9 @@ void Population::reproduction(const float localK, const float envval, const int inds[i]->resetFallow(); // NOTE: FOR COMPLEX SEXUAL MODEL, NO. OF FEMALES *ACTUALLY* BREEDING DOES NOT // NECESSARILY EQUAL THE EXPECTED NO. FROM EQN. 7 IN THE MANUAL... +#if RS_RCPP if(propBreed > 1) Rcpp::Rcout << "propBreed: " << propBreed << std::endl; +#endif if (pRandom->Bernoulli(propBreed)) { expected = fec[stage][0]; // breeds } @@ -1684,8 +1686,9 @@ std::vector Population::getIndsWithCharacteristics( // Select a se // get all suitable individuals based on settings std::vector filteredInds; int ninds = (int)inds.size(); +#if RS_RCPP Rcpp::Rcout << "Number individuals in cell: " << ninds << endl; - +#endif if (ninds > 0) { // copy ALL individuals to filteredInds for (int i = 0; i < ninds; i++) { @@ -1737,7 +1740,9 @@ std::vector Population::getIndsWithCharacteristics( // Select a se } } } else { +#if RS_RCPP Rcpp::Rcout << "No individuals in source patch" << endl; +#endif return filteredInds; } int nfiltered = 0; @@ -1775,9 +1780,9 @@ int Population::sampleIndividuals( // Select a set of individuals with specified // get individuals with the characteristics std::vector filtered; filtered = getIndsWithCharacteristics(min_age, max_age, stage, sex); - +#if RS_RCPP Rcpp::Rcout << "Number of individuals with fitting characteristics: " << filtered.size() << endl; - +#endif if (filtered.size() <= nb) // Sample all individuals in selected stages sampledInds = filtered; @@ -1808,7 +1813,9 @@ Individual* Population::catchIndividual( // Translocate a set of individuals wit // If individual is part of the sampledInds vector: if (std::find(sampledInds.begin(), sampledInds.end(), inds[j]) != std::end(sampledInds)){ // try to catch individual +#if RS_RCPP if(catching_rate > 1) Rcpp::Rcout << "Catching rate: " << catching_rate << std::endl; +#endif if (pRandom->Bernoulli(catching_rate)){ indStats indstat = inds[j]->getStats(); catched = inds[j]; From 2745571166bff9a11d0fdbd0449f80eb2757df7c Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Tue, 16 Jul 2024 13:27:10 +0200 Subject: [PATCH 192/332] added Management.cpp to CMakeLists.txt --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c14a3e3..85cca2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,9 +7,9 @@ if (NOT batchmode) # that is, RScore as a standalone # specify the C++ standard set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) - add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp Utils.cpp) + add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp Utils.cpp Management.cpp) else() # that is, RScore compiled as library within RangeShifter_batch - add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp Utils.cpp) + add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp Utils.cpp Management.cpp) endif() # pass config definitions to compiler From 3fd9def1c6d6100b257e15e581a81902cd2260e2 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Tue, 16 Jul 2024 13:34:39 +0200 Subject: [PATCH 193/332] shifted Manamgent.cpp to before Model.cpp in CMakeLists.txt --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 85cca2e..d305b15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,9 +7,9 @@ if (NOT batchmode) # that is, RScore as a standalone # specify the C++ standard set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) - add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp Utils.cpp Management.cpp) + add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Management.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp Utils.cpp) else() # that is, RScore compiled as library within RangeShifter_batch - add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp Utils.cpp Management.cpp) + add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Management.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp Utils.cpp) endif() # pass config definitions to compiler From 0343164051eebd2a4f74f2a2333a37b5fa564a76 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Tue, 16 Jul 2024 13:44:19 +0200 Subject: [PATCH 194/332] adapted Main.cpp --- Main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Main.cpp b/Main.cpp index 0d15cdb..d9c5a32 100644 --- a/Main.cpp +++ b/Main.cpp @@ -37,6 +37,7 @@ #include "Landscape.h" #include "Species.h" #include "SubCommunity.h" +#include "Management.h" using namespace std; @@ -56,6 +57,7 @@ paramStoch* paramsStoch; paramInit* paramsInit; paramSim* paramsSim; RSrandom* pRandom; +Management* pManagement; // pointer to management routines ofstream DEBUGLOG; ofstream MUTNLOG; vector hfnames; From 2f791f0e7f4453d64ce374494958e36245e960d7 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 16 Jul 2024 17:11:51 +0100 Subject: [PATCH 195/332] fixed bug - missing sex and density-dependence in expression of settlement traits --- Individual.cpp | 35 ++++++++++++++++++++++++++--------- Individual.h | 2 +- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index a4579e4..8e109ee 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -227,6 +227,7 @@ void Individual::setDispersalPhenotypes(Species* pSpecies, int resol) { const emigRules emig = pSpecies->getEmigRules(); const transferRules trfr = pSpecies->getTransferRules(); const settleType sett = pSpecies->getSettle(); + const settleRules settRules = pSpecies->getSettRules(stage, sex); // record phenotypic traits if (emig.indVar) @@ -234,7 +235,7 @@ void Individual::setDispersalPhenotypes(Species* pSpecies, int resol) { if (trfr.indVar) this->setTransferTraits(pSpecies, trfr, resol); if (sett.indVar) - this->setSettlementTraits(pSpecies, sett.sexDep); + this->setSettlementTraits(pSpecies, sett.sexDep, settRules.densDep); } void Individual::setTransferTraits(Species* pSpecies, transferRules trfr, int resol) { @@ -249,18 +250,34 @@ void Individual::setTransferTraits(Species* pSpecies, transferRules trfr, int re setIndKernelTraits(pSpecies, trfr.sexDep, trfr.twinKern, resol); } -void Individual::setSettlementTraits(Species* pSpecies, bool sexDep) { +void Individual::setSettlementTraits(Species* pSpecies, bool sexDep, bool densDep) { settleTraits s; s.s0 = s.alpha = s.beta = 0.0; - if (sexDep && this->getSex() == MAL) { - s.s0 = getTrait(S_S0_M)->express(); - s.alpha = getTrait(S_ALPHA_M)->express(); - s.beta = getTrait(S_BETA_M)->express(); + if (sexDep) { + if (this->getSex() == MAL) { + s.s0 = getTrait(S_S0_M)->express(); + if (densDep) { + s.alpha = getTrait(S_ALPHA_M)->express(); + s.beta = getTrait(S_BETA_M)->express(); + } + } + else if (this->getSex() == FEM) { + s.s0 = getTrait(S_S0_F)->express(); + if (densDep) { + s.alpha = getTrait(S_ALPHA_F)->express(); + s.beta = getTrait(S_BETA_F)->express(); + } + } + else { + throw runtime_error("Attempt to express invalid emigration trait sex."); + } } else { - s.s0 = getTrait(S_S0_F)->express(); - s.alpha = getTrait(S_ALPHA_F)->express(); - s.beta = getTrait(S_BETA_F)->express(); + s.s0 = getTrait(S_S0)->express(); + if (densDep) { + s.alpha = getTrait(S_ALPHA)->express(); + s.beta = getTrait(S_BETA)->express(); + } } pSettleTraits = make_unique(); diff --git a/Individual.h b/Individual.h index d5072aa..de143b9 100644 --- a/Individual.h +++ b/Individual.h @@ -252,7 +252,7 @@ class Individual { trfrCRWTraits getIndCRWTraits(void); // Get phenotypic transfer by CRW traits - void setSettlementTraits(Species* pSpecies, bool sexDep); + void setSettlementTraits(Species* pSpecies, bool sexDep, bool densDep); settleTraits getIndSettTraits(void); // Get phenotypic settlement traits From 3f5f47bb5f4145cf5b7561170ee5b70c4b3caf5c Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 16 Jul 2024 18:32:46 +0100 Subject: [PATCH 196/332] test for #34, phew that was big one --- unit_tests/testIndividual.cpp | 314 +++++++++++++++++++++++++++++++++- 1 file changed, 313 insertions(+), 1 deletion(-) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 88ea1b1..eb86ed8 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -656,7 +656,6 @@ void testGenetics() { } } } - } bool haveSameEmigD0Allele(const Individual& indA, const Individual& indB, const int& position, short whichHaplo = 0) { @@ -1006,6 +1005,319 @@ void testIndividual() { assert(!ind.isViable()); } + // Dispersal trait alleles can take any value, but + // phenotypes are constrained to valid values + { + // Case 1 - Settlement + Kernel-based transfer + { + const int genomeSz = 4; + + const bool isDiploid{ true }; // haploid, simpler check + const float mutationRate = 0.0; // no mutations + + Patch* pPatch = new Patch(0, 0); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + + // Genome-level settings + Species* pSpecies = new Species(); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // one chromosome + genomeSz, + 0.0, // no recombination + set{}, "none", set{}, 0 // no output so no sampling + ); + + settleType sett; + sett.indVar = true; + sett.sexDep = false; + sett.stgDep = false; + pSpecies->setSettle(sett); + settleRules settRules; + settRules.densDep = true; + pSpecies->setSettRules(0, 0, settRules); + + transferRules trfr; + trfr.indVar = true; + trfr.usesMovtProc = false; + trfr.moveType = 0; // kernels + trfr.twinKern = false; + trfr.sexDep = false; + trfr.stgDep = false; + pSpecies->setTrfrRules(trfr); + + // Species-level traits + const map distParams{ + // prameters don't matter, allele values are overwritten below + pair{GenParamType::MIN, 1.0}, + pair{GenParamType::MAX, 1.0} + }; + SpeciesTrait* trSettProb = new SpeciesTrait( + TraitType::S_S0, + sex_t::NA, + set{ 0 }, + ExpressionType::AVERAGE, + DistributionType::UNIFORM, distParams, + DistributionType::NONE, distParams, // no dominance, params are ignored + true, // isInherited + mutationRate, // does not mutate + DistributionType::UNIFORM, distParams, // not used + isDiploid ? 2 : 1 + ); + SpeciesTrait* trSettAlpha = new SpeciesTrait( + TraitType::S_ALPHA, + sex_t::NA, + set{ 1 }, + ExpressionType::AVERAGE, + DistributionType::UNIFORM, distParams, + DistributionType::NONE, distParams, // no dominance, params are ignored + true, // isInherited + mutationRate, // does not mutate + DistributionType::UNIFORM, distParams, // not used + isDiploid ? 2 : 1 + ); + SpeciesTrait* trSettBeta = new SpeciesTrait( + TraitType::S_BETA, + sex_t::NA, + set{ 2 }, + ExpressionType::AVERAGE, + DistributionType::UNIFORM, distParams, + DistributionType::NONE, distParams, // no dominance, params are ignored + true, // isInherited + mutationRate, // does not mutate + DistributionType::UNIFORM, distParams, // not used + isDiploid ? 2 : 1 + ); + SpeciesTrait* trMeanKern = new SpeciesTrait( + TraitType::KERNEL_MEANDIST_1, + sex_t::NA, + set{ 3 }, + ExpressionType::ADDITIVE, + DistributionType::UNIFORM, distParams, + DistributionType::NONE, distParams, // no dominance, params are ignored + true, // isInherited + mutationRate, // does not mutate + DistributionType::UNIFORM, distParams, // not used + isDiploid ? 2 : 1 + ); + + pSpecies->addTrait(TraitType::S_S0, *trSettProb); + pSpecies->addTrait(TraitType::S_ALPHA, *trSettAlpha); + pSpecies->addTrait(TraitType::S_BETA, *trSettBeta); + pSpecies->addTrait(TraitType::KERNEL_MEANDIST_1, *trMeanKern); + + Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + ind.setUpGenes(pSpecies, 1.0); + + // Overwrite genotypes with alleles resulting in invalid phenotypes + auto sProbGenotype = createTestGenotype(genomeSz, true, 1.1, 1.2); + auto sAlphaGenotype = createTestGenotype(genomeSz, true, -1.5, -0.5); + auto kernelDistGenotype = createTestGenotype(genomeSz, true, -0.2, -0.4); + ind.overrideGenotype(S_S0, sProbGenotype); + ind.overrideGenotype(S_ALPHA, sAlphaGenotype); + ind.overrideGenotype(KERNEL_MEANDIST_1, kernelDistGenotype); + // any value is valid for settlement beta + + ind.triggerMutations(pSpecies); // no mutations, but trigger expression + + settleTraits settTr = ind.getIndSettTraits(); + assert(settTr.s0 <= 1.0); + assert(settTr.alpha > 0.0); + kernelData trfrTr = *(static_cast(ind.getTrfrData())); + assert(trfrTr.meanDist1 >= 0.0); + } + + // Case 2 - Correlated random walk transfer + { + const int genomeSz = 2; + + const bool isDiploid{ true }; // haploid, simpler check + const float mutationRate = 0.0; // no mutations + + Patch* pPatch = new Patch(0, 0); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + + // Genome-level settings + Species* pSpecies = new Species(); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // one chromosome + genomeSz, + 0.0, // no recombination + set{}, "none", set{}, 0 // no output so no sampling + ); + + settleType sett; + sett.indVar = false; + pSpecies->setSettle(sett); + + transferRules trfr; + trfr.indVar = true; + trfr.usesMovtProc = true; + trfr.moveType = 2; // CRW + pSpecies->setTrfrRules(trfr); + + // Species-level traits + const map distParams{ + // prameters don't matter, allele values are overwritten below + pair{GenParamType::MIN, 1.0}, + pair{GenParamType::MAX, 1.0} + }; + SpeciesTrait* trCRWLen = new SpeciesTrait( + TraitType::CRW_STEPLENGTH, + sex_t::NA, + set{ 0 }, + ExpressionType::ADDITIVE, + DistributionType::UNIFORM, distParams, + DistributionType::NONE, distParams, // no dominance, params are ignored + true, // isInherited + mutationRate, // does not mutate + DistributionType::UNIFORM, distParams, // not used + isDiploid ? 2 : 1 + ); + SpeciesTrait* trCRWCorr = new SpeciesTrait( + TraitType::CRW_STEPCORRELATION, + sex_t::NA, + set{ 1 }, + ExpressionType::AVERAGE, + DistributionType::UNIFORM, distParams, + DistributionType::NONE, distParams, // no dominance, params are ignored + true, // isInherited + mutationRate, // does not mutate + DistributionType::UNIFORM, distParams, // not used + isDiploid ? 2 : 1 + ); + + pSpecies->addTrait(TraitType::CRW_STEPLENGTH, *trCRWLen); + pSpecies->addTrait(TraitType::CRW_STEPCORRELATION, *trCRWCorr); + + bool usesMovtProcess = true; + short whichMovtProcess = 2; // CRW + Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, usesMovtProcess, whichMovtProcess); + ind.setUpGenes(pSpecies, 1.0); + + // Overwrite genotypes with alleles resulting in invalid phenotypes + auto crwLenGenotype = createTestGenotype(genomeSz, true, -1.1, -1.2); + auto crwCorrGenoType = createTestGenotype(genomeSz, true, 1.5, 2.0); + ind.overrideGenotype(CRW_STEPLENGTH, crwLenGenotype); + ind.overrideGenotype(CRW_STEPCORRELATION, crwCorrGenoType); + + ind.triggerMutations(pSpecies); // no mutations, but trigger expression + + crwData trfrTr = *(static_cast(ind.getTrfrData())); + assert(trfrTr.stepLength >= 0.0); + assert(trfrTr.rho <= 1.0); + } + + // Case 3 - Transfer with Sotchastic Movement Simulator + { + const int genomeSz = 2; + + const bool isDiploid{ true }; // haploid, simpler check + const float mutationRate = 0.0; // no mutations + + Patch* pPatch = new Patch(0, 0); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + + // Genome-level settings + Species* pSpecies = new Species(); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // one chromosome + genomeSz, + 0.0, // no recombination + set{}, "none", set{}, 0 // no output so no sampling + ); + + settleType sett; + sett.indVar = false; + pSpecies->setSettle(sett); + + transferRules trfr; + trfr.indVar = true; + trfr.usesMovtProc = true; + trfr.moveType = 1; // SMS + pSpecies->setTrfrRules(trfr); + + // Species-level traits + const map distParams{ + // prameters don't matter, allele values are overwritten below + pair{GenParamType::MIN, 1.0}, + pair{GenParamType::MAX, 1.0} + }; + SpeciesTrait* trSmsDirPers = new SpeciesTrait( + TraitType::SMS_DP, + sex_t::NA, + set{ 0 }, + ExpressionType::ADDITIVE, + DistributionType::UNIFORM, distParams, + DistributionType::NONE, distParams, // no dominance, params are ignored + true, // isInherited + mutationRate, // does not mutate + DistributionType::UNIFORM, distParams, // not used + isDiploid ? 2 : 1 + ); + SpeciesTrait* trSmsGoalBias = new SpeciesTrait( + TraitType::SMS_GB, + sex_t::NA, + set{ 1 }, + ExpressionType::AVERAGE, + DistributionType::UNIFORM, distParams, + DistributionType::NONE, distParams, // no dominance, params are ignored + true, // isInherited + mutationRate, // does not mutate + DistributionType::UNIFORM, distParams, // not used + isDiploid ? 2 : 1 + ); + SpeciesTrait* trSmsAlpha = new SpeciesTrait( + TraitType::SMS_ALPHADB, + sex_t::NA, + set{ 0 }, + ExpressionType::ADDITIVE, + DistributionType::UNIFORM, distParams, + DistributionType::NONE, distParams, // no dominance, params are ignored + true, // isInherited + mutationRate, // does not mutate + DistributionType::UNIFORM, distParams, // not used + isDiploid ? 2 : 1 + ); + SpeciesTrait* trSmsBeta = new SpeciesTrait( + TraitType::SMS_BETADB, + sex_t::NA, + set{ 1 }, + ExpressionType::AVERAGE, + DistributionType::UNIFORM, distParams, + DistributionType::NONE, distParams, // no dominance, params are ignored + true, // isInherited + mutationRate, // does not mutate + DistributionType::UNIFORM, distParams, // not used + isDiploid ? 2 : 1 + ); + + pSpecies->addTrait(TraitType::SMS_DP, *trSmsDirPers); + pSpecies->addTrait(TraitType::SMS_GB, *trSmsGoalBias); + pSpecies->addTrait(TraitType::SMS_ALPHADB, *trSmsAlpha); + pSpecies->addTrait(TraitType::SMS_BETADB, *trSmsBeta); + + bool usesMovtProcess = true; + short whichMovtProcess = 1; // SMS + Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, usesMovtProcess, whichMovtProcess); + ind.setUpGenes(pSpecies, 1.0); + + // Overwrite genotypes with alleles resulting in invalid phenotypes + auto smsDPGenotype = createTestGenotype(genomeSz, true, 0.1, 0.2); + auto smsGBGenotype = createTestGenotype(genomeSz, true, 0.5, 0.0); + auto smsAlphaGenotype = createTestGenotype(genomeSz, true, 0.0, 0.0); + ind.overrideGenotype(SMS_DP, smsDPGenotype); + ind.overrideGenotype(SMS_GB, smsGBGenotype); + ind.overrideGenotype(SMS_ALPHADB, smsAlphaGenotype); + // any value is valid for SMS beta + + ind.triggerMutations(pSpecies); // no mutations, but trigger expression + + smsData trfrTr = *(static_cast(ind.getTrfrData())); + assert(trfrTr.dp >= 1.0); + assert(trfrTr.gb >= 1.0); + assert(trfrTr.alphaDB > 0.0); + } + } } From f6c2a5b5b883decdbd69353966c7f1c4ea76ea4a Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Wed, 17 Jul 2024 14:29:45 +0200 Subject: [PATCH 197/332] updated Cell.cpp now up-to-date with new_genetics branch (RS_DEBUG flags removed + some formatting) --- Cell.cpp | 194 ++++++++++++++++++++++++------------------------------- 1 file changed, 85 insertions(+), 109 deletions(-) diff --git a/Cell.cpp b/Cell.cpp index 1c0f937..62dfe90 100644 --- a/Cell.cpp +++ b/Cell.cpp @@ -1,25 +1,25 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter 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 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - + + //--------------------------------------------------------------------------- #include "Cell.h" @@ -32,99 +32,75 @@ Cell::Cell(int xx,int yy,intptr patch,int hab) { -x = xx; y = yy; -pPatch = patch; -envVal = 1.0; // default - no effect of any gradient -envDev = eps = 0.0; -habIxx.push_back(hab); -#if RSDEBUG -//DebugGUI(("Cell::Cell(): this=" + Int2Str((int)this) -// + " x=" + Int2Str(x) + " y=" + Int2Str(y) -// + " habIndex=" + Int2Str(habIndex) -//).c_str()); -#endif -visits = 0; -smsData = 0; + x = xx; y = yy; + pPatch = patch; + envVal = 1.0; // default - no effect of any gradient + envDev = eps = 0.0; + habIxx.push_back(hab); + visits = 0; + smsData = 0; } Cell::Cell(int xx,int yy,intptr patch,float hab) { -x = xx; y = yy; -pPatch = patch; -envVal = 1.0; // default - no effect of any gradient -envDev = eps = 0.0; -habitats.push_back(hab); -visits = 0; -smsData = 0; + x = xx; y = yy; + pPatch = patch; + envVal = 1.0; // default - no effect of any gradient + envDev = eps = 0.0; + habitats.push_back(hab); + visits = 0; + smsData = 0; } Cell::~Cell() { -#if RSDEBUG -//DEBUGLOG << "Cell::~Cell(): this = " << this << " smsData = " << smsData << endl; -#endif -habIxx.clear(); -habitats.clear(); -if (smsData != 0) { - if (smsData->effcosts != 0) delete smsData->effcosts; - delete smsData; -} -#if RSDEBUG -//DEBUGLOG << "Cell::~Cell(): deleted" << endl; -#endif + habIxx.clear(); + habitats.clear(); + if (smsData != 0) { + if (smsData->effcosts != 0) delete smsData->effcosts; + delete smsData; + } } void Cell::setHabIndex(short hx) { -#if RSDEBUG -//DebugGUI(("Cell::setHabIndex(): this=" + Int2Str((int)this) -// + " x=" + Int2Str(x) + " y=" + Int2Str(y) -// + " habIx=" + Int2Str(habIx) -//).c_str()); -#endif -if (hx < 0) habIxx.push_back(0); -else habIxx.push_back(hx); + if (hx < 0) habIxx.push_back(0); + else habIxx.push_back(hx); } void Cell::changeHabIndex(short ix,short hx) { -if (ix >= 0 && ix < (short)habIxx.size() && hx >= 0) habIxx[ix] = hx; -else habIxx[ix] = 0; + if (ix >= 0 && ix < (short)habIxx.size() && hx >= 0) habIxx[ix] = hx; + else habIxx[ix] = 0; } int Cell::getHabIndex(int ix) { -if (ix < 0 || ix >= (int)habIxx.size()) - // nodata cell OR should not occur, but treat as such - return -1; -else return habIxx[ix]; + if (ix < 0 || ix >= (int)habIxx.size()) + // nodata cell OR should not occur, but treat as such + return -1; + else return habIxx[ix]; } int Cell::nHabitats(void) { -int nh = (int)habIxx.size(); -if ((int)habitats.size() > nh) nh = (int)habitats.size(); -return nh; + int nh = (int)habIxx.size(); + if ((int)habitats.size() > nh) nh = (int)habitats.size(); + return nh; } void Cell::setHabitat(float q) { -if (q >= 0.0 && q <= 100.0) habitats.push_back(q); -else habitats.push_back(0.0); + if (q >= 0.0 && q <= 100.0) habitats.push_back(q); + else habitats.push_back(0.0); } float Cell::getHabitat(int ix) { -if (ix < 0 || ix >= (int)habitats.size()) - // nodata cell OR should not occur, but treat as such - return -1.0; -else return habitats[ix]; + if (ix < 0 || ix >= (int)habitats.size()) + // nodata cell OR should not occur, but treat as such + return -1.0; + else return habitats[ix]; } void Cell::setPatch(intptr p) { -pPatch = p; + pPatch = p; } intptr Cell::getPatch(void) { -#if RSDEBUG -//DebugGUI(("Cell::getPatch(): this=" + Int2Str((int)this) -// + " x=" + Int2Str(x) + " y=" + Int2Str(y) -// + " habIxx[0]=" + Int2Str(habIxx[0]) + " pPatch=" + Int2Str(pPatch) -//).c_str()); -#endif -return pPatch; + return pPatch; } locn Cell::getLocn(void) { locn q; q.x = x; q.y = y; return q; } @@ -134,13 +110,13 @@ void Cell::setEnvDev(float d) { envDev = d; } float Cell::getEnvDev(void) { return envDev; } void Cell::setEnvVal(float e) { -if (e >= 0.0) envVal = e; + if (e >= 0.0) envVal = e; } float Cell::getEnvVal(void) { return envVal; } void Cell::updateEps(float ac,float randpart) { -eps = eps*ac + randpart; + eps = eps*ac + randpart; } float Cell::getEps(void) { return eps; } @@ -148,53 +124,53 @@ float Cell::getEps(void) { return eps; } // Functions to handle costs for SMS int Cell::getCost(void) { -int c; -if (smsData == 0) c = 0; // costs not yet set up -else c = smsData->cost; -return c; + int c; + if (smsData == 0) c = 0; // costs not yet set up + else c = smsData->cost; + return c; } void Cell::setCost(int c) { -if (smsData == 0) { - smsData = new smscosts; - smsData->effcosts = 0; -} -smsData->cost = c; + if (smsData == 0) { + smsData = new smscosts; + smsData->effcosts = 0; + } + smsData->cost = c; } // Reset the cost and the effective cost of the cell void Cell::resetCost(void) { -if (smsData != 0) { resetEffCosts(); delete smsData; } -smsData = 0; + if (smsData != 0) { resetEffCosts(); delete smsData; } + smsData = 0; } array3x3f Cell::getEffCosts(void) { -array3x3f a; -if (smsData == 0 || smsData->effcosts == 0) { // effective costs have not been calculated - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - a.cell[i][j] = -1.0; - } - } -} -else - a = *smsData->effcosts; -return a; + array3x3f a; + if (smsData == 0 || smsData->effcosts == 0) { // effective costs have not been calculated + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + a.cell[i][j] = -1.0; + } + } + } + else + a = *smsData->effcosts; + return a; } -void Cell::setEffCosts(array3x3f a) { -if (smsData->effcosts == 0) smsData->effcosts = new array3x3f; -*smsData->effcosts = a; +void Cell::setEffCosts(array3x3f a) { + if (smsData->effcosts == 0) smsData->effcosts = new array3x3f; + *smsData->effcosts = a; } // Reset the effective cost, but not the cost, of the cell void Cell::resetEffCosts(void) { -if (smsData != 0) { - if (smsData->effcosts != 0) { - delete smsData->effcosts; - smsData->effcosts = 0; - } -} + if (smsData != 0) { + if (smsData->effcosts != 0) { + delete smsData->effcosts; + smsData->effcosts = 0; + } + } } void Cell::resetVisits(void) { visits = 0; } @@ -206,7 +182,7 @@ unsigned long int Cell::getVisits(void) { return visits; } // Initial species distribution cell functions DistCell::DistCell(int xx,int yy) { -x = xx; y = yy; initialise = false; + x = xx; y = yy; initialise = false; } DistCell::~DistCell() { @@ -214,12 +190,12 @@ DistCell::~DistCell() { } void DistCell::setCell(bool init) { -initialise = init; + initialise = init; } bool DistCell::toInitialise(locn loc) { -if (loc.x == x && loc.y == y) return initialise; -else return false; + if (loc.x == x && loc.y == y) return initialise; + else return false; } bool DistCell::selected(void) { return initialise; } From 7bc206b1328b4f0345d46fbe521908582bc6c278 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 31 Jul 2024 17:07:36 +0100 Subject: [PATCH 198/332] annotation --- NeutralStatsManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 5c72d95..3e2a30b 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -596,7 +596,7 @@ void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, con sqDist = p - pBar; //(p_liu - pbar_u)^2 sqDist *= sqDist; - num = pq * popSizes[i] / (popSizes[i] - 1); + num = pq * popSizes[i] / (popSizes[i] - 1); // eq. 8 Weir & Hill 2002 numeratorPairwiseFst[i][i] += num; numeratorWeightedFst += num * popSizes[i]; // see equ. 9, Weir & Hill 2002 denominator += popSizes[i] * sqDist + popWeights[i] * pq; //common denominator From c24292f1dca534fd63a9c3383ea43d7ebcc13a51 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Thu, 1 Aug 2024 10:36:45 +0200 Subject: [PATCH 199/332] uncomment multiple declaration of sampledInd vector However, I still need to check whether there are conflicts between genetics and translocation feature using this vector to store sampled individuals --- Population.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Population.h b/Population.h index 9b7ab2a..940f86a 100644 --- a/Population.h +++ b/Population.h @@ -275,7 +275,7 @@ class Population { // has been completed vector sampledInds; - std::vector sampledInds; // individuals with specified characteristics from translocation!!! + //std::vector sampledInds; // individuals with specified characteristics from translocation!!! vector popNeutralCountTables; void resetPopNeutralTables(); }; From 0738d892130004dd6747c72d6c47a62de77d66d5 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Thu, 1 Aug 2024 10:44:47 +0200 Subject: [PATCH 200/332] removed GUI related code --- Model.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Model.cpp b/Model.cpp index 8a6ec6a..fa59625 100644 --- a/Model.cpp +++ b/Model.cpp @@ -446,12 +446,6 @@ int RunModel(Landscape* pLandscape, int seqsim) ); } - if (v.viewPop || (sim.saveMaps && yr % sim.mapInt == 0)) { - if (updateland && gen == 0) { - pLandscape->drawLandscape(rep, landIx, ppLand.landNum); - } - pComm->draw(rep, yr, gen, ppLand.landNum); - } // Output and pop. visualisation before reproduction if (v.viewPop || v.viewTraits || sim.outOccup || sim.outTraitsCells || sim.outTraitsRows || sim.saveMaps) From 3261ed0542e05f9fbbc8e5e8fcc19289e1e7a150 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 5 Aug 2024 16:56:03 +0100 Subject: [PATCH 201/332] rm debuglog clutter --- Patch.cpp | 43 +++---------------------------------------- SubCommunity.cpp | 2 +- 2 files changed, 4 insertions(+), 41 deletions(-) diff --git a/Patch.cpp b/Patch.cpp index f3f88f0..dddd7f2 100644 --- a/Patch.cpp +++ b/Patch.cpp @@ -126,7 +126,6 @@ void Patch::addCell(Cell* pCell, int x, int y) { void Patch::setCarryingCapacity(Species* pSpecies, patchLimits landlimits, float epsGlobal, short nHab, short rasterType, short landIx, bool gradK) { envStochParams env = paramsStoch->getStoch(); - //Cell *pCell; locn loc; int xsum, ysum; short hx; @@ -136,23 +135,12 @@ void Patch::setCarryingCapacity(Species* pSpecies, patchLimits landlimits, int nsuitable = 0; double mean; -#if RSDEBUG - //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum - // << " xMin=" << xMin << " yMin=" << yMin << " xMax=" << xMax << " yMax=" << yMax - // << endl; -#endif - if (xMin > landlimits.xMax || xMax < landlimits.xMin || yMin > landlimits.yMax || yMax < landlimits.yMin) { // patch lies wholely outwith current landscape limits // NB the next statement is unnecessary, as localK has been set to zero above // retained only for consistency in standard variant localK = 0.0; -#if RSDEBUG - //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum - // << " localK=" << localK - // << endl; -#endif return; } @@ -164,8 +152,6 @@ void Patch::setCarryingCapacity(Species* pSpecies, patchLimits landlimits, else envval = 1.0; // no gradient effect if (env.stoch && env.inK) { // environmental stochasticity in K if (env.local) { - // pCell = getRandomCell(); - // if (pCell != 0) envval += pCell->getEps(); envval += cells[i]->getEps(); } else { // global stochasticity @@ -200,20 +186,11 @@ void Patch::setCarryingCapacity(Species* pSpecies, patchLimits landlimits, } break; } -#if RSDEBUG - //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum - // << " i=" << i << " hx=" << hx << " q=" << q << " k=" << k << " localK=" << localK - // << endl; -#endif loc = cells[i]->getLocn(); xsum += loc.x; ysum += loc.y; } -#if RSDEBUG - //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum - // << " epsGlobal=" << epsGlobal << " localK=" << localK - // << endl; -#endif -// calculate centroid co-ordinates + + // calculate centroid co-ordinates if (ncells > 0) { mean = (double)xsum / (double)ncells; x = (int)(mean + 0.5); @@ -226,24 +203,10 @@ void Patch::setCarryingCapacity(Species* pSpecies, patchLimits landlimits, float limit; limit = pSpecies->getMinMax(0) * (float)nsuitable; if (localK < limit) localK = limit; -#if RSDEBUG - //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum - // << " limit=" << limit << " localK=" << localK - // << endl; -#endif + limit = pSpecies->getMinMax(1) * (float)nsuitable; if (localK > limit) localK = limit; -#if RSDEBUG - //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum - // << " limit=" << limit << " localK=" << localK - // << endl; -#endif } -#if RSDEBUG - //DEBUGLOG << "Patch::setCarryingCapacity(): patchNum=" << patchNum - // << " localK=" << localK - // << endl; -#endif } diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 60abb6c..8408441 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -65,7 +65,7 @@ void SubCommunity::initialise(Landscape* pLandscape, Species* pSpecies) landParams ppLand = pLandscape->getLandParams(); initParams init = paramsInit->getInit(); -// determine size of initial population + // determine size of initial population int nInds = 0; if (subCommNum == 0 // matrix patch || !initial) // not in initial region or distribution From 7389fd78fe5032b50bb871f5a5882be6930f0261 Mon Sep 17 00:00:00 2001 From: JetteReeg <47744741+JetteReeg@users.noreply.github.com> Date: Tue, 6 Aug 2024 08:41:58 +0200 Subject: [PATCH 202/332] Bugfix for issue #66 #66 fixed --- Individual.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Individual.cpp b/Individual.cpp index 28555b1..aa70414 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -38,7 +38,7 @@ Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short rep geneticFitness = 1.0; stage = stg; if (probmale <= 0.0) sex = FEM; - else sex = pRandom->Bernoulli(probmale) ? FEM : MAL; + else sex = pRandom->Bernoulli(probmale) ? MAL : FEM; age = a; status = 0; From d88eb10f3ffe3232058915c9bdb3452eb520695e Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 6 Aug 2024 11:17:38 +0100 Subject: [PATCH 203/332] gcc doesn't like NULL --- SpeciesTrait.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 6ed9c3a..726ff38 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -24,7 +24,7 @@ SpeciesTrait::SpeciesTrait( mutationRate{ mutRate } { // Initialise ploidy only once per species - if (ploidy == NULL) this->ploidy = pSpecies->isDiploid() ? 2 : 1; + if (ploidy == 0) this->ploidy = pSpecies->isDiploid() ? 2 : 1; // Check distribution parameters // Initial distribution From 463a640c923f06799a7a7149eb28d406d3eca79d Mon Sep 17 00:00:00 2001 From: JetteReeg <47744741+JetteReeg@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:07:04 +0200 Subject: [PATCH 204/332] Bugfix in setGeneticSim() outputStartGenetics was not transfered correctly (instead outputGeneticInterval was also used for outputStartGenetics) --- Parameters.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Parameters.cpp b/Parameters.cpp index 0c37dab..5806deb 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -279,7 +279,7 @@ void paramSim::setGeneticSim(string patchSamplingOption, bool outputGeneticValue this->outputWCFstat = outputWCFstat; this->outputPerLocusWCFstat = outputPerLocusWCFstat; this->outputPairwiseFst = outputPairwiseFst; - this->outputStartGenetics = outputGeneticInterval; + this->outputStartGenetics = outputStartGenetics; this->outputGeneticInterval = outputGeneticInterval; } From 6ab3ae5aa17cb2cad467770b345bb02982fcb03e Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 6 Aug 2024 15:30:31 +0100 Subject: [PATCH 205/332] fix issue with neutral stats assuming less neutral alleles than actually exist --- Community.cpp | 2 +- NeutralStatsManager.cpp | 6 +++--- NeutralTrait.cpp | 2 +- Population.cpp | 4 ++-- SpeciesTrait.h | 5 +++++ 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Community.cpp b/Community.cpp index d7698be..88dbd74 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1845,7 +1845,7 @@ void Community::writePairwiseFSTFile(Species* pSpecies, const int yr, const int void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool fstat, bool perLocus, bool pairwise) { - const int nAlleles = (int)(pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second); + const int nAlleles = pSpecies->getSpTrait(NEUTRAL)->getNbNeutralAlleles(); const int nLoci = (int)pSpecies->getNPositionsForTrait(NEUTRAL); const set patchList = pSpecies->getSamplePatches(); int nInds = 0; diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 3e2a30b..7cd21b9 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -39,7 +39,7 @@ NeutralStatsManager::NeutralStatsManager(const int& nbSampledPatches, const int void NeutralStatsManager::updateAllNeutralTables(Species* pSpecies, Landscape* pLandscape, set const& patchList) { const int nLoci = pSpecies->getNPositionsForTrait(NEUTRAL); - const int nAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second; + const int nAlleles = pSpecies->getSpTrait(NEUTRAL)->getNbNeutralAlleles(); const int ploidy = pSpecies->isDiploid() ? 2 : 1; // Create / Update community-level NEUTRAL counts table @@ -104,7 +104,7 @@ void NeutralStatsManager::calcAllelicDiversityMetrics(set const& patchList, { int i, j; const int nLoci = pSpecies->getNPositionsForTrait(NEUTRAL); - const int nAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second; + const int nAlleles = pSpecies->getSpTrait(NEUTRAL)->getNbNeutralAlleles(); const int ploidy = pSpecies->isDiploid() ? 2 : 1; unsigned int nbPopulatedPatches = 0; int nbAllelesInPatch = 0; @@ -535,7 +535,7 @@ void NeutralStatsManager::calcPerLocusMeanSquaresFst(set const& patchList, // ---------------------------------------------------------------------------------------- void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape) { - const int nAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second; + const int nAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second + 1; const int ploidy = pSpecies->isDiploid() ? 2 : 1; // Needs to be in vector to iterate over, copy preserves order diff --git a/NeutralTrait.cpp b/NeutralTrait.cpp index 7c55c0c..be6a12a 100644 --- a/NeutralTrait.cpp +++ b/NeutralTrait.cpp @@ -14,7 +14,7 @@ NeutralTrait::NeutralTrait(SpeciesTrait* P) map mutationParameters = pSpeciesTrait->getMutationParameters(); // Set default value to user-specified max - wildType = (int)mutationParameters.find(MAX)->second - 1; + wildType = (int)mutationParameters.find(MAX)->second; if (wildType > NeutralValUpperBound) throw logic_error("Error:: max number of alleles cannot exceed " + to_string(NeutralValUpperBound) + ".\n"); diff --git a/Population.cpp b/Population.cpp index d7b9072..749eb69 100644 --- a/Population.cpp +++ b/Population.cpp @@ -333,7 +333,7 @@ void Population::resetPopNeutralTables() { void Population::updatePopNeutralTables() { const int nLoci = pSpecies->getNPositionsForTrait(NEUTRAL); - const int nAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second; + const int nAlleles = pSpecies->getSpTrait(NEUTRAL)->getNbNeutralAlleles(); const auto& positions = pSpecies->getSpTrait(NEUTRAL)->getGenePositions(); const int ploidy = pSpecies->isDiploid() ? 2 : 1; @@ -434,7 +434,7 @@ vector Population::countNbHeterozygotesEachLocus() { // ---------------------------------------------------------------------------------------- double Population::computeHs() { int nLoci = pSpecies->getNPositionsForTrait(NEUTRAL); - int nAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getInitialParameters().find(MAX)->second; + int nAlleles = pSpecies->getSpTrait(NEUTRAL)->getNbNeutralAlleles(); double hs = 0; double freq; vector locihet(nLoci, 1); diff --git a/SpeciesTrait.h b/SpeciesTrait.h index ef68e9a..db7cc1f 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -50,6 +50,11 @@ class SpeciesTrait { map getInitialParameters() const { return initialParameters; }; ExpressionType getExpressionType() const { return expressionType; }; + int getNbNeutralAlleles() const { + if (!traitType == NEUTRAL) throw logic_error("getNbNeutralAlleles() should only be called for neutral traits."); + else return getInitialParameters().find(MAX)->second + 1; // possible values range from 0 to MAX + } + private: inline static int ploidy = 0; From ad73797963c13594d8c0f9ca1115a208ee805679 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 8 Aug 2024 15:39:14 +0100 Subject: [PATCH 206/332] clarify use of the max uniform parameter --- NeutralStatsManager.cpp | 2 +- SpeciesTrait.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 7cd21b9..d9e0690 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -535,7 +535,7 @@ void NeutralStatsManager::calcPerLocusMeanSquaresFst(set const& patchList, // ---------------------------------------------------------------------------------------- void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape) { - const int nAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second + 1; + const int nAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getNbNeutralAlleles(); const int ploidy = pSpecies->isDiploid() ? 2 : 1; // Needs to be in vector to iterate over, copy preserves order diff --git a/SpeciesTrait.h b/SpeciesTrait.h index db7cc1f..d78c35d 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -52,7 +52,7 @@ class SpeciesTrait { int getNbNeutralAlleles() const { if (!traitType == NEUTRAL) throw logic_error("getNbNeutralAlleles() should only be called for neutral traits."); - else return getInitialParameters().find(MAX)->second + 1; // possible values range from 0 to MAX + else return getMutationParameters().find(MAX)->second + 1; // possible values range from 0 to MAX } private: From 3c060fa5cbb95dde618ce15dc163123ec9ee6380 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 8 Aug 2024 16:45:30 +0100 Subject: [PATCH 207/332] clarify meaning of allelic diversity metrics --- NeutralStatsManager.cpp | 10 +++++----- NeutralStatsManager.h | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index d9e0690..e72e15a 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -153,7 +153,7 @@ void NeutralStatsManager::calcAllelicDiversityMetrics(set const& patchList, // Compute number of fixed loci per patch // mean number of loci that are fixed at pop level per pop - meanNbFixedAllelesPerPatch = 0; + meanNbFixedLociPerPatch = 0; if (nbPopulatedPatches > 0) { for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); @@ -161,17 +161,17 @@ void NeutralStatsManager::calcAllelicDiversityMetrics(set const& patchList, if (pPop != 0) { for (i = 0; i < nLoci; ++i) for (j = 0; j < nAlleles; ++j) - meanNbFixedAllelesPerPatch += pPop->getAlleleFrequency(i, j) == 1; + meanNbFixedLociPerPatch += pPop->getAlleleFrequency(i, j) == 1; } } - meanNbFixedAllelesPerPatch /= nbPopulatedPatches; + meanNbFixedLociPerPatch /= nbPopulatedPatches; } // Compute number of fixed loci - nbGloballyFixedAlleles = 0; + meanFixedLoci = 0; for (i = 0; i < nLoci; ++i) for (j = 0; j < nAlleles; ++j) - nbGloballyFixedAlleles += commNeutralCountTables[i].getFrequency(j) == 1; + meanFixedLoci += commNeutralCountTables[i].getFrequency(j) == 1; } // ---------------------------------------------------------------------------------------- diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index ee0fdf4..ecfb440 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -110,8 +110,8 @@ class NeutralStatsManager { double getMeanNbAllPerLocusPerPatch() const { return meanNbAllelesPerLocusPerPatch; } double getMeanNbAllPerLocus() const { return meanNbAllelesPerLocus; } - double getMeanFixdAllelesPerPatch() const { return meanNbFixedAllelesPerPatch; } - double getTotalFixdAlleles() const { return nbGloballyFixedAlleles; } + double getMeanFixdAllelesPerPatch() const { return meanNbFixedLociPerPatch; } + double getTotalFixdAlleles() const { return meanFixedLoci; } double getHo() const { return ho; } double getHs() const { return hs; } @@ -137,7 +137,7 @@ class NeutralStatsManager { vector commNeutralCountTables; // community-level tallies of allele counts and freqs double meanNbAllelesPerLocusPerPatch, meanNbAllelesPerLocus; - double meanNbFixedAllelesPerPatch, nbGloballyFixedAlleles; + double meanNbFixedLociPerPatch, meanFixedLoci; double ho; // observed heterozygosity double hs; // expected population-level heterozygosity From 8e4da5126c6701c92f9ceebba0d3bdfeb75b001f Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 16 Aug 2024 13:46:12 +0100 Subject: [PATCH 208/332] fix variable name mismatch --- NeutralStatsManager.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index b3baa1d..375e51f 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -106,7 +106,7 @@ void NeutralStatsManager::calcAllelicDiversityMetrics(set const& patchList, const int nLoci = pSpecies->getNPositionsForTrait(NEUTRAL); const int nAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getMutationParameters().find(MAX)->second; const int ploidy = pSpecies->isDiploid() ? 2 : 1; - unsigned int nbPopulatedPatches = 0; + unsigned int nbPops = 0; int nbAllelesInPatch = 0; double meanAllelicDivInPatch = 0; bool alleleExistsInPop = 0; @@ -125,7 +125,7 @@ void NeutralStatsManager::calcAllelicDiversityMetrics(set const& patchList, const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop != 0) { if (pPop->sampleSize() > 0) { - nbPopulatedPatches++; + nbPops++; nbAllelesInPatch = 0; for (i = 0; i < nLoci; ++i) for (j = 0; j < nAlleles; ++j) { @@ -138,7 +138,7 @@ void NeutralStatsManager::calcAllelicDiversityMetrics(set const& patchList, } } } - meanNbAllelesPerLocusPerPatch = nbPopulatedPatches > 0 ? meanAllelicDivInPatch / nbPopulatedPatches : 0; + meanNbAllelesPerLocusPerPatch = nbPops > 0 ? meanAllelicDivInPatch / nbPops : 0; // Compute mean nb alleles per locus meanNbAllelesPerLocus = 0; @@ -154,7 +154,7 @@ void NeutralStatsManager::calcAllelicDiversityMetrics(set const& patchList, // Compute number of fixed loci per patch // mean number of loci that are fixed at pop level per pop meanNbFixedAllelesPerPatch = 0; - if (nbPopulatedPatches > 0) { + if (nbPops > 0) { for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); @@ -164,7 +164,7 @@ void NeutralStatsManager::calcAllelicDiversityMetrics(set const& patchList, meanNbFixedAllelesPerPatch += pPop->getAlleleFrequency(i, j) == 1; } } - meanNbFixedAllelesPerPatch /= nbPopulatedPatches; + meanNbFixedAllelesPerPatch /= nbPops; } // Compute number of fixed loci @@ -281,7 +281,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int double nBar, nC, inverseNbar; unsigned int nbPops = 0; const int ploidy = pSpecies->isDiploid() ? 2 : 1; - const int globalSampleSize = nbSampledIndsInComm * ploidy; // total nb of alleles + const int totalSampleSize = nbSampledIndsInComm * ploidy; // total nb of alleles for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); @@ -290,7 +290,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int int popSampleSize = pPop->sampleSize() * ploidy; if (popSampleSize > 0) { nbPops++; - sumWeights += static_cast(popSampleSize * popSampleSize) / globalSampleSize; + sumWeights += static_cast(popSampleSize * popSampleSize) / totalSampleSize; } } } @@ -301,16 +301,16 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int if (nbPops > 1) { // Calculate F stats - nBar = static_cast(totalSampleSize) / nbPopulatedPatches; // average sample size, cannot be less than 1 - nC = (totalSampleSize - sumWeights) / (nbPopulatedPatches - 1); + nBar = static_cast(totalSampleSize) / nbPops; // average sample size, cannot be less than 1 + nC = (totalSampleSize - sumWeights) / (nbPops - 1); double nBarMinusOne = (nBar == 1.0) ? 1.0 : nBar - 1.0; // avoid / 0 if exactly 1 ind per pop inverseNbar = 1.0 / nBarMinusOne; - inverseNtotal = 1.0 / globalSampleSize; + inverseNtotal = 1.0 / totalSampleSize; double var; double s2, pBar, hBar; - double s2Denom = 1.0 / ((nbPopulatedPatches - 1) * nBar); - double rTerm = static_cast(nbPopulatedPatches - 1) / nbPopulatedPatches; + double s2Denom = 1.0 / ((nbPops - 1) * nBar); + double rTerm = static_cast(nbPops - 1) / nbPops; double hBarFactor = (2 * nBar - 1) / (4 * nBar); double a = 0, b = 0, c = 0, intermediateTerm; @@ -542,7 +542,7 @@ void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, con copy(patchList.begin(), patchList.end(), std::back_inserter(patchVect)); int nPatches = static_cast(patchList.size()); - int nbPopulatedPatches = 0; + int nbPops = 0; // Initialise if (pairwiseFstMatrix.getNbCells() != nPatches * nPatches) @@ -572,14 +572,14 @@ void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, con } // else popSizes[i] remain default init value 0, safe popWeights[i] = popSizes[i] - (popSizes[i] * popSizes[i] / totSize); // n_ic in Weir & Hill 2002 sumWeights += popWeights[i]; - if (popSizes[i] > 0) nbPopulatedPatches++; + if (popSizes[i] > 0) nbPops++; // Fill the pairwise Fst matrix with default value 0 for (int j = 0; j < nPatches; j++) numeratorPairwiseFst[i][j] = 0; } - if (nbPopulatedPatches > 1) { + if (nbPops > 1) { // Calculate Fst numerators and denominators double p, pq, pBar, sqDist, num; for (int i = 0; i < nPatches; ++i) { From 4ba52c53303c78f95a327d79980fcc3ad32c9307 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 16 Aug 2024 16:08:12 +0100 Subject: [PATCH 209/332] fix iteration bug --- GeneticFitnessTrait.cpp | 15 ++++++++++----- NeutralTrait.cpp | 23 ++++++++++++++--------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index 533a0ba..771a676 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -308,9 +308,14 @@ void GeneticFitnessTrait::inheritGenes(const bool& fromMother, QuantitativeTrait // ---------------------------------------------------------------------------------------- void GeneticFitnessTrait::inheritDiploid(const bool& fromMother, map>> const& parentGenes, set const& recomPositions, int parentChromosome) { - auto it = recomPositions.lower_bound(parentGenes.begin()->first); - int nextBreakpoint = *it; - auto distance = std::distance(recomPositions.begin(), it); + const int lastPosition = parentGenes.rbegin()->first; + auto recomIt = recomPositions.lower_bound(parentGenes.begin()->first); + // If no recombination sites, only breakpoint is last position + // i.e., no recombination occurs + int nextBreakpoint = recomIt == recomPositions.end() ? lastPosition : *recomIt; + + // Is the first parent gene position already recombinant? + auto distance = std::distance(recomPositions.begin(), recomIt); if (distance % 2 != 0) parentChromosome = 1 - parentChromosome; // switch chromosome @@ -318,9 +323,9 @@ void GeneticFitnessTrait::inheritDiploid(const bool& fromMother, map nextBreakpoint) { - std::advance(it, 1); - nextBreakpoint = *it; parentChromosome = 1 - parentChromosome; + std::advance(recomIt, 1); // go to next recombination site + nextBreakpoint = recomIt == recomPositions.end() ? lastPosition : *recomIt; } if (locus <= nextBreakpoint) { diff --git a/NeutralTrait.cpp b/NeutralTrait.cpp index dc6a3b3..a883cc1 100644 --- a/NeutralTrait.cpp +++ b/NeutralTrait.cpp @@ -186,9 +186,14 @@ void NeutralTrait::inheritGenes(const bool& fromMother, QuantitativeTrait* paren // ---------------------------------------------------------------------------------------- void NeutralTrait::inheritDiploid(const bool& fromMother, map> const& parentGenes, set const& recomPositions, int parentChromosome) { - auto it = recomPositions.lower_bound(parentGenes.begin()->first); - unsigned int nextBreakpoint = *it; - auto distance = std::distance(recomPositions.begin(), it); + const int lastPosition = parentGenes.rbegin()->first; + auto recomIt = recomPositions.lower_bound(parentGenes.begin()->first); + // If no recombination sites, only breakpoint is last position + // i.e., no recombination occurs + int nextBreakpoint = recomIt == recomPositions.end() ? lastPosition : *recomIt; + + // Is the first parent gene position already recombinant? + auto distance = std::distance(recomPositions.begin(), recomIt); if (distance - 1 % 2 != 0) parentChromosome = 1 - parentChromosome; //switch chromosome @@ -196,24 +201,24 @@ void NeutralTrait::inheritDiploid(const bool& fromMother, map nextBreakpoint) { - std::advance(it, 1); - nextBreakpoint = *it; - parentChromosome = 1 - parentChromosome; //switch chromosome + parentChromosome = 1 - parentChromosome; + std::advance(recomIt, 1); // go to next recombination site + nextBreakpoint = recomIt == recomPositions.end() ? lastPosition : *recomIt; } if (locus <= nextBreakpoint) { - unsigned char sp = allelePair[parentChromosome]; + unsigned char parentAllele = allelePair[parentChromosome]; auto it = genes.find(locus); if (it == genes.end()) { // locus does not exist yet, create and initialise it if (!fromMother) throw runtime_error("Father-inherited locus does not exist."); vector newAllelePair(2, wildType); - newAllelePair[sex_t::FEM] = sp; + newAllelePair[sex_t::FEM] = parentAllele; genes.insert(make_pair(locus, newAllelePair)); } else { // father, locus already exists if (fromMother) throw runtime_error("Mother-inherited locus already exists."); - it->second[sex_t::MAL] = sp; + it->second[sex_t::MAL] = parentAllele; } } } From 3cc291ebc28d16a780d40101325e22d8653d20ee Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Sat, 17 Aug 2024 21:25:09 +0100 Subject: [PATCH 210/332] readGenetics, readTraitsFile now reads the correct nb of lines for each simulation --- SpeciesTrait.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index b222335..c0cdd87 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -35,7 +35,7 @@ SpeciesTrait::SpeciesTrait( { case MIN: case MAX: case MEAN: if (!isValidTraitVal(paramVal)) - throw logic_error("Invalid parameter value: initial parameter " + to_string(paramType) + " must have a valid value for trait" + to_string(traitType) + "."); + throw logic_error("Invalid parameter value: initial parameter " + to_string(paramType) + " must have a valid value for trait " + to_string(traitType) + "."); break; case SD: if (paramVal <= 0.0) @@ -57,7 +57,7 @@ SpeciesTrait::SpeciesTrait( && !isValidTraitVal(paramVal) // dispersal traits are cumulative so no value is invalid ) - throw logic_error("Invalid parameter value: mutation parameter " + to_string(paramType) + " must have a valid value for trait" + to_string(traitType) + "."); + throw logic_error("Invalid parameter value: mutation parameter " + to_string(paramType) + " must have a valid value for trait " + to_string(traitType) + "."); break; case SD: case SHAPE: case SCALE: if (paramVal <= 0.0) From 23cda73f8278fd99990d09c95805950a273d3f06 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 20 Aug 2024 15:04:42 +0100 Subject: [PATCH 211/332] output dominance coefficients, solve #60 --- Community.cpp | 4 ++-- DispersalTrait.cpp | 7 +++++++ DispersalTrait.h | 1 + GeneticFitnessTrait.cpp | 14 +++++++------- GeneticFitnessTrait.h | 2 +- NeutralTrait.h | 4 ++++ Population.cpp | 17 +++++++++++++++-- QuantitativeTrait.h | 1 + 8 files changed, 38 insertions(+), 12 deletions(-) diff --git a/Community.cpp b/Community.cpp index c940316..ccf3662 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1584,10 +1584,10 @@ bool Community::openOutGenesFile(const bool& isDiploid, const int landNr, const ofsGenes.open(name.c_str()); ofsGenes << "Year\tGeneration\tIndID\ttraitType\tlocusPosition"; if (isDiploid) { - ofsGenes << "\talleleValueA\talleleValueB"; + ofsGenes << "\talleleValueA\tdomCoefA\talleleValueBA\tdomCoefB"; } else { - ofsGenes << "\talleleValue"; + ofsGenes << "\talleleValueA\tdomCoefA"; } ofsGenes << endl; return ofsGenes.is_open(); diff --git a/DispersalTrait.cpp b/DispersalTrait.cpp index 1cf59df..8413775 100644 --- a/DispersalTrait.cpp +++ b/DispersalTrait.cpp @@ -455,6 +455,13 @@ float DispersalTrait::getAlleleValueAtLocus(short whichChromosome, int position) return it->second[whichChromosome].get()->getAlleleValue(); } +float DispersalTrait::getDomCoefAtLocus(short whichChromosome, int position) const { + auto it = genes.find(position); + if (it == genes.end()) + throw runtime_error("The genetic load locus queried for its dominance coefficient does not exist."); + return it->second[whichChromosome]->getDominanceCoef(); +} + #if RSDEBUG // Testing only // Get allele ID at locus diff --git a/DispersalTrait.h b/DispersalTrait.h index 3f9815c..76a76ab 100644 --- a/DispersalTrait.h +++ b/DispersalTrait.h @@ -42,6 +42,7 @@ class DispersalTrait : public QuantitativeTrait { void inheritGenes(const bool& fromMother, QuantitativeTrait* parent, set const& recomPositions, int startingChromosome) override; float getAlleleValueAtLocus(short chromosome, int i) const override; + float getDomCoefAtLocus(short chromosome, int position) const override; int countHeterozygoteLoci() const; bool isHeterozygoteAtLocus(int locus) const override; diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index 771a676..cd266c5 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -426,6 +426,13 @@ float GeneticFitnessTrait::getAlleleValueAtLocus(short whichChromosome, int posi return it->second[whichChromosome] == 0 ? wildType->getAlleleValue() : it->second[whichChromosome]->getAlleleValue(); } +float GeneticFitnessTrait::getDomCoefAtLocus(short whichChromosome, int position) const { + auto it = genes.find(position); + if (it == genes.end()) + throw runtime_error("The genetic load locus queried for its dominance coefficient does not exist."); + return it->second[whichChromosome] == 0 ? wildType->getDominanceCoef() : it->second[whichChromosome]->getDominanceCoef(); +} + #if RSDEBUG // Testing only // Get allele ID at locus int GeneticFitnessTrait::getAlleleIDAtLocus(short whichChromosome, int position) const { @@ -435,11 +442,4 @@ int GeneticFitnessTrait::getAlleleIDAtLocus(short whichChromosome, int position) return it->second[whichChromosome].get()->getId(); } -float GeneticFitnessTrait::getDomCoefAtLocus(short whichChromosome, int position) const { - auto it = genes.find(position); - if (it == genes.end()) - throw runtime_error("The genetic load locus queried for its dominance coefficient does not exist."); - return it->second[whichChromosome] == 0 ? wildType->getDominanceCoef() : it->second[whichChromosome]->getDominanceCoef(); -} - #endif // RSDEBUG \ No newline at end of file diff --git a/GeneticFitnessTrait.h b/GeneticFitnessTrait.h index 8bd60ac..ebb6e76 100644 --- a/GeneticFitnessTrait.h +++ b/GeneticFitnessTrait.h @@ -46,11 +46,11 @@ class GeneticFitnessTrait : public QuantitativeTrait { virtual void inheritGenes(const bool& fromMother, QuantitativeTrait* parent, set const& recomPositions, int startingChromosome) override; virtual float getAlleleValueAtLocus(short chromosome, int position) const override; + virtual float getDomCoefAtLocus(short chromosome, int position) const override; virtual int countHeterozygoteLoci() const; virtual bool isHeterozygoteAtLocus(int locus) const override; #if RSDEBUG // for testing only int getAlleleIDAtLocus(short whichChromosome, int position) const; - float getDomCoefAtLocus(short chromosome, int position) const; #endif private: diff --git a/NeutralTrait.h b/NeutralTrait.h index e2a0e6d..ed12339 100644 --- a/NeutralTrait.h +++ b/NeutralTrait.h @@ -47,6 +47,10 @@ class NeutralTrait : public QuantitativeTrait { } virtual float getAlleleValueAtLocus(short chromosome, int position) const override; + virtual float getDomCoefAtLocus(short chromosome, int position) const override { + return 0.0; + } + virtual int countHeterozygoteLoci() const; virtual bool isHeterozygoteAtLocus(int locus) const override; #if RSDEBUG // for testing only diff --git a/Population.cpp b/Population.cpp index 97ee943..59b302f 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1938,6 +1938,7 @@ void Population::outputGeneValues(ofstream& ofsGenes, const int& yr, const int& auto traitTypes = pSpecies->getTraitTypes(); int indID; float alleleOnChromA, alleleOnChromB; + float domCoefA, domCoefB; // Fetch map to positions for each trait // Presumably faster than fetching for every individual @@ -1955,10 +1956,22 @@ void Population::outputGeneValues(ofstream& ofsGenes, const int& yr, const int& auto indTrait = ind->getTrait(trType); for (auto pos : positions) { alleleOnChromA = indTrait->getAlleleValueAtLocus(0, pos); - ofsGenes << yr << '\t' << gen << '\t' << indID << '\t' << trType << '\t' << pos << '\t' << alleleOnChromA; + if (trType == GENETIC_LOAD1 || trType == GENETIC_LOAD2 || trType == GENETIC_LOAD3 || trType == GENETIC_LOAD4 || trType == GENETIC_LOAD5) { + domCoefA = indTrait->getDomCoefAtLocus(0, pos); + } + else { + domCoefA = 0.0; + } + ofsGenes << yr << '\t' << gen << '\t' << indID << '\t' << to_string(trType) << '\t' << pos << '\t' << alleleOnChromA << '\t' << domCoefA; if (isDiploid) { alleleOnChromB = indTrait->getAlleleValueAtLocus(1, pos); - ofsGenes << '\t' << alleleOnChromB; + if (trType == GENETIC_LOAD1 || trType == GENETIC_LOAD2 || trType == GENETIC_LOAD3 || trType == GENETIC_LOAD4 || trType == GENETIC_LOAD5) { + domCoefB = indTrait->getDomCoefAtLocus(1, pos); + } + else { + domCoefB = 0.0; + } + ofsGenes << '\t' << alleleOnChromB << '\t' << domCoefB; } ofsGenes << endl; } diff --git a/QuantitativeTrait.h b/QuantitativeTrait.h index e19a9bf..7d0a0e4 100644 --- a/QuantitativeTrait.h +++ b/QuantitativeTrait.h @@ -21,6 +21,7 @@ class QuantitativeTrait { virtual float getMutationRate() const = 0; virtual bool isInherited() const = 0; virtual float getAlleleValueAtLocus(short chromosome, int i) const = 0; + virtual float getDomCoefAtLocus(short whichChromosome, int position) const = 0; virtual int countHeterozygoteLoci() const = 0; virtual bool isHeterozygoteAtLocus(int loci) const = 0; virtual float express() = 0; From da35269f5d0fb6e410728373eb614b608398a043 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 20 Aug 2024 16:12:26 +0100 Subject: [PATCH 212/332] enable selecting which traits are output, solve #53 --- Population.cpp | 20 ++++++------- SpeciesTrait.cpp | 12 +++++--- SpeciesTrait.h | 5 +++- unit_tests/testIndividual.cpp | 54 +++++++++++++++++++++++------------ 4 files changed, 58 insertions(+), 33 deletions(-) diff --git a/Population.cpp b/Population.cpp index 59b302f..c9ebb73 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1741,7 +1741,6 @@ void Population::outPopulation(int rep, int yr, int gen, float eps, // Open individuals file and write header record void Population::outIndsHeaders(int rep, int landNr, bool patchModel) { - if (landNr == -999) { // close file if (outInds.is_open()) { outInds.close(); outInds.clear(); @@ -1884,12 +1883,6 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, if (trfr.moveType == 2) { // CRW trfrCRWTraits c = inds[i]->getIndCRWTraits(); outInds << "\t" << c.stepLength << "\t" << c.rho; -#if RSDEBUG - //DEBUGLOG << "Population::outIndividual():" - // << " patchNum=" << patchNum << " i=" << i << " ID=" << inds[i]->getId() - // << " nTrfrGenes=" << nTrfrGenes << " loc[0][0].allele[0]=" << loc[0][0].allele[0] - // << endl; -#endif } // end of CRW } else { // kernel @@ -1935,15 +1928,22 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, void Population::outputGeneValues(ofstream& ofsGenes, const int& yr, const int& gen) const { const bool isDiploid = pSpecies->isDiploid(); - auto traitTypes = pSpecies->getTraitTypes(); int indID; float alleleOnChromA, alleleOnChromB; float domCoefA, domCoefB; + // Subset traits that are selected to be output + set traitTypes = pSpecies->getTraitTypes(); + set outputTraitTypes; + for (auto trType : traitTypes) { + if (pSpecies->getSpTrait(trType)->isOutput()) + outputTraitTypes.insert(trType); + } + // Fetch map to positions for each trait // Presumably faster than fetching for every individual map> allGenePositions; - for (auto trType : traitTypes) { + for (auto trType : outputTraitTypes) { set traitPositions = pSpecies->getSpTrait(trType)->getGenePositions(); allGenePositions.insert(make_pair(trType, traitPositions)); } @@ -1951,7 +1951,7 @@ void Population::outputGeneValues(ofstream& ofsGenes, const int& yr, const int& set positions; for (Individual* ind : sampledInds) { indID = ind->getId(); - for (auto trType : traitTypes) { + for (auto trType : outputTraitTypes) { positions = allGenePositions[trType]; auto indTrait = ind->getTrait(trType); for (auto pos : positions) { diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index c0cdd87..6ffd4c1 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -13,7 +13,8 @@ SpeciesTrait::SpeciesTrait( bool isInherited, const float& mutRate, const DistributionType& mutationDist, const map mutationParams, - const int nPloidy) : + const int nPloidy, + const bool isOutput) : traitType{ trType }, sex{ sx }, genePositions{ pos }, @@ -26,7 +27,8 @@ SpeciesTrait::SpeciesTrait( mutationDistribution{ mutationDist }, mutationParameters{ mutationParams }, mutationRate{ mutRate }, - ploidy{ nPloidy } + ploidy{ nPloidy }, + traitIsOutput{ isOutput } { // Check distribution parameters // Initial distribution @@ -212,7 +214,8 @@ SpeciesTrait* createTestEmigSpTrait(const set& genePositions, const bool& i 0.0, // mutation rate DistributionType::UNIFORM, distParams, - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); return spTr; } @@ -237,7 +240,8 @@ SpeciesTrait* createTestNeutralSpTrait(const float& maxAlleleVal, const set // Mutation sampled from a uniform(0, max) DistributionType::KAM, distParams, - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); return spTr; } diff --git a/SpeciesTrait.h b/SpeciesTrait.h index 6aa6794..9761332 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -28,11 +28,13 @@ class SpeciesTrait { const float& mutationRate, const DistributionType& mutationDist, const map mutationParams, - const int ploidy + const int ploidy, + const bool isOutput ); bool isValidTraitVal(const float& val) const; TraitType getTraitType() const { return traitType; } + bool isOutput() const { return traitIsOutput; } // Getters sex_t getSex() const { return sex; } @@ -60,6 +62,7 @@ class SpeciesTrait { int ploidy; float mutationRate; TraitType traitType; + bool traitIsOutput; sex_t sex; // Positions in the genome of all genes (loci) pertaining to this trait diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index eb86ed8..5e6d2cb 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -545,7 +545,8 @@ void testGenetics() { isInherited, 0.0, // no mutations DistributionType::UNIFORM, distParams, // ignored - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); // Create individual trait objects @@ -604,7 +605,8 @@ void testGenetics() { true, 1.0, // every site mutates DistributionType::GAMMA, mutationParams, - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); // Create individual trait object @@ -644,7 +646,8 @@ void testGenetics() { true, 1.0, // every site mutates DistributionType::NORMAL, mutationParams, - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); // Create individual trait object @@ -791,7 +794,8 @@ void testIndividual() { true, // isInherited maleMutationRate, // does not mutate DistributionType::UNIFORM, mutationParams, // not used - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); pSpecies->addTrait(TraitType::E_D0_M, *spTrM); @@ -806,7 +810,8 @@ void testIndividual() { true, // isInherited femaleMutationRate, // does mutate DistributionType::UNIFORM, mutationParams, // not used - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); pSpecies->addTrait(TraitType::E_D0_F, *spTrF); @@ -869,7 +874,8 @@ void testIndividual() { true, // isInherited 0.0, // no mutation DistributionType::UNIFORM, mutationParams, // not used - 2 // diploid + 2, // diploid + false ); pSpecies->addTrait(TraitType::E_D0, *spTr); @@ -933,7 +939,8 @@ void testIndividual() { true, // isInherited 1.0, // will mutate DistributionType::UNIFORM, mutationParams, // lethal mutation - 2 // diploid + 2, // diploid + false ); pSpecies->addTrait(TraitType::GENETIC_LOAD1, *spTr); @@ -982,7 +989,8 @@ void testIndividual() { true, // isInherited 0.0, // no mutation DistributionType::UNIFORM, distParams, // lethal mutation - 2 // diploid + 2, // diploid + false ); pSpecies->addTrait(TraitType::GENETIC_LOAD1, *spTr); @@ -1061,7 +1069,8 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); SpeciesTrait* trSettAlpha = new SpeciesTrait( TraitType::S_ALPHA, @@ -1073,7 +1082,8 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); SpeciesTrait* trSettBeta = new SpeciesTrait( TraitType::S_BETA, @@ -1085,7 +1095,8 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); SpeciesTrait* trMeanKern = new SpeciesTrait( TraitType::KERNEL_MEANDIST_1, @@ -1097,7 +1108,8 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); pSpecies->addTrait(TraitType::S_S0, *trSettProb); @@ -1171,7 +1183,8 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); SpeciesTrait* trCRWCorr = new SpeciesTrait( TraitType::CRW_STEPCORRELATION, @@ -1183,7 +1196,8 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); pSpecies->addTrait(TraitType::CRW_STEPLENGTH, *trCRWLen); @@ -1252,7 +1266,8 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); SpeciesTrait* trSmsGoalBias = new SpeciesTrait( TraitType::SMS_GB, @@ -1264,7 +1279,8 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); SpeciesTrait* trSmsAlpha = new SpeciesTrait( TraitType::SMS_ALPHADB, @@ -1276,7 +1292,8 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); SpeciesTrait* trSmsBeta = new SpeciesTrait( TraitType::SMS_BETADB, @@ -1288,7 +1305,8 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used - isDiploid ? 2 : 1 + isDiploid ? 2 : 1, + false ); pSpecies->addTrait(TraitType::SMS_DP, *trSmsDirPers); From 2c20025d8eb4ab7366fadddfd1e1a93ed51b483c Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 26 Aug 2024 14:58:19 +0100 Subject: [PATCH 213/332] better placement for closing macro --- DispersalTrait.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DispersalTrait.cpp b/DispersalTrait.cpp index 8413775..be66d93 100644 --- a/DispersalTrait.cpp +++ b/DispersalTrait.cpp @@ -471,6 +471,7 @@ int DispersalTrait::getAlleleIDAtLocus(short whichChromosome, int position) cons throw runtime_error("The Dispersal locus queried for its allele value does not exist."); return it->second[whichChromosome].get()->getId(); } +#endif #if RSDEBUG @@ -499,5 +500,4 @@ map>> createTestGenotype( } return genotype; } -#endif RSDEBUG #endif // RSDEBUG \ No newline at end of file From 3c4fa34f9fee2b77e05b98b9278ff8c265d0e1e9 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 26 Aug 2024 15:00:01 +0100 Subject: [PATCH 214/332] default switch case to avoid gcc warning --- Parameters.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Parameters.cpp b/Parameters.cpp index afce6f3..6b47f06 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -427,6 +427,7 @@ string to_string(const TraitType& tr) { case SMS_ALPHADB: return "SMS_ALPHADB"; case SMS_BETADB: return "SMS_BETADB"; case INVALID_TRAIT: return "INVALID_TRAIT"; + default: return ""; } } @@ -440,6 +441,7 @@ string to_string(const GenParamType& param) { case SHAPE: return "SHAPE"; case SCALE: return "SCALE"; case INVALID: return "INVALID"; + default: return ""; } } @@ -454,6 +456,7 @@ string to_string(const DistributionType& dist) { case KAM: return "KAM"; case SSM: return "SSM"; case NONE: return "NONE"; + default: return ""; } } @@ -464,6 +467,7 @@ string to_string(const ExpressionType& expr) { case ADDITIVE: return "ADDITIVE"; case NOTEXPR: return "NOTEXPR"; case MULTIPLICATIVE: return "MULTIPLICATIVE"; + default: return ""; } } From 13f18782058d8a5961a107a10bfb99cca4306b23 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 26 Aug 2024 15:06:19 +0100 Subject: [PATCH 215/332] fix bug with reading carriage returns as part of TraitsFIle --- Species.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Species.h b/Species.h index 557de11..9e47725 100644 --- a/Species.h +++ b/Species.h @@ -420,8 +420,6 @@ class Species { SpeciesTrait* getSpTrait(TraitType trait) const; - //map>& getTraitTable(void); //return by reference so ensure variable recieving is const - std::set getTraitTypes(); int getNTraits() const; From e9a4327d118740292e7ad88448ab5c218a092e09 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 26 Aug 2024 22:18:54 +0100 Subject: [PATCH 216/332] progress on #44 --- Individual.cpp | 10 ++++ Individual.h | 3 +- NeutralTrait.cpp | 21 ++++++++ NeutralTrait.h | 11 +++- Population.cpp | 93 ++------------------------------- unit_tests/testNeutralStats.cpp | 40 +++++++++----- 6 files changed, 75 insertions(+), 103 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 8e109ee..aff3ed8 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1664,5 +1664,15 @@ void Individual::overrideGenotype(TraitType whichTrait, const map>& newGenotype) { + + if (!whichTrait == NEUTRAL) { + throw logic_error("Attempt to override non-neutral trait with neutral trait genotype.\n"); + } + NeutralTrait* pNeutralTrait; + pNeutralTrait = dynamic_cast(this->getTrait(NEUTRAL)); + pNeutralTrait->getGenes() = newGenotype; +}; + #endif // RSDEBUG diff --git a/Individual.h b/Individual.h index de143b9..0c18422 100644 --- a/Individual.h +++ b/Individual.h @@ -352,7 +352,8 @@ class Individual { }; void triggerMutations(Species* pSp); // Shorthand function to edit a genotype with custom values - void overrideGenotype(TraitType whichTrait, const map>>& newGenotype); + void overrideGenotype(TraitType whichTrait, const map>>& newGenotype); // dispersal + gen. fitness + void overrideGenotype(TraitType whichTrait, const map>& newGenotype); // neutral #endif private: diff --git a/NeutralTrait.cpp b/NeutralTrait.cpp index a883cc1..41229fa 100644 --- a/NeutralTrait.cpp +++ b/NeutralTrait.cpp @@ -297,4 +297,25 @@ int NeutralTrait::getAlleleIDAtLocus(short whichChromosome, int position) const // need this declaration for quanti trait that use an actual ID return getAlleleValueAtLocus(whichChromosome, position); } + +// Create a default set of neutral alleles for testing +// +// Shorthand function to manually set genotypes for neutral +// traits, instead of having to manipulate mutations. +map> createTestNeutralGenotype( + const int genomeSz, const bool isDiploid, + const unsigned char valAlleleA, + const unsigned char valAlleleB +) { + vector gene(isDiploid ? 2 : 1); + gene[0] = valAlleleA; + if (isDiploid) gene[1] = valAlleleB; + + map> genotype; + for (int i = 0; i < genomeSz; i++) { + genotype.emplace(i, gene); + } + return genotype; +} + #endif // RSDEBUG \ No newline at end of file diff --git a/NeutralTrait.h b/NeutralTrait.h index ed12339..61db526 100644 --- a/NeutralTrait.h +++ b/NeutralTrait.h @@ -85,4 +85,13 @@ class NeutralTrait : public QuantitativeTrait { void mutate_SSM(); // single-step mutations }; -#endif \ No newline at end of file + +#if RSDEBUG // for testing purposes only +map> createTestNeutralGenotype( + const int genomeSz, const bool isDiploid, + const unsigned char valAlleleA, + const unsigned char valAlleleB = -99.9 // if haploid +); +#endif + +#endif // NeutralTraitH \ No newline at end of file diff --git a/Population.cpp b/Population.cpp index c9ebb73..5ebb46e 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1384,12 +1384,6 @@ void Population::survival0(float localK, short option0, short option1) dev[stg][sex] = 1.0; surv[stg][sex] = 1.0; minAge[stg][sex] = 0; } } -#if RSDEBUG - //DEBUGLOG << "Population::survival0(): 1111 " - // << " dev[" << stg << "][" << sex << "] = " << dev[stg][sex] - // << " surv[" << stg << "][" << sex << "] = " << surv[stg][sex] - // << endl; -#endif } } if (dem.stageStruct) { @@ -1414,11 +1408,6 @@ void Population::survival0(float localK, short option0, short option1) weight = pSpecies->getDDwtDev(stg, effstg); } effect += (float)nInds[effstg][effsex] * weight; -#if RSDEBUG - // DEBUGLOG << " effstg=" << effstg << " effsex=" << effsex; - // DEBUGLOG << " weight=" << weight << " effect=" << effect - // << endl; -#endif } } } @@ -1426,18 +1415,9 @@ void Population::survival0(float localK, short option0, short option1) effect = (float)totalPop(); if (localK > 0.0) dev[stg][sex] *= exp(-(ddparams.devCoeff * effect) / localK); -#if RSDEBUG - //DEBUGLOG << "Population::survival0(): 2288 " << " effect=" << effect; - //if (localK > 0.0) - // DEBUGLOG << " exp=" << exp(-(ddparams.devCoeff*effect)/localK); - //DEBUGLOG << " dev[" << stg << "][" << sex << "] = " << dev[stg][sex] - // << endl; -#endif } // end of if (sstruct.devDens && stg > 0) if (option1 != 0 && sstruct.survDens) { -#if RSDEBUG - // DEBUGLOG << "DD in SURVIVAL for stg=" << stg << " sex=" << sex << endl; -#endif + float effect = 0.0; if (sstruct.survStageDens) { // stage-specific density dependence // NOTE: matrix entries represent effect of ROW on COLUMN @@ -1455,11 +1435,6 @@ void Population::survival0(float localK, short option0, short option1) weight = pSpecies->getDDwtSurv(stg, effstg); } effect += (float)nInds[effstg][effsex] * weight; -#if RSDEBUG - // DEBUGLOG << " effstg=" << effstg << " effsex=" << effsex; - // DEBUGLOG << " weight=" << weight << " effect=" << effect - // << endl; -#endif } } } @@ -1467,33 +1442,14 @@ void Population::survival0(float localK, short option0, short option1) effect = (float)totalPop(); if (localK > 0.0) surv[stg][sex] *= exp(-(ddparams.survCoeff * effect) / localK); -#if RSDEBUG - //DEBUGLOG << "Population::survival0(): 3333 " << " effect=" << effect; - //if (localK > 0.0) - // DEBUGLOG << " exp = " << exp(-(ddparams.survCoeff*effect)/localK); - //DEBUGLOG << " surv[" << stg << "][" << sex << "] = " << surv[stg][sex] - // << endl; -#endif } // end of if (sstruct.survDens) } } } // identify which individuals die or develop -#if RSDEBUG -//DEBUGLOG << "Population::survival0():" << " ninds " << ninds -// << endl; -#endif for (int i = 0; i < ninds; i++) { indStats ind = inds[i]->getStats(); -#if RSDEBUG - //DEBUGLOG << "Population::survival0():" - // << " i=" << i << " indId=" << inds[i]->getId() - // << " stage=" << ind.stage << " status=" << ind.status << " sex=" << ind.sex - //#if PARTMIGRN - // << " migrnstatus=" << inds[i]->getMigrnStatus() - //#endif // PARTMIGRN - // << endl; -#endif + if ((ind.stage == 0 && option0 < 2) || (ind.stage > 0 && option0 > 0)) { // condition for processing the stage is met... if (ind.status < 6) { // not already doomed @@ -1506,19 +1462,7 @@ void Population::survival0(float localK, short option0, short option1) // does the individual develop? double probdev = dev[ind.stage][ind.sex]; if (ind.stage < nStages - 1) { // not final stage -#if RSDEBUG - //DEBUGLOG << "Population::survival0():" - // << " i=" << i << " indId=" << inds[i]->getId() - // << " age=" << ind.age << " minAge[stage+1]=" << minAge[ind.stage+1][ind.sex] - // << " probdev=" << probdev - // << endl; -#endif if (ind.age >= minAge[ind.stage + 1][ind.sex]) { // old enough to enter next stage -#if RSDEBUG - //DEBUGLOG << "Population::survival0():" - // << " i=" << i << " indId=" << inds[i]->getId() << " OLD ENOUGH" - // << endl; -#endif if (pRandom->Bernoulli(probdev)) { inds[i]->developing(); } @@ -1526,22 +1470,10 @@ void Population::survival0(float localK, short option0, short option1) } } else { // doomed to die -#if RSDEBUG - //DEBUGLOG << "Population::survival0():" - // << " i=" << i << " indId=" << inds[i]->getId() << " DIES" - // << endl; -#endif inds[i]->setStatus(8); } } } -#if RSDEBUG - //ind = inds[i]->getStats(); - //DEBUGLOG << "Population::survival0():" - // << " i = " << i << " ID = " << inds[i]->getId() - // << " stage = " << ind.stage << " status = " << ind.status - // << endl; -#endif } } @@ -1549,19 +1481,10 @@ void Population::survival0(float localK, short option0, short option1) void Population::survival1(void) { int ninds = (int)inds.size(); -#if RSDEBUG - //DEBUGLOG << "Population::survival1(): this=" << this - // << " patchNum=" << pPatch->getPatchNum() << " ninds=" << ninds - // << endl; -#endif + for (int i = 0; i < ninds; i++) { indStats ind = inds[i]->getStats(); -#if RSDEBUG - //DEBUGLOG << "Population::survival1(): i=" << i - // << " indId=" << inds[i]->getId() << " stage=" << ind.stage << " sex=" << ind.sex - // << " isDeveloping=" << ind.isDeveloping << " status=" << ind.status - // << endl; -#endif + if (ind.status > 5) { // doomed to die if (ind.status != 10) //not going into cold storage delete inds[i]; @@ -1576,15 +1499,7 @@ void Population::survival1(void) } } } -#if RSDEBUG - //DEBUGLOG << "Population::survival1(): this=" << this - // << " patchNum=" << pPatch->getPatchNum() << " completed individuals loop" - // << endl; -#endif - - clean(); - } void Population::ageIncrement(void) { diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index 4a5c47c..759440b 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -14,7 +14,7 @@ demogrParams createDefltHaploidDemogrParams() { return d; } -demogrParams createDefltDiploidDemogrParams() { +demogrParams createDefaultDiploidDemogrParams() { demogrParams d; d.repType = 1; d.repSeasons = 1; @@ -89,7 +89,7 @@ void testNeutralStats() { // Create genetic structure const int genomeSz = 4; Species* pSpecies = new Species(); - pSpecies->setDemogr(createDefltDiploidDemogrParams()); + pSpecies->setDemogr(createDefaultDiploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome genomeSz, @@ -136,7 +136,7 @@ void testNeutralStats() { // Create genetic structure const int genomeSz = 4; Species* pSpecies = new Species(); - pSpecies->setDemogr(createDefltDiploidDemogrParams()); + pSpecies->setDemogr(createDefaultDiploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome genomeSz, @@ -178,20 +178,21 @@ void testNeutralStats() { Landscape* pLandscape = new Landscape; const int nbPatches = 2; vector patches(nbPatches); + vector cells(nbPatches); set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - Cell* pCell = new Cell(0, 0, (intptr)patches[i], 0); - patches[i]->addCell(pCell, 0, 0); + cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } const string indSampling = "all"; const set stgToSample = { 1 }; // Create genetic structure - const int genomeSz = 4; + const int genomeSz = 2; Species* pSpecies = new Species(); - pSpecies->setDemogr(createDefltDiploidDemogrParams()); + pSpecies->setDemogr(createDefaultDiploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome genomeSz, @@ -201,19 +202,34 @@ void testNeutralStats() { stgToSample, 1 ); - const set genePositions = { 0, 1, 3 }; // arbitrary + const set genePositions = { 0, 1 }; const int nbLoci = genePositions.size(); const bool isDiploid{ true }; const float maxAlleleVal = 255; // highly unlikely that same value sampled twice SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); pSpecies->addTrait(TraitType::NEUTRAL, *spTr); - // Initialise populations const int nbIndsPerPop = 2; - for (auto p : patches) { - Population* pPop = new Population(pSpecies, p, nbIndsPerPop, 1); + unsigned char alleleValPopA = char(0); + unsigned char alleleValPopB = char(1); + auto popAGenotype = createTestNeutralGenotype(genomeSz, true, alleleValPopA, alleleValPopA); + auto popBGenotype = createTestNeutralGenotype(genomeSz, true, alleleValPopB, alleleValPopB); + vector< + map> + > genotypes = { popAGenotype, popBGenotype }; + + // Initialise populations + for (int p = 0; p < patches.size(); p++) { + Population* pPop = new Population(pSpecies, patches[p], 0, 1); + // create individuals and add to pop + for (int i = 0; i < nbIndsPerPop; i++) { + Individual ind = Individual(cells[p], patches[p], 0, 0, 0, 0.0, false, 1); + ind.setUpGenes(pSpecies, 1.0); + ind.overrideGenotype(NEUTRAL, genotypes[p]); + pPop->recruit(&ind); + } pPop->sampleIndsWithoutReplacement(indSampling, stgToSample); - } + } // do individuals still exist? // Calculate heterozygosity auto pNeutralStatistics = make_unique(nbPatches, nbLoci); From 5d5da878d15cb8dd63ebb22694dc60e4cbb28454 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 27 Aug 2024 10:49:48 +0100 Subject: [PATCH 217/332] fix incorrect initiation of rows and columns in PatchMatrix --- NeutralStatsManager.cpp | 5 ++- NeutralStatsManager.h | 20 +++++------ unit_tests/testNeutralStats.cpp | 62 +++++++++++++++++++-------------- 3 files changed, 47 insertions(+), 40 deletions(-) diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 6918214..e506a7c 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -345,7 +345,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int c *= 0.5; fst = a / (a + b + c); // theta hat in eq. 1 in WC 1984 - fis = b / (b + c); // f hat + fis = (b + c == 0.0) ? 0.0 : b / (b + c); // f hat fit = (a + b) / (a + b + c); // F hat } else { // zero or one sampled pops, cannot compute F stats @@ -545,8 +545,7 @@ void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, con int nbPops = 0; // Initialise - if (pairwiseFstMatrix.getNbCells() != nPatches * nPatches) - pairwiseFstMatrix = PatchMatrix(nPatches, nPatches); + pairwiseFstMatrix = PatchMatrix(nPatches, nPatches); // Reset table pairwiseFstMatrix.setAll(0.0); // or nanf("NULL")? diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index 93bc4d9..ca7d2c7 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -11,27 +11,27 @@ using namespace std; struct PatchMatrix { public: - PatchMatrix(int rows = 0, int cols = 0) : rows(0), cols(0), nbCells(0), value(0) { - nbCells = rows * cols; + PatchMatrix(unsigned int nRows = 0, unsigned int nCols = 0) : + rows{ nRows }, + cols{ nCols }, + nbCells{nCols * nRows} { value.resize(nbCells); - rows = rows; cols = cols; }; // Get value at specified position double get(unsigned int i, unsigned int j) { - if (!((i + 1) * (j + 1) > nbCells)) - return value[i * cols + j]; - else throw runtime_error("Error: PatchMatrix::get() out of range!\n"); - return 0; + if (i >= cols || j >= rows) + throw runtime_error("Error: PatchMatrix::get() out of range!\n"); + else return value[i * cols + j]; } int getNbCells() { return nbCells; }; /** Sets element at row i and column j to value val **/ void set(unsigned int i, unsigned int j, double val) { - if (i * j < nbCells) - value[i * cols + j] = val; - else throw runtime_error("Error: PatchMatrix::set() out of range!\n"); + if (i >= cols || j >= rows) + throw runtime_error("Error: PatchMatrix::set() out of range!\n"); + else value[i * cols + j] = val; } /** Assigns a value to all elements of the matrix. */ diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index 759440b..79b154d 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -169,14 +169,24 @@ void testNeutralStats() { assert(pNeutralStatistics->getHo() == 1.0); } - // If two sampled pops have zero allele in common, Fst is 1 - // - global Fst - // - per-locus Fst - // - pairwise per-patch Fst + // If two sampled pops are monomorphic for different alleles, + // then Fst is 1 { + // Patch setup + const int nbPatches = 2; + const int nbIndsPerPop = 2; + // Genetic setup + const int genomeSz = 2; + const bool isDiploid{ true }; + const set genePositions = { 0, 1 }; + const float maxAlleleVal = 1; + unsigned char alleleValPopA = char(0); + unsigned char alleleValPopB = char(1); + auto popAGenotype = createTestNeutralGenotype(genomeSz, true, alleleValPopA, alleleValPopA); + auto popBGenotype = createTestNeutralGenotype(genomeSz, true, alleleValPopB, alleleValPopB); + // Create two-patches landscape Landscape* pLandscape = new Landscape; - const int nbPatches = 2; vector patches(nbPatches); vector cells(nbPatches); set patchList; @@ -189,8 +199,7 @@ void testNeutralStats() { const string indSampling = "all"; const set stgToSample = { 1 }; - // Create genetic structure - const int genomeSz = 2; + // Create species trait structure Species* pSpecies = new Species(); pSpecies->setDemogr(createDefaultDiploidDemogrParams()); pSpecies->setGeneticParameters( @@ -202,36 +211,26 @@ void testNeutralStats() { stgToSample, 1 ); - const set genePositions = { 0, 1 }; const int nbLoci = genePositions.size(); - const bool isDiploid{ true }; - const float maxAlleleVal = 255; // highly unlikely that same value sampled twice SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); pSpecies->addTrait(TraitType::NEUTRAL, *spTr); - const int nbIndsPerPop = 2; - unsigned char alleleValPopA = char(0); - unsigned char alleleValPopB = char(1); - auto popAGenotype = createTestNeutralGenotype(genomeSz, true, alleleValPopA, alleleValPopA); - auto popBGenotype = createTestNeutralGenotype(genomeSz, true, alleleValPopB, alleleValPopB); - vector< - map> - > genotypes = { popAGenotype, popBGenotype }; - // Initialise populations + vector>> genotypes = { popAGenotype, popBGenotype }; + const int indStg = 1; for (int p = 0; p < patches.size(); p++) { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual ind = Individual(cells[p], patches[p], 0, 0, 0, 0.0, false, 1); - ind.setUpGenes(pSpecies, 1.0); - ind.overrideGenotype(NEUTRAL, genotypes[p]); - pPop->recruit(&ind); + Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + pInd->setUpGenes(pSpecies, 1.0); + pInd->overrideGenotype(NEUTRAL, genotypes[p]); + pPop->recruit(pInd); } - pPop->sampleIndsWithoutReplacement(indSampling, stgToSample); - } // do individuals still exist? + pPop->sampleIndsWithoutReplacement(indSampling, { indStg }); + } - // Calculate heterozygosity + // Compute auto pNeutralStatistics = make_unique(nbPatches, nbLoci); pNeutralStatistics->updateAllNeutralTables( pSpecies, @@ -247,7 +246,16 @@ void testNeutralStats() { pSpecies, pLandscape ); - // assert(pNeutralStatistics->getFstWC() == 0.4); + assert(pNeutralStatistics->getFstWC() == 1.0); + + pNeutralStatistics->calcPairwiseWeightedFst( + patchList, + nbIndsPerPop* patchList.size(), + nbLoci, + pSpecies, + pLandscape + ); + assert(pNeutralStatistics->getPairwiseFst(0, 1) == 0.0); } } From ae5ae91e7f630e197012c819b41cdbdc044b30d2 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 27 Aug 2024 11:00:24 +0100 Subject: [PATCH 218/332] Fst for monomorphic pops is correct, fix #44 --- unit_tests/testNeutralStats.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index 79b154d..2769b01 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -230,14 +230,14 @@ void testNeutralStats() { pPop->sampleIndsWithoutReplacement(indSampling, { indStg }); } - // Compute + // Compute F-stats auto pNeutralStatistics = make_unique(nbPatches, nbLoci); pNeutralStatistics->updateAllNeutralTables( pSpecies, pLandscape, patchList ); - const int maxNbNeutralAlleles = static_cast(maxAlleleVal); + const int maxNbNeutralAlleles = static_cast(maxAlleleVal) + 1; pNeutralStatistics->calculateFstatWC( patchList, nbIndsPerPop * patchList.size(), From 1490006e58c4134e8d3eca5ccb714a10baceb20c Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 27 Aug 2024 11:59:06 +0100 Subject: [PATCH 219/332] fst is zero when it cannot be computed, fix #46 --- unit_tests/testNeutralStats.cpp | 193 ++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index 2769b01..59b7ba7 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -169,6 +169,199 @@ void testNeutralStats() { assert(pNeutralStatistics->getHo() == 1.0); } + // If the sample is too small, Fst evaluates to zero + // More importantly, the neutral stats module still runs without error + { + // 1 - if there is zero population in the sample + { + // Patch setup + const int nbPatches = 2; + + // Create two-patches landscape + Landscape* pLandscape = new Landscape; + vector patches(nbPatches); + vector cells(nbPatches); + set patchList; + for (int i = 0; i < nbPatches; i++) { + patches[i] = pLandscape->newPatch(i); + cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + patches[i]->addCell(cells[i], 0, 0); + patchList.insert(patches[i]->getPatchNum()); + } + // Create species trait structure + Species* pSpecies = new Species(); + const bool isDiploid = true; + const set genePositions = { 0 }; + const float maxAlleleVal = 0; + SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); + pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + + // Oops, no populations in patches + + // Compute F-stats + const int nbLoci = 0; + auto pNeutralStatistics = make_unique(nbPatches, nbLoci); + pNeutralStatistics->updateAllNeutralTables( + pSpecies, + pLandscape, + patchList + ); + const int maxNbNeutralAlleles = 0; + pNeutralStatistics->calculateFstatWC( + patchList, + 0, + nbLoci, + maxNbNeutralAlleles, + pSpecies, + pLandscape + ); + assert(pNeutralStatistics->getFstWC() == 0.0); + } // end case 1 - zero pop in sample + + // 2 - If there is only one population in the sample + { + // Patch setup + const int nbPatches = 2; + const int nbPops = nbPatches - 1; // oops, 1 population is missing + const int nbIndsPerPop = 5; + // Genetic setup + const int genomeSz = 2; + const bool isDiploid{ true }; + const set genePositions = { 0, 1 }; + const float maxAlleleVal = 0; + + // Create two-patches landscape + Landscape* pLandscape = new Landscape; + vector patches(nbPatches); + vector cells(nbPatches); + set patchList; + for (int i = 0; i < nbPatches; i++) { + patches[i] = pLandscape->newPatch(i); + cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + patches[i]->addCell(cells[i], 0, 0); + patchList.insert(patches[i]->getPatchNum()); + } + const string indSampling = "all"; + const set stgToSample = { 1 }; + + // Create species trait structure + Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefaultDiploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + patchList, + indSampling, + stgToSample, + 1 + ); + const int nbLoci = genePositions.size(); + SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); + pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + + // Initialise populations + const int indStg = 1; + for (int p = 0; p < nbPops; p++) { + Population* pPop = new Population(pSpecies, patches[p], 0, 1); + // create individuals and add to pop + for (int i = 0; i < nbIndsPerPop; i++) { + Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + pInd->setUpGenes(pSpecies, 1.0); + pPop->recruit(pInd); + } + pPop->sampleIndsWithoutReplacement(indSampling, { indStg }); + } + + // Compute F-stats + auto pNeutralStatistics = make_unique(nbPatches, nbLoci); + pNeutralStatistics->updateAllNeutralTables( + pSpecies, + pLandscape, + patchList + ); + const int maxNbNeutralAlleles = static_cast(maxAlleleVal) + 1; + pNeutralStatistics->calculateFstatWC( + patchList, + nbIndsPerPop * patchList.size(), + nbLoci, + maxNbNeutralAlleles, + pSpecies, + pLandscape + ); + assert(pNeutralStatistics->getFstWC() == 0.0); + } // end case 2, only one population in sample + + // 3 - Two empty populations + { + // Patch setup + const int nbPatches = 2; + const int nbIndsPerPop = 0; // oops + + // Genetic setup + const int genomeSz = 2; + const bool isDiploid{ true }; + const set genePositions = { 0, 1 }; + const float maxAlleleVal = 0; + + // Create two-patches landscape + Landscape* pLandscape = new Landscape; + vector patches(nbPatches); + vector cells(nbPatches); + set patchList; + for (int i = 0; i < nbPatches; i++) { + patches[i] = pLandscape->newPatch(i); + cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + patches[i]->addCell(cells[i], 0, 0); + patchList.insert(patches[i]->getPatchNum()); + } + const string indSampling = "all"; + const set stgToSample = { 1 }; + + // Create species trait structure + Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefaultDiploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + patchList, + indSampling, + stgToSample, + 1 + ); + const int nbLoci = genePositions.size(); + SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); + pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + + // Initialise populations + const int indStg = 1; + for (int p = 0; p < nbPatches; p++) { + Population* pPop = new Population(pSpecies, patches[p], nbIndsPerPop, 1); + // create individuals and add to pop + pPop->sampleIndsWithoutReplacement(indSampling, { indStg }); + } + + // Compute F-stats + auto pNeutralStatistics = make_unique(nbPatches, nbLoci); + pNeutralStatistics->updateAllNeutralTables( + pSpecies, + pLandscape, + patchList + ); + const int maxNbNeutralAlleles = static_cast(maxAlleleVal) + 1; + pNeutralStatistics->calculateFstatWC( + patchList, + nbIndsPerPop * patchList.size(), + nbLoci, + maxNbNeutralAlleles, + pSpecies, + pLandscape + ); + assert(pNeutralStatistics->getFstWC() == 0.0); + } + } + // If two sampled pops are monomorphic for different alleles, // then Fst is 1 { From c98221bf6a22713e040164e768be46efee202edf Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 27 Aug 2024 14:14:00 +0100 Subject: [PATCH 220/332] fix incorrect sample size --- NeutralStatsManager.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index e506a7c..3ffff0a 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -280,22 +280,21 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int double sumWeights = 0; double nBar, nC, inverseNbar; unsigned int nbPops = 0; - const int ploidy = pSpecies->isDiploid() ? 2 : 1; - const int totalSampleSize = nbSampledIndsInComm * ploidy; // total nb of alleles + const int totalSampleSize = nbSampledIndsInComm; // r * n_bar for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop != 0) { - int popSampleSize = pPop->sampleSize() * ploidy; + int popSampleSize = pPop->sampleSize(); // n_i if (popSampleSize > 0) { nbPops++; - sumWeights += static_cast(popSampleSize * popSampleSize) / totalSampleSize; + sumWeights += static_cast(popSampleSize * popSampleSize) / totalSampleSize; // sum(n_i^2/rn_bar) } } } - nbExtantPops = nbPops; + nbExtantPops = nbPops; // r totalNbSampledInds = nbSampledIndsInComm; if (nbPops > 1) { @@ -325,7 +324,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int if (pPop != 0) { var = pPop->getAlleleFrequency(thisLocus, allele) - pBar; var *= var; - s2 += var * pPop->sampleSize() * ploidy; + s2 += var * pPop->sampleSize(); hBar += pPop->getHeteroTally(thisLocus, allele); // n_i * h_i } } //end for pop From 2b6263a3fc5fbc8c09ace827604e773c24e1b903 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 27 Aug 2024 14:14:38 +0100 Subject: [PATCH 221/332] calculation fits weir and cockerham expectation, fix #41 --- unit_tests/testNeutralStats.cpp | 100 ++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index 59b7ba7..34f8b04 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -450,6 +450,106 @@ void testNeutralStats() { ); assert(pNeutralStatistics->getPairwiseFst(0, 1) == 0.0); } + + // Fst calculation is correct for an ordinary sample + { + // Two 10-individual pops, + // 1 tri-allelic locus + + // Patch setup + const int nbPatches = 2; + const int nbIndsPerPop = 10; + + // Genetic setup + const int genomeSz = 1; + const bool isDiploid{ true }; + const set genePositions = { 0 }; + const float maxAlleleVal = 2; + unsigned char alleleA = char(0); + unsigned char alleleB = char(1); + unsigned char alleleC = char(2); + // Create genotypes + auto genotypeAA = createTestNeutralGenotype(genomeSz, true, alleleA, alleleA); + auto genotypeAB = createTestNeutralGenotype(genomeSz, true, alleleA, alleleB); + auto genotypeAC = createTestNeutralGenotype(genomeSz, true, alleleA, alleleC); + auto genotypeBB = createTestNeutralGenotype(genomeSz, true, alleleB, alleleB); + auto genotypeBC = createTestNeutralGenotype(genomeSz, true, alleleB, alleleC); + auto genotypeCC = createTestNeutralGenotype(genomeSz, true, alleleC, alleleC); + vector>>> genotypeList = { + { // Genotypes of population 1 + genotypeAA, genotypeAA, genotypeAB, genotypeAB, genotypeAB, + genotypeAB, genotypeAC, genotypeAC, genotypeBB, genotypeCC + }, + { // Genotypes of population 2 + genotypeAA, genotypeAB, genotypeAC, genotypeBB, genotypeBC, + genotypeBC, genotypeBC, genotypeBC, genotypeCC, genotypeCC + } + }; + + // Create two-patches landscape + Landscape* pLandscape = new Landscape; + vector patches(nbPatches); + vector cells(nbPatches); + set patchList; + for (int i = 0; i < nbPatches; i++) { + patches[i] = pLandscape->newPatch(i); + cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + patches[i]->addCell(cells[i], 0, 0); + patchList.insert(patches[i]->getPatchNum()); + } + const string indSampling = "all"; + const set stgToSample = { 1 }; + + // Create species trait structure + Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefaultDiploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + patchList, + indSampling, + stgToSample, + 1 + ); + const int nbLoci = genePositions.size(); + SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); + pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + + // Initialise populations + const int indStg = 1; + for (int p = 0; p < patches.size(); p++) { + Population* pPop = new Population(pSpecies, patches[p], 0, 1); + // create individuals and add to pop + for (int i = 0; i < nbIndsPerPop; i++) { + Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + pInd->setUpGenes(pSpecies, 1.0); + pInd->overrideGenotype(NEUTRAL, genotypeList[p][i]); + pPop->recruit(pInd); + } + pPop->sampleIndsWithoutReplacement(indSampling, { indStg }); + } + + // Compute F-stats + auto pNeutralStatistics = make_unique(nbPatches, nbLoci); + pNeutralStatistics->updateAllNeutralTables( + pSpecies, + pLandscape, + patchList + ); + const int maxNbNeutralAlleles = static_cast(maxAlleleVal) + 1; + pNeutralStatistics->calculateFstatWC( + patchList, + nbIndsPerPop * patchList.size(), + nbLoci, + maxNbNeutralAlleles, + pSpecies, + pLandscape + ); + const double expectedFst = 0.0583; // calculated by hand from Weir and Cockerham 1984 + double calcError = abs(pNeutralStatistics->getFstWC() - expectedFst); + assert(calcError < 0.0001); + } } #endif //RSDEBUG \ No newline at end of file From 0d6a0dc372b0866978f7e5f37f64c5d33abe8526 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 27 Aug 2024 14:59:11 +0100 Subject: [PATCH 222/332] solution for test var within vs between, fix #68 #69 --- unit_tests/testNeutralStats.cpp | 182 ++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index 34f8b04..ac25228 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -451,6 +451,188 @@ void testNeutralStats() { assert(pNeutralStatistics->getPairwiseFst(0, 1) == 0.0); } + // In strictly homozygote samples: + // 1. Fis = 1 (maximum inbreeding) + // 2. The sign of the Fst depends on the ratio of variation within vs between populations + { + // Case 1/2: variation within > between + // Within: frequencies of allele A and B are quite different + // Between: no variation + { + // Patch setup + const int nbPatches = 2; + const int nbIndsPerPop = 10; + // Genetic setup + const int genomeSz = 1; + const bool isDiploid{ true }; + const set genePositions = { 0 }; + const float maxAlleleVal = 1; + unsigned char alleleValPopA = char(0); + unsigned char alleleValPopB = char(1); + const auto genotypeAA = createTestNeutralGenotype(genomeSz, true, alleleValPopA, alleleValPopA); + const auto genotypeBB = createTestNeutralGenotype(genomeSz, true, alleleValPopB, alleleValPopB); + vector>> genotypes = { + // 8 AA, 2 BB (no heterozygotes) + genotypeAA, genotypeAA, genotypeAA, genotypeAA, genotypeAA, + genotypeAA, genotypeAA, genotypeAA, genotypeBB, genotypeBB + }; + + // Create two-patches landscape + Landscape* pLandscape = new Landscape; + vector patches(nbPatches); + vector cells(nbPatches); + set patchList; + for (int i = 0; i < nbPatches; i++) { + patches[i] = pLandscape->newPatch(i); + cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + patches[i]->addCell(cells[i], 0, 0); + patchList.insert(patches[i]->getPatchNum()); + } + const string indSampling = "all"; + const set stgToSample = { 1 }; + + // Create species trait structure + Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefaultDiploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + patchList, + indSampling, + stgToSample, + 1 + ); + const int nbLoci = genePositions.size(); + SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); + pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + + // Initialise populations + const int indStg = 1; + for (int p = 0; p < patches.size(); p++) { + Population* pPop = new Population(pSpecies, patches[p], 0, 1); + // create individuals and add to pop + for (int i = 0; i < nbIndsPerPop; i++) { + Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + pInd->setUpGenes(pSpecies, 1.0); + pInd->overrideGenotype(NEUTRAL, genotypes[i]); + pPop->recruit(pInd); + } + pPop->sampleIndsWithoutReplacement(indSampling, { indStg }); + } + + // Compute F-stats + auto pNeutralStatistics = make_unique(nbPatches, nbLoci); + pNeutralStatistics->updateAllNeutralTables( + pSpecies, + pLandscape, + patchList + ); + const int maxNbNeutralAlleles = static_cast(maxAlleleVal) + 1; + pNeutralStatistics->calculateFstatWC( + patchList, + nbIndsPerPop * patchList.size(), + nbLoci, + maxNbNeutralAlleles, + pSpecies, + pLandscape + ); + assert(pNeutralStatistics->getFstWC() < 0.0); + assert(pNeutralStatistics->getFisWC() == 1.0); + } + + // Case 2/2: variation within < between + // Within: no variation for pop1, same allelic frequencies + // Between: larger variation + { + // Patch setup + const int nbPatches = 2; + const int nbIndsPerPop = 10; + // Genetic setup + const int genomeSz = 1; + const bool isDiploid{ true }; + const set genePositions = { 0 }; + const float maxAlleleVal = 1; + unsigned char alleleValPopA = char(0); + unsigned char alleleValPopB = char(1); + const auto genotypeAA = createTestNeutralGenotype(genomeSz, true, alleleValPopA, alleleValPopA); + const auto genotypeBB = createTestNeutralGenotype(genomeSz, true, alleleValPopB, alleleValPopB); + vector>>> genotypeList = { + { // Pop 1: 5 AA, 5 BB (no heterozygotes) + genotypeAA, genotypeAA, genotypeAA, genotypeAA, genotypeAA, + genotypeBB, genotypeBB, genotypeBB, genotypeBB, genotypeBB + }, + { // Pop 2: 8 AA, 2 BB (no heterozygotes) + genotypeAA, genotypeAA, genotypeAA, genotypeAA, genotypeAA, + genotypeAA, genotypeAA, genotypeAA, genotypeBB, genotypeBB + } + }; + + // Create two-patches landscape + Landscape* pLandscape = new Landscape; + vector patches(nbPatches); + vector cells(nbPatches); + set patchList; + for (int i = 0; i < nbPatches; i++) { + patches[i] = pLandscape->newPatch(i); + cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + patches[i]->addCell(cells[i], 0, 0); + patchList.insert(patches[i]->getPatchNum()); + } + const string indSampling = "all"; + const set stgToSample = { 1 }; + + // Create species trait structure + Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefaultDiploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + patchList, + indSampling, + stgToSample, + 1 + ); + const int nbLoci = genePositions.size(); + SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); + pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + + // Initialise populations + const int indStg = 1; + for (int p = 0; p < patches.size(); p++) { + Population* pPop = new Population(pSpecies, patches[p], 0, 1); + // create individuals and add to pop + for (int i = 0; i < nbIndsPerPop; i++) { + Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + pInd->setUpGenes(pSpecies, 1.0); + pInd->overrideGenotype(NEUTRAL, genotypeList[p][i]); + pPop->recruit(pInd); + } + pPop->sampleIndsWithoutReplacement(indSampling, { indStg }); + } + + // Compute F-stats + auto pNeutralStatistics = make_unique(nbPatches, nbLoci); + pNeutralStatistics->updateAllNeutralTables( + pSpecies, + pLandscape, + patchList + ); + const int maxNbNeutralAlleles = static_cast(maxAlleleVal) + 1; + pNeutralStatistics->calculateFstatWC( + patchList, + nbIndsPerPop * patchList.size(), + nbLoci, + maxNbNeutralAlleles, + pSpecies, + pLandscape + ); + assert(pNeutralStatistics->getFstWC() > 0.0); + assert(pNeutralStatistics->getFisWC() == 1.0); + } + } + // Fst calculation is correct for an ordinary sample { // Two 10-individual pops, From 54c2330aebb95b187d7d5513caba7f5e51ded0f3 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 27 Aug 2024 15:07:27 +0100 Subject: [PATCH 223/332] test all heterozygotes case, fix #71 #68 --- unit_tests/testNeutralStats.cpp | 90 +++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 5 deletions(-) diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index ac25228..4aefe2d 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -536,9 +536,9 @@ void testNeutralStats() { maxNbNeutralAlleles, pSpecies, pLandscape - ); - assert(pNeutralStatistics->getFstWC() < 0.0); - assert(pNeutralStatistics->getFisWC() == 1.0); + ); + assert(pNeutralStatistics->getFstWC() < 0.0); + assert(pNeutralStatistics->getFisWC() == 1.0); } // Case 2/2: variation within < between @@ -561,7 +561,7 @@ void testNeutralStats() { { // Pop 1: 5 AA, 5 BB (no heterozygotes) genotypeAA, genotypeAA, genotypeAA, genotypeAA, genotypeAA, genotypeBB, genotypeBB, genotypeBB, genotypeBB, genotypeBB - }, + }, { // Pop 2: 8 AA, 2 BB (no heterozygotes) genotypeAA, genotypeAA, genotypeAA, genotypeAA, genotypeAA, genotypeAA, genotypeAA, genotypeAA, genotypeBB, genotypeBB @@ -622,7 +622,7 @@ void testNeutralStats() { const int maxNbNeutralAlleles = static_cast(maxAlleleVal) + 1; pNeutralStatistics->calculateFstatWC( patchList, - nbIndsPerPop * patchList.size(), + nbIndsPerPop* patchList.size(), nbLoci, maxNbNeutralAlleles, pSpecies, @@ -633,6 +633,86 @@ void testNeutralStats() { } } + // In a strictly heterozygote sample, Fis = -1 + // + if there is no variation between individuals, Fst = 0 + { + // Patch setup + const int nbPatches = 2; + const int nbIndsPerPop = 10; + // Genetic setup + const int genomeSz = 1; + const bool isDiploid{ true }; + const set genePositions = { 0 }; + const float maxAlleleVal = 1; + unsigned char alleleValPopA = char(0); + unsigned char alleleValPopB = char(1); + const auto genotypeAB = createTestNeutralGenotype(genomeSz, true, alleleValPopA, alleleValPopB); + // all individuals have genotype AB + + // Create two-patches landscape + Landscape* pLandscape = new Landscape; + vector patches(nbPatches); + vector cells(nbPatches); + set patchList; + for (int i = 0; i < nbPatches; i++) { + patches[i] = pLandscape->newPatch(i); + cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + patches[i]->addCell(cells[i], 0, 0); + patchList.insert(patches[i]->getPatchNum()); + } + const string indSampling = "all"; + const set stgToSample = { 1 }; + + // Create species trait structure + Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefaultDiploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + patchList, + indSampling, + stgToSample, + 1 + ); + const int nbLoci = genePositions.size(); + SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); + pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + + // Initialise populations + const int indStg = 1; + for (int p = 0; p < patches.size(); p++) { + Population* pPop = new Population(pSpecies, patches[p], 0, 1); + // create individuals and add to pop + for (int i = 0; i < nbIndsPerPop; i++) { + Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + pInd->setUpGenes(pSpecies, 1.0); + pInd->overrideGenotype(NEUTRAL, genotypeAB); + pPop->recruit(pInd); + } + pPop->sampleIndsWithoutReplacement(indSampling, { indStg }); + } + + // Compute F-stats + auto pNeutralStatistics = make_unique(nbPatches, nbLoci); + pNeutralStatistics->updateAllNeutralTables( + pSpecies, + pLandscape, + patchList + ); + const int maxNbNeutralAlleles = static_cast(maxAlleleVal) + 1; + pNeutralStatistics->calculateFstatWC( + patchList, + nbIndsPerPop* patchList.size(), + nbLoci, + maxNbNeutralAlleles, + pSpecies, + pLandscape + ); + assert(pNeutralStatistics->getFstWC() == 0.0); + assert(pNeutralStatistics->getFisWC() == -1.0); + } + // Fst calculation is correct for an ordinary sample { // Two 10-individual pops, From e9dbab2df584739cd2e4352a292d8c1d88d2322d Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 27 Aug 2024 15:39:22 +0100 Subject: [PATCH 224/332] assert correct nb of individuals is sampled, fix #53 --- unit_tests/testNeutralStats.cpp | 56 ++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index 4aefe2d..a5b17a9 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -169,6 +169,60 @@ void testNeutralStats() { assert(pNeutralStatistics->getHo() == 1.0); } + // The correct number of individuals is sampled + { + const int nbIndsPopA = 15; + const int nbIndsPopB = 11; + const string indSampling = "13"; + const set stgToSample = { 1 }; + + // Patch setup + const int nbPatches = 2; + // Genetic setup + const int genomeSz = 2; + const bool isDiploid{ true }; + const set genePositions = { 0, 1 }; + const float maxAlleleVal = 1; + + // Create two-patches landscape + Landscape* pLandscape = new Landscape; + vector patches(nbPatches); + vector cells(nbPatches); + set patchList; + for (int i = 0; i < nbPatches; i++) { + patches[i] = pLandscape->newPatch(i); + cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + patches[i]->addCell(cells[i], 0, 0); + patchList.insert(patches[i]->getPatchNum()); + } + + // Create species trait structure + Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefaultDiploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + patchList, + indSampling, + stgToSample, + 1 + ); + const int nbLoci = genePositions.size(); + SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); + pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + + // Initialise populations + const int indStg = 1; + Population* pPopA = new Population(pSpecies, patches[0], nbIndsPopA, 1); + Population* pPopB = new Population(pSpecies, patches[1], nbIndsPopB, 1); + pPopA->sampleIndsWithoutReplacement(indSampling, { indStg }); + pPopB->sampleIndsWithoutReplacement(indSampling, { indStg }); + + assert(pPopA->sampleSize() == stoi(indSampling)); // the correct nb of individuals has been sampled + assert(pPopB->sampleSize() == nbIndsPopB); // too small; all individuals have been sampled + } + // If the sample is too small, Fst evaluates to zero // More importantly, the neutral stats module still runs without error { @@ -711,7 +765,7 @@ void testNeutralStats() { ); assert(pNeutralStatistics->getFstWC() == 0.0); assert(pNeutralStatistics->getFisWC() == -1.0); - } + } // Fst calculation is correct for an ordinary sample { From 7ee8cfa5442528b6d5e2375bd2954be052ae58f4 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 28 Aug 2024 13:49:55 +0100 Subject: [PATCH 225/332] unlucky draw --- unit_tests/testNeutralStats.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index a5b17a9..3928c49 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -146,7 +146,7 @@ void testNeutralStats() { stgToSample, 1 ); - const set genePositions = { 0, 1, 3 }; // arbitrary + const set genePositions = { 0, 2 }; // arbitrary const bool isDiploid{ true }; const float maxAlleleVal = 255; // highly unlikely that same value sampled twice SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); From b147de3220bb53c0deb8a8ce804385bf25183884 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 28 Aug 2024 13:50:32 +0100 Subject: [PATCH 226/332] fix bugged haploid GeneticFitness trait --- GeneticFitnessTrait.cpp | 5 +++-- Individual.cpp | 4 ++-- Population.cpp | 2 +- SubCommunity.cpp | 18 ------------------ 4 files changed, 6 insertions(+), 23 deletions(-) diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index cd266c5..2de095f 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -366,12 +366,13 @@ float GeneticFitnessTrait::express() { for (auto const& [locus, pAllelePair] : genes) { - shared_ptr pAlleleA = pAllelePair[0] == 0 ? wildType : pAllelePair[0]; - shared_ptr pAlleleB = pAllelePair[1] == 0 ? wildType : pAllelePair[1]; + shared_ptr pAlleleA = pAllelePair[0] == 0 ? wildType : pAllelePair[0]; sA = pAlleleA->getAlleleValue(); hA = pAlleleA->getDominanceCoef(); + if (pSpeciesTrait->getPloidy() == 2) { + shared_ptr pAlleleB = pAllelePair[1] == 0 ? wildType : pAllelePair[1]; sB = pAlleleB->getAlleleValue(); hB = pAlleleB->getDominanceCoef(); } diff --git a/Individual.cpp b/Individual.cpp index aff3ed8..89022a9 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -188,9 +188,9 @@ void Individual::inherit(Species* pSpecies, const Individual* mother) { set recomPositions; //not used here cos haploid but need it for inherit function, not ideal int startingChromosome = 0; - const auto& motherTraits = getTraitTypes(); + const auto& spTraits = pSpecies->getTraitTypes(); - for (auto const& trait : motherTraits) + for (auto const& trait : spTraits) { const auto motherTrait = mother->getTrait(trait); auto newTrait = motherTrait->clone(); // shallow copy, pointer to species trait initialised and empty sequence diff --git a/Population.cpp b/Population.cpp index 5ebb46e..202f60d 100644 --- a/Population.cpp +++ b/Population.cpp @@ -683,7 +683,7 @@ void Population::reproduction(const float localK, const float envval, const int #endif if (pSpecies->getNTraits() > 0) { - newJuv->inheritTraits(pSpecies, inds[i], father, resol); + newJuv->inheritTraits(pSpecies, inds[i], resol); } if (!newJuv->isViable()) { diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 8408441..7d5bd4c 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -283,24 +283,6 @@ void SubCommunity::reproduction(int resol, float epsGlobal, short rasterType, bo popns[i]->fledge(); } } - /* - else { // patch in dynamic landscape has become unsuitable - // NB - THIS WILL NEED TO BE MADE SPECIES-SPECIFIC... - Species *pSpecies; - for (int i = 0; i < npops; i++) { // all populations - pSpecies = popns[i]->getSpecies(); - demogrParams dem = pSpecies->getDemogr(); - if (dem.stageStruct) { - stageParams sstruct = pSpecies->getStage(); - if (sstruct.disperseOnLoss) popns[i]->allEmigrate(); - else popns[i]->extirpate(); - } - else { // non-stage-structured species is destroyed - popns[i]->extirpate(); - } - } - } - */ } void SubCommunity::emigration(void) From cc68505fd5319ada9203b5fc9a0229fb7f5fb461 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 28 Aug 2024 13:58:11 +0100 Subject: [PATCH 227/332] Offspring survival scales with mutation rate, fix #54 --- Model.cpp | 16 +------- Population.cpp | 66 +++++++++++++++++++++++++++++---- Species.cpp | 28 ++++++++++++++ Species.h | 6 +++ unit_tests/testNeutralStats.cpp | 26 +------------ 5 files changed, 95 insertions(+), 47 deletions(-) diff --git a/Model.cpp b/Model.cpp index 17ec8e7..b63ca8b 100644 --- a/Model.cpp +++ b/Model.cpp @@ -48,15 +48,6 @@ int RunModel(Landscape* pLandscape, int seqsim) simParams sim = paramsSim->getSim(); simView v = paramsSim->getViews(); -#if RSDEBUG - landPix p = pLandscape->getLandPix(); - DEBUGLOG << "RunModel(): reps=" << sim.reps - << " ppLand.nHab=" << ppLand.nHab - << " p.pix=" << p.pix - << endl; - DEBUGLOG << endl; -#endif - if (!ppLand.generated) { if (!ppLand.patchModel) { // cell-based landscape // create patches for suitable cells, adding unsuitable cells to the matrix @@ -124,13 +115,8 @@ int RunModel(Landscape* pLandscape, int seqsim) if (pComm != 0) delete pComm; // generate new cell-based landscape pLandscape->resetLand(); -#if RSDEBUG - DEBUGLOG << "RunModel(): finished resetting landscape" << endl << endl; -#endif pLandscape->generatePatches(); -#if RSDEBUG - DEBUGLOG << endl << "RunModel(): finished generating patches" << endl; -#endif + pComm = new Community(pLandscape); // set up community // set up a sub-community associated with each patch (incl. the matrix) pLandscape->updateCarryingCapacity(pSpecies, 0, 0); diff --git a/Population.cpp b/Population.cpp index 202f60d..b836c94 100644 --- a/Population.cpp +++ b/Population.cpp @@ -842,15 +842,9 @@ void Population::sampleIndsWithoutReplacement(string strNbToSample, const set tempSampledInds; // Sample n individuals across selected stages sample(stagedInds.begin(), stagedInds.end(), std::back_inserter(sampledInds), nbToSample, rng); - // Copy from vector to set - //std::copy(tempSampledInds.begin(), tempSampledInds.end(), std::inserter(sampledInds, sampledInds.end())); } -#if RSDEBUG - assert(sampledInds.size() <= inds.size()); -#endif } } @@ -1902,6 +1896,64 @@ void Population::outputGeneValues(ofstream& ofsGenes, const int& yr, const int& #if RSDEBUG void testPopulation() { - // test population... + // Given a genetic load trait, offspring + // Survival is (inversely) proportional to the mutation rate + { + vector mutationRates = { 0.0, 0.05, 0.1 }; + vector survivingInds; + const int initialNbInds = 1000; + const float localK = 10000; // not limiting + + // Simple genetic layout + const bool isDiploid{ false }; // haploid suffices + const int genomeSz = 1; + const set genePositions = { 0 }; + + // All mutations are dominant lethal + const map mutParams{ + pair{GenParamType::MIN, 1}, + pair{GenParamType::MAX, 1} + }; + const map domParams{ + pair{GenParamType::MIN, 1}, + pair{GenParamType::MAX, 1} + }; + + for (float mutationRate : mutationRates) { + Landscape* pLandscape = new Landscape; + Patch* pPatch = pLandscape->newPatch(1); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + pPatch->addCell(pCell, 0, 0); + + Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefaultHaploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + { }, "none", { }, 0 // no sampling + ); + SpeciesTrait* spTr = new SpeciesTrait( + TraitType::GENETIC_LOAD, + sex_t::NA, + genePositions, + ExpressionType::MULTIPLICATIVE, + DistributionType::NONE, map{}, + DistributionType::UNIFORM, domParams, + true, // isInherited + mutationRate, // mutation rate + DistributionType::UNIFORM, mutParams, + isDiploid ? 2 : 1, + false + ); + pSpecies->addTrait(TraitType::GENETIC_LOAD, *spTr); + + Population pop = Population(pSpecies, pPatch, initialNbInds, 1); + pop.reproduction(localK, 1, 1); // juveniles are checked for viability at birth + pop.fledge(); // non-overlapping: adults are replaced with juveniles + survivingInds.push_back(pop.getNInds()); + } + assert(survivingInds[0] > survivingInds[1] && survivingInds[1] > survivingInds[2]); + } } #endif // RSDEBUG diff --git a/Species.cpp b/Species.cpp index 1e5a75f..96e207c 100644 --- a/Species.cpp +++ b/Species.cpp @@ -791,3 +791,31 @@ void Species::setSamplePatchList(const set& samplePatchList) { //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- +#if RSDEBUG +// For testing purposes only + +demogrParams createDefaultHaploidDemogrParams() { + demogrParams d; + d.repType = 0; + d.repSeasons = 1; + d.stageStruct = false; + d.propMales = 0.0; + d.harem = 1.0; + d.bc = 1.0; + d.lambda = 2.0; + return d; +} + +demogrParams createDefaultDiploidDemogrParams() { + demogrParams d; + d.repType = 1; + d.repSeasons = 1; + d.stageStruct = false; + d.propMales = 0.5; + d.harem = 1.0; + d.bc = 1.0; + d.lambda = 2.0; + return d; +} + +#endif // RSDEBUG diff --git a/Species.h b/Species.h index 9e47725..5a82d1d 100644 --- a/Species.h +++ b/Species.h @@ -573,5 +573,11 @@ class Species { //--------------------------------------------------------------------------- +#if RSDEBUG +// For testing purposes only +demogrParams createDefaultHaploidDemogrParams(); +demogrParams createDefaultDiploidDemogrParams(); +#endif RSDEBUG + //--------------------------------------------------------------------------- #endif diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index 3928c49..d0bc458 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -2,30 +2,6 @@ #include "../Community.h" -demogrParams createDefltHaploidDemogrParams() { - demogrParams d; - d.repType = 0; - d.repSeasons = 1; - d.stageStruct = false; - d.propMales = 0.5; - d.harem = 1.0; - d.bc = 1.0; - d.lambda = 1.0; - return d; -} - -demogrParams createDefaultDiploidDemogrParams() { - demogrParams d; - d.repType = 1; - d.repSeasons = 1; - d.stageStruct = false; - d.propMales = 0.5; - d.harem = 1.0; - d.bc = 1.0; - d.lambda = 1.0; - return d; -} - void testNeutralStats() { // In haploid settings, Ho is always zero @@ -42,7 +18,7 @@ void testNeutralStats() { // Create genetic structure const int genomeSz = 4; Species* pSpecies = new Species(); - pSpecies->setDemogr(createDefltHaploidDemogrParams()); + pSpecies->setDemogr(createDefaultHaploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome genomeSz, From 95d4763b64b1640ed92cf697509076353db4e21a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 28 Aug 2024 15:29:16 +0100 Subject: [PATCH 228/332] number of emigrants scale with emig_0 mutation rate, fix #55 --- Community.cpp | 34 --------------------- Population.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 36 deletions(-) diff --git a/Community.cpp b/Community.cpp index ccf3662..0935edf 100644 --- a/Community.cpp +++ b/Community.cpp @@ -317,10 +317,6 @@ void Community::addManuallySelected(void) { landParams ppLand = pLandscape->getLandParams(); npatches = pLandscape->initCellCount(); // no. of patches/cells specified -#if RSDEBUG - DEBUGLOG << "Community::addManuallySelected(): this = " << this - << " npatches = " << npatches << endl; -#endif // identify sub-communities to be initialised if (ppLand.patchModel) { for (int i = 0; i < npatches; i++) { @@ -343,28 +339,12 @@ void Community::addManuallySelected(void) { pCell = pLandscape->findCell(initloc.x, initloc.y); if (pCell != 0) { // not no-data cell patch = pCell->getPatch(); -#if RSDEBUG - DEBUGLOG << "Community::initialise(): i = " << i - << " x = " << initloc.x << " y = " << initloc.y - << " pCell = " << pCell << " patch = " << patch - << endl; -#endif if (patch != 0) { pPatch = (Patch*)patch; subcomm = pPatch->getSubComm(); -#if RSDEBUG - DEBUGLOG << "Community::initialise(): i = " << i - << " pPatch = " << pPatch << " subcomm = " << subcomm - << endl; -#endif if (subcomm != 0) { pSubComm = (SubCommunity*)subcomm; pSubComm->setInitial(true); -#if RSDEBUG - DEBUGLOG << "Community::initialise(): i = " << i - << " pSubComm = " << pSubComm - << endl; -#endif } } } @@ -406,10 +386,6 @@ void Community::reproduction(int yr) landParams land = pLandscape->getLandParams(); envStochParams env = paramsStoch->getStoch(); int nsubcomms = (int)subComms.size(); -#if RSDEBUG - DEBUGLOG << "Community::reproduction(): this=" << this - << " nsubcomms=" << nsubcomms << endl; -#endif for (int i = 0; i < nsubcomms; i++) { // all sub-communities if (env.stoch) { @@ -419,24 +395,14 @@ void Community::reproduction(int yr) } subComms[i]->reproduction(land.resol, eps, land.rasterType, land.patchModel); } -#if RSDEBUG - DEBUGLOG << "Community::reproduction(): finished" << endl; -#endif } void Community::emigration(void) { int nsubcomms = static_cast(subComms.size()); -#if RSDEBUG - DEBUGLOG << "Community::emigration(): this=" << this - << " nsubcomms=" << nsubcomms << endl; -#endif for (int i = 0; i < nsubcomms; i++) { // all sub-communities subComms[i]->emigration(); } -#if RSDEBUG - DEBUGLOG << "Community::emigration(): finished" << endl; -#endif } #if RS_RCPP // included also SEASONAL diff --git a/Population.cpp b/Population.cpp index b836c94..71cb6d0 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1017,7 +1017,8 @@ disperser Population::extractDisperser(int ix) { disperser d = disperser(); indStats ind = inds[ix]->getStats(); if (ind.status == 1) { // emigrant - d.pInd = inds[ix]; d.yes = true; + d.pInd = inds[ix]; + d.yes = true; inds[ix] = 0; nInds[ind.stage][ind.sex]--; } @@ -1918,7 +1919,7 @@ void testPopulation() pair{GenParamType::MIN, 1}, pair{GenParamType::MAX, 1} }; - + for (float mutationRate : mutationRates) { Landscape* pLandscape = new Landscape; Patch* pPatch = pLandscape->newPatch(1); @@ -1955,5 +1956,81 @@ void testPopulation() } assert(survivingInds[0] > survivingInds[1] && survivingInds[1] > survivingInds[2]); } + + // Dispersal is proportional to the mutation rate + { + vector mutationRates = { 0.0, 0.05, 0.1 }; + vector emigratingInds; + const int initialNbInds = 1000; + const float localK = 10000; // not limiting + + // Simple genetic layout + const bool isDiploid{ false }; // haploid suffices + const int genomeSz = 1; + const set genePositions = { 0 }; + + // Wild-types nver emigrate, mutants always do + const map initParams{ + pair{GenParamType::MIN, 0}, + pair{GenParamType::MAX, 0} + }; + const map mutParams{ + pair{GenParamType::MIN, 1}, + pair{GenParamType::MAX, 1} + }; + + for (float mutationRate : mutationRates) { + Landscape* pLandscape = new Landscape; + Patch* pPatch = pLandscape->newPatch(1); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + pPatch->addCell(pCell, 0, 0); + + Species* pSpecies = new Species(); + emigRules emig; + emig.indVar = true; + emig.sexDep = false; + emig.densDep = false; + emig.stgDep = false; + pSpecies->setEmigRules(emig); + stageParams stg; + stg.nStages = 2; + pSpecies->setStage(stg); + pSpecies->setDemogr(createDefaultHaploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + { }, "none", { }, 0 // no sampling + ); + SpeciesTrait* spTr = new SpeciesTrait( + TraitType::E_D0, + sex_t::NA, + genePositions, + ExpressionType::ADDITIVE, + DistributionType::UNIFORM, initParams, + DistributionType::NONE, map{}, // no dominance + true, // isInherited + mutationRate, // mutation rate + DistributionType::UNIFORM, mutParams, + isDiploid ? 2 : 1, + false + ); + pSpecies->addTrait(TraitType::E_D0, *spTr); + + Population pop = Population(pSpecies, pPatch, initialNbInds, 1); + pop.reproduction(localK, 1, 1); + pop.fledge(); // replace initial pop with juveniles + pop.emigration(localK); // select and flag emigrants + int popSize = pop.totalPop(); + for (int i = 0; i < popSize; i++) { + pop.extractDisperser(i); // rm emigrants from pop + } + int nbEmigrating = popSize - pop.totalPop(); // diff is nb of emigrants + if (mutationRate == 0.0) + assert(nbEmigrating == 0); + emigratingInds.push_back(nbEmigrating); + } + assert(emigratingInds[0] < emigratingInds[1] && emigratingInds[1] < emigratingInds[2]); + } } #endif // RSDEBUG From edc34afd55a1857ea65780efff77c24361aa64d6 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 28 Aug 2024 15:34:38 +0100 Subject: [PATCH 229/332] move testPopulation to its own file --- CMakeLists.txt | 2 +- Main.cpp | 1 + Population.cpp | 142 --------------------------------- Population.h | 4 - unit_tests/testPopulation.cpp | 145 ++++++++++++++++++++++++++++++++++ 5 files changed, 147 insertions(+), 147 deletions(-) create mode 100644 unit_tests/testPopulation.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0caf9a8..daf71b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ if (NOT batchmode) # that is, RScore as a standalone # specify the C++ standard set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) - add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp "unit_tests/testIndividual.cpp" "unit_tests/testNeutralStats.cpp") + add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp "unit_tests/testIndividual.cpp" "unit_tests/testNeutralStats.cpp" "unit_tests/testPopulation.cpp") else() # that is, RScore compiled as library within RangeShifter_batch add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) endif() diff --git a/Main.cpp b/Main.cpp index cf35bdf..5bb63d2 100644 --- a/Main.cpp +++ b/Main.cpp @@ -43,6 +43,7 @@ using namespace std; void testIndividual(); void testNeutralStats(); +void testPopulation(); void run_unit_tests() { cout << "******* Unit test output *******" << endl; diff --git a/Population.cpp b/Population.cpp index 71cb6d0..ee08b7c 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1892,145 +1892,3 @@ void Population::outputGeneValues(ofstream& ofsGenes, const int& yr, const int& //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- - - -#if RSDEBUG -void testPopulation() -{ - // Given a genetic load trait, offspring - // Survival is (inversely) proportional to the mutation rate - { - vector mutationRates = { 0.0, 0.05, 0.1 }; - vector survivingInds; - const int initialNbInds = 1000; - const float localK = 10000; // not limiting - - // Simple genetic layout - const bool isDiploid{ false }; // haploid suffices - const int genomeSz = 1; - const set genePositions = { 0 }; - - // All mutations are dominant lethal - const map mutParams{ - pair{GenParamType::MIN, 1}, - pair{GenParamType::MAX, 1} - }; - const map domParams{ - pair{GenParamType::MIN, 1}, - pair{GenParamType::MAX, 1} - }; - - for (float mutationRate : mutationRates) { - Landscape* pLandscape = new Landscape; - Patch* pPatch = pLandscape->newPatch(1); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); - pPatch->addCell(pCell, 0, 0); - - Species* pSpecies = new Species(); - pSpecies->setDemogr(createDefaultHaploidDemogrParams()); - pSpecies->setGeneticParameters( - set{genomeSz - 1}, // single chromosome - genomeSz, - 0.0, // no recombination - { }, "none", { }, 0 // no sampling - ); - SpeciesTrait* spTr = new SpeciesTrait( - TraitType::GENETIC_LOAD, - sex_t::NA, - genePositions, - ExpressionType::MULTIPLICATIVE, - DistributionType::NONE, map{}, - DistributionType::UNIFORM, domParams, - true, // isInherited - mutationRate, // mutation rate - DistributionType::UNIFORM, mutParams, - isDiploid ? 2 : 1, - false - ); - pSpecies->addTrait(TraitType::GENETIC_LOAD, *spTr); - - Population pop = Population(pSpecies, pPatch, initialNbInds, 1); - pop.reproduction(localK, 1, 1); // juveniles are checked for viability at birth - pop.fledge(); // non-overlapping: adults are replaced with juveniles - survivingInds.push_back(pop.getNInds()); - } - assert(survivingInds[0] > survivingInds[1] && survivingInds[1] > survivingInds[2]); - } - - // Dispersal is proportional to the mutation rate - { - vector mutationRates = { 0.0, 0.05, 0.1 }; - vector emigratingInds; - const int initialNbInds = 1000; - const float localK = 10000; // not limiting - - // Simple genetic layout - const bool isDiploid{ false }; // haploid suffices - const int genomeSz = 1; - const set genePositions = { 0 }; - - // Wild-types nver emigrate, mutants always do - const map initParams{ - pair{GenParamType::MIN, 0}, - pair{GenParamType::MAX, 0} - }; - const map mutParams{ - pair{GenParamType::MIN, 1}, - pair{GenParamType::MAX, 1} - }; - - for (float mutationRate : mutationRates) { - Landscape* pLandscape = new Landscape; - Patch* pPatch = pLandscape->newPatch(1); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); - pPatch->addCell(pCell, 0, 0); - - Species* pSpecies = new Species(); - emigRules emig; - emig.indVar = true; - emig.sexDep = false; - emig.densDep = false; - emig.stgDep = false; - pSpecies->setEmigRules(emig); - stageParams stg; - stg.nStages = 2; - pSpecies->setStage(stg); - pSpecies->setDemogr(createDefaultHaploidDemogrParams()); - pSpecies->setGeneticParameters( - set{genomeSz - 1}, // single chromosome - genomeSz, - 0.0, // no recombination - { }, "none", { }, 0 // no sampling - ); - SpeciesTrait* spTr = new SpeciesTrait( - TraitType::E_D0, - sex_t::NA, - genePositions, - ExpressionType::ADDITIVE, - DistributionType::UNIFORM, initParams, - DistributionType::NONE, map{}, // no dominance - true, // isInherited - mutationRate, // mutation rate - DistributionType::UNIFORM, mutParams, - isDiploid ? 2 : 1, - false - ); - pSpecies->addTrait(TraitType::E_D0, *spTr); - - Population pop = Population(pSpecies, pPatch, initialNbInds, 1); - pop.reproduction(localK, 1, 1); - pop.fledge(); // replace initial pop with juveniles - pop.emigration(localK); // select and flag emigrants - int popSize = pop.totalPop(); - for (int i = 0; i < popSize; i++) { - pop.extractDisperser(i); // rm emigrants from pop - } - int nbEmigrating = popSize - pop.totalPop(); // diff is nb of emigrants - if (mutationRate == 0.0) - assert(nbEmigrating == 0); - emigratingInds.push_back(nbEmigrating); - } - assert(emigratingInds[0] < emigratingInds[1] && emigratingInds[1] < emigratingInds[2]); - } -} -#endif // RSDEBUG diff --git a/Population.h b/Population.h index 40cc4b3..ac978b3 100644 --- a/Population.h +++ b/Population.h @@ -262,10 +262,6 @@ extern RSrandom* pRandom; extern ofstream DEBUGLOG; #endif -#if RSDEBUG -void testPopulation(); -#endif - //--------------------------------------------------------------------------- #endif diff --git a/unit_tests/testPopulation.cpp b/unit_tests/testPopulation.cpp new file mode 100644 index 0000000..2ab9b1b --- /dev/null +++ b/unit_tests/testPopulation.cpp @@ -0,0 +1,145 @@ +#if RSDEBUG + +#include "../Individual.h" +#include "../Population.h" + +void testPopulation() +{ + // Given a genetic load trait, offspring + // Survival is (inversely) proportional to the mutation rate + { + vector mutationRates = { 0.0, 0.05, 0.1 }; + vector survivingInds; + const int initialNbInds = 1000; + const float localK = 10000; // not limiting + + // Simple genetic layout + const bool isDiploid{ false }; // haploid suffices + const int genomeSz = 1; + const set genePositions = { 0 }; + + // All mutations are dominant lethal + const map mutParams{ + pair{GenParamType::MIN, 1}, + pair{GenParamType::MAX, 1} + }; + const map domParams{ + pair{GenParamType::MIN, 1}, + pair{GenParamType::MAX, 1} + }; + + for (float mutationRate : mutationRates) { + Landscape* pLandscape = new Landscape; + Patch* pPatch = pLandscape->newPatch(1); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + pPatch->addCell(pCell, 0, 0); + + Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefaultHaploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + { }, "none", { }, 0 // no sampling + ); + SpeciesTrait* spTr = new SpeciesTrait( + TraitType::GENETIC_LOAD, + sex_t::NA, + genePositions, + ExpressionType::MULTIPLICATIVE, + DistributionType::NONE, map{}, + DistributionType::UNIFORM, domParams, + true, // isInherited + mutationRate, // mutation rate + DistributionType::UNIFORM, mutParams, + isDiploid ? 2 : 1, + false + ); + pSpecies->addTrait(TraitType::GENETIC_LOAD, *spTr); + + Population pop = Population(pSpecies, pPatch, initialNbInds, 1); + pop.reproduction(localK, 1, 1); // juveniles are checked for viability at birth + pop.fledge(); // non-overlapping: adults are replaced with juveniles + survivingInds.push_back(pop.getNInds()); + } + assert(survivingInds[0] > survivingInds[1] && survivingInds[1] > survivingInds[2]); + } + + // Dispersal is proportional to the mutation rate + { + vector mutationRates = { 0.0, 0.05, 0.1 }; + vector emigratingInds; + const int initialNbInds = 1000; + const float localK = 10000; // not limiting + + // Simple genetic layout + const bool isDiploid{ false }; // haploid suffices + const int genomeSz = 1; + const set genePositions = { 0 }; + + // Wild-types nver emigrate, mutants always do + const map initParams{ + pair{GenParamType::MIN, 0}, + pair{GenParamType::MAX, 0} + }; + const map mutParams{ + pair{GenParamType::MIN, 1}, + pair{GenParamType::MAX, 1} + }; + + for (float mutationRate : mutationRates) { + Landscape* pLandscape = new Landscape; + Patch* pPatch = pLandscape->newPatch(1); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + pPatch->addCell(pCell, 0, 0); + + Species* pSpecies = new Species(); + emigRules emig; + emig.indVar = true; + emig.sexDep = false; + emig.densDep = false; + emig.stgDep = false; + pSpecies->setEmigRules(emig); + stageParams stg; + stg.nStages = 2; + pSpecies->setStage(stg); + pSpecies->setDemogr(createDefaultHaploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + { }, "none", { }, 0 // no sampling + ); + SpeciesTrait* spTr = new SpeciesTrait( + TraitType::E_D0, + sex_t::NA, + genePositions, + ExpressionType::ADDITIVE, + DistributionType::UNIFORM, initParams, + DistributionType::NONE, map{}, // no dominance + true, // isInherited + mutationRate, // mutation rate + DistributionType::UNIFORM, mutParams, + isDiploid ? 2 : 1, + false + ); + pSpecies->addTrait(TraitType::E_D0, *spTr); + + Population pop = Population(pSpecies, pPatch, initialNbInds, 1); + pop.reproduction(localK, 1, 1); + pop.fledge(); // replace initial pop with juveniles + pop.emigration(localK); // select and flag emigrants + int popSize = pop.totalPop(); + for (int i = 0; i < popSize; i++) { + pop.extractDisperser(i); // rm emigrants from pop + } + int nbEmigrating = popSize - pop.totalPop(); // diff is nb of emigrants + if (mutationRate == 0.0) + assert(nbEmigrating == 0); + emigratingInds.push_back(nbEmigrating); + } + assert(emigratingInds[0] < emigratingInds[1] && emigratingInds[1] < emigratingInds[2]); + } +} + +#endif //RSDEBUG \ No newline at end of file From c4976804170257bb174c853936ee31f94910c813 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 29 Aug 2024 12:59:51 +0100 Subject: [PATCH 230/332] traitsFile is indicated in ControlFile instead of GeneticsFile --- Model.cpp | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/Model.cpp b/Model.cpp index 17ec8e7..c7b3e8f 100644 --- a/Model.cpp +++ b/Model.cpp @@ -48,15 +48,6 @@ int RunModel(Landscape* pLandscape, int seqsim) simParams sim = paramsSim->getSim(); simView v = paramsSim->getViews(); -#if RSDEBUG - landPix p = pLandscape->getLandPix(); - DEBUGLOG << "RunModel(): reps=" << sim.reps - << " ppLand.nHab=" << ppLand.nHab - << " p.pix=" << p.pix - << endl; - DEBUGLOG << endl; -#endif - if (!ppLand.generated) { if (!ppLand.patchModel) { // cell-based landscape // create patches for suitable cells, adding unsuitable cells to the matrix @@ -99,6 +90,8 @@ int RunModel(Landscape* pLandscape, int seqsim) // Loop through replicates for (int rep = 0; rep < sim.reps; rep++) { + cout << "Running replicate " << rep + 1 << " / " << sim.reps << endl; + #if RS_RCPP && !R_CMD Rcpp::Rcout << endl << "starting replicate " << rep << endl; #endif @@ -124,13 +117,7 @@ int RunModel(Landscape* pLandscape, int seqsim) if (pComm != 0) delete pComm; // generate new cell-based landscape pLandscape->resetLand(); -#if RSDEBUG - DEBUGLOG << "RunModel(): finished resetting landscape" << endl << endl; -#endif pLandscape->generatePatches(); -#if RSDEBUG - DEBUGLOG << endl << "RunModel(): finished generating patches" << endl; -#endif pComm = new Community(pLandscape); // set up community // set up a sub-community associated with each patch (incl. the matrix) pLandscape->updateCarryingCapacity(pSpecies, 0, 0); @@ -291,9 +278,9 @@ int RunModel(Landscape* pLandscape, int seqsim) || (yr < 3000001 && yr % 1000000 == 0) ) { #if RS_RCPP && !R_CMD - Rcpp::Rcout << "starting year " << yr << "..." << endl; + Rcpp::Rcout << "Starting year " << yr << "..." << endl; #else - cout << "starting year " << yr << endl; + cout << "Starting year " << yr << endl; #endif } if (init.seedType == 0 && init.freeType < 2) { From b394cd1830e5b30e4df141ab4ca910761c910b55 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 30 Aug 2024 11:22:17 +0100 Subject: [PATCH 231/332] a large populations confroms to hardy-weinberg expectations, fix #57 --- Individual.cpp | 2 +- Individual.h | 2 +- Population.cpp | 13 +++--- unit_tests/testPopulation.cpp | 77 +++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 8 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 89022a9..122cd68 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -610,7 +610,7 @@ void Individual::setStatus(short s) { status = s; } -void Individual::developing(void) { +void Individual::setToDevelop(void) { isDeveloping = true; } diff --git a/Individual.h b/Individual.h index 0c18422..feac20c 100644 --- a/Individual.h +++ b/Individual.h @@ -279,7 +279,7 @@ class Individual { settlePatch getSettPatch(void); void setSettPatch(const settlePatch); void setStatus(short); - void developing(void); + void setToDevelop(void); void develop(void); void ageIncrement( // Age by one year short // maximum age - if exceeded, the Individual dies diff --git a/Population.cpp b/Population.cpp index ee08b7c..ec80930 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1336,16 +1336,17 @@ bool Population::matePresent(Cell* pCell, short othersex) void Population::survival0(float localK, short option0, short option1) { // option0: 0 - stage 0 (juveniles) only - // 1 - all stages - // 2 - stage 1 and above (all non-juveniles) + // 1 - all stages + // 2 - stage 1 and above (all non-juveniles) + // // option1: 0 - development only (when survival is annual) - // 1 - development and survival - // 2 - survival only (when survival is annual) + // 1 - development and survival + // 2 - survival only (when survival is annual) densDepParams ddparams = pSpecies->getDensDep(); demogrParams dem = pSpecies->getDemogrParams(); stageParams sstruct = pSpecies->getStageParams(); - // get surrent population size + // get current population size int ninds = (int)inds.size(); if (ninds == 0) return; // set up local copies of species development and survival tables @@ -1459,7 +1460,7 @@ void Population::survival0(float localK, short option0, short option1) if (ind.stage < nStages - 1) { // not final stage if (ind.age >= minAge[ind.stage + 1][ind.sex]) { // old enough to enter next stage if (pRandom->Bernoulli(probdev)) { - inds[i]->developing(); + inds[i]->setToDevelop(); } } } diff --git a/unit_tests/testPopulation.cpp b/unit_tests/testPopulation.cpp index 2ab9b1b..6acb5f5 100644 --- a/unit_tests/testPopulation.cpp +++ b/unit_tests/testPopulation.cpp @@ -140,6 +140,83 @@ void testPopulation() } assert(emigratingInds[0] < emigratingInds[1] && emigratingInds[1] < emigratingInds[2]); } + + // In the absence of evolutionary forces, neutral gene + // frequencies conform to Hardy-Weinberg principle, i.e.: + // 1 - Allele frequencies p and q remain constant through generations + // 2 - Genotype frequencies conform to fAA = p^2, fAB = 2pq, fBB = q^2 + { + float mutationRate = 0.0; + const float localK = 10000.0; + const int initialNbInds = localK; + const float initFreqA = 0.7; + const float exptdFreqA = initFreqA; // Allelic freqs are constant under HW + const float exptdFreqB = 1 - exptdFreqA; + const float exptdFreqHeteroZ = 2 * exptdFreqA * exptdFreqB; // according to HW + const int nbGens = 10; + float obsFreqA = 0.0; + float obsFreqB = 0.0; + float obsFreqHeteroZ = 0.0; + const float tolerance = 0.02; // fairly high tolerance, I expect a bit of drift to act. + + // Simple genetic layout + const bool isDiploid{ true }; // HW only applies to diploids + const int genomeSz = 1; + const set genePositions = { 0 }; + const float maxAlleleVal = 1; + unsigned char alleleA = char(0); + unsigned char alleleB = char(1); + auto genotypeAA = createTestNeutralGenotype(genomeSz, true, alleleA, alleleA); + auto genotypeBB = createTestNeutralGenotype(genomeSz, true, alleleB, alleleB); + + Landscape* pLandscape = new Landscape; + Patch* pPatch = pLandscape->newPatch(1); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + pPatch->addCell(pCell, 0, 0); + + Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefaultDiploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + { }, "none", { }, 0 // no sampling + ); + SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); + pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + + // Initialise population with + Population pop = Population(pSpecies, pPatch, 0, 1); + for (int i = 0; i < initialNbInds; i++) { + Individual* pInd = new Individual(pCell, pPatch, 1, 0, 0, 0.5, false, 1); + pInd->setUpGenes(pSpecies, 1.0); + if (i < initialNbInds * initFreqA) + pInd->overrideGenotype(NEUTRAL, genotypeAA); + else + pInd->overrideGenotype(NEUTRAL, genotypeBB); + pop.recruit(pInd); + } + + // Check allele frequencies conform to HW through generations + for (int yr = 0; yr < nbGens; yr++) { + pop.reproduction(localK, 1, 1); + pop.fledge(); // replace initial pop with juveniles + pop.survival0(localK, 0, 0); // flag juveniles for development + pop.survival1(); // develop to stage 1 (breeders) + + // Count allele and heterozygote frequencies + pop.sampleIndsWithoutReplacement("all", { 1 }); + pop.updatePopNeutralTables(); + obsFreqA = pop.getAlleleFrequency(0, alleleA); + obsFreqB = pop.getAlleleFrequency(0, alleleB); + float nbHeteroZ = pop.getHeteroTally(0, alleleA); + int nbInds = pop.getNInds(); + obsFreqHeteroZ = nbHeteroZ / nbInds; + assert(abs(obsFreqA - exptdFreqA) < tolerance); + assert(abs(obsFreqB - exptdFreqB) < tolerance); + assert(abs(obsFreqHeteroZ - exptdFreqHeteroZ) < tolerance); + } + } } #endif //RSDEBUG \ No newline at end of file From 340906826afeecc9f282e0d56384ca0ba6badb11 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 2 Sep 2024 11:23:27 +0100 Subject: [PATCH 232/332] haploid fst matches equivalent diploid fst, fix #75 --- unit_tests/testNeutralStats.cpp | 100 ++++++++++++++++++++++++++++++-- 1 file changed, 95 insertions(+), 5 deletions(-) diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index d0bc458..22b7898 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -481,6 +481,8 @@ void testNeutralStats() { assert(pNeutralStatistics->getPairwiseFst(0, 1) == 0.0); } + double refDiploidFst; // for use in haploid test below + // In strictly homozygote samples: // 1. Fis = 1 (maximum inbreeding) // 2. The sign of the Fst depends on the ratio of variation within vs between populations @@ -503,8 +505,8 @@ void testNeutralStats() { const auto genotypeBB = createTestNeutralGenotype(genomeSz, true, alleleValPopB, alleleValPopB); vector>> genotypes = { // 8 AA, 2 BB (no heterozygotes) - genotypeAA, genotypeAA, genotypeAA, genotypeAA, genotypeAA, - genotypeAA, genotypeAA, genotypeAA, genotypeBB, genotypeBB + genotypeAA, genotypeAA, genotypeAA, genotypeAA, genotypeBB, + genotypeAA, genotypeAA, genotypeAA, genotypeAA, genotypeBB }; // Create two-patches landscape @@ -567,8 +569,10 @@ void testNeutralStats() { pSpecies, pLandscape ); - assert(pNeutralStatistics->getFstWC() < 0.0); - assert(pNeutralStatistics->getFisWC() == 1.0); + assert(pNeutralStatistics->getFstWC() < 0.0); + assert(pNeutralStatistics->getFisWC() == 1.0); + + refDiploidFst = pNeutralStatistics->getFstWC(); // for use in haploid test below } // Case 2/2: variation within < between @@ -842,6 +846,92 @@ void testNeutralStats() { double calcError = abs(pNeutralStatistics->getFstWC() - expectedFst); assert(calcError < 0.0001); } + + // THe Fst is a haploid sample equals that of a diploid sample if: + // 1 - allelic frequencies are equal + // 2 - the diploid sample has no heterozygotes + // (reference diploid Fst has already been calculated above) + { + const bool isDiploid{ false }; + // Patch setup + const int nbPatches = 2; + const int nbIndsPerPop = 10; + // Genetic setup + const int genomeSz = 1; + const set genePositions = { 0 }; + const float maxAlleleVal = 1; + unsigned char alleleValPopA = char(0); + unsigned char alleleValPopB = char(1); + const auto genotypeA = createTestNeutralGenotype(genomeSz, true, alleleValPopA); + const auto genotypeB = createTestNeutralGenotype(genomeSz, true, alleleValPopB); + vector>> genotypes = { + // 8 A, 2B (no heterozygotes) + genotypeA, genotypeA, genotypeA, genotypeA, genotypeB, + genotypeA, genotypeA, genotypeA, genotypeA, genotypeB + }; + + // Create two-patches landscape + Landscape* pLandscape = new Landscape; + vector patches(nbPatches); + vector cells(nbPatches); + set patchList; + for (int i = 0; i < nbPatches; i++) { + patches[i] = pLandscape->newPatch(i); + cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + patches[i]->addCell(cells[i], 0, 0); + patchList.insert(patches[i]->getPatchNum()); + } + const string indSampling = "all"; + const set stgToSample = { 1 }; + + // Create species trait structure + Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefaultHaploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + patchList, + indSampling, + stgToSample, + 1 + ); + const int nbLoci = genePositions.size(); + SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); + pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + + // Initialise populations + const int indStg = 1; + for (int p = 0; p < patches.size(); p++) { + Population* pPop = new Population(pSpecies, patches[p], 0, 1); + // create individuals and add to pop + for (int i = 0; i < nbIndsPerPop; i++) { + Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + pInd->setUpGenes(pSpecies, 1.0); + pInd->overrideGenotype(NEUTRAL, genotypes[i]); + pPop->recruit(pInd); + } + pPop->sampleIndsWithoutReplacement(indSampling, { indStg }); + } + + // Compute F-stats + auto pNeutralStatistics = make_unique(nbPatches, nbLoci); + pNeutralStatistics->updateAllNeutralTables( + pSpecies, + pLandscape, + patchList + ); + const int maxNbNeutralAlleles = static_cast(maxAlleleVal) + 1; + pNeutralStatistics->calculateFstatWC( + patchList, + nbIndsPerPop * patchList.size(), + nbLoci, + maxNbNeutralAlleles, + pSpecies, + pLandscape + ); + assert(pNeutralStatistics->getFstWC() == refDiploidFst); + } } -#endif //RSDEBUG \ No newline at end of file +#endif // RSDEBUG \ No newline at end of file From 43da58ff8c195d18ce363d44112b7ac57b36ae59 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 2 Sep 2024 11:42:19 +0100 Subject: [PATCH 233/332] weir and cockerham, weir & hill converge, fix #73 --- NeutralStatsManager.cpp | 5 ++--- unit_tests/testNeutralStats.cpp | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 3ffff0a..894c043 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -534,7 +534,6 @@ void NeutralStatsManager::calcPerLocusMeanSquaresFst(set const& patchList, void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape) { const int nAlleles = (int)pSpecies->getSpTrait(NEUTRAL)->getNbNeutralAlleles(); - const int ploidy = pSpecies->isDiploid() ? 2 : 1; // Needs to be in vector to iterate over, copy preserves order vector patchVect; @@ -559,14 +558,14 @@ void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, con double denominator = 0; double sumWeights = 0; - totSize = nInds * ploidy; + totSize = nInds; // Calculate weight (n_ic) terms for (int i = 0; i < nPatches; ++i) { const auto patch = pLandscape->findPatch(patchVect[i]); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop != 0) { - popSizes[i] = pPop->sampleSize() * ploidy; + popSizes[i] = pPop->sampleSize(); } // else popSizes[i] remain default init value 0, safe popWeights[i] = popSizes[i] - (popSizes[i] * popSizes[i] / totSize); // n_ic in Weir & Hill 2002 sumWeights += popWeights[i]; diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index 22b7898..72c369c 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -481,11 +481,12 @@ void testNeutralStats() { assert(pNeutralStatistics->getPairwiseFst(0, 1) == 0.0); } - double refDiploidFst; // for use in haploid test below + double refDiploidFst; // for use in further tests below // In strictly homozygote samples: // 1. Fis = 1 (maximum inbreeding) // 2. The sign of the Fst depends on the ratio of variation within vs between populations + // 3. (if sample sizes are equal) The Weir&Cockerham 1984, Weir&Hill 2002 estimators yield the same values { // Case 1/2: variation within > between // Within: frequencies of allele A and B are quite different @@ -572,7 +573,17 @@ void testNeutralStats() { assert(pNeutralStatistics->getFstWC() < 0.0); assert(pNeutralStatistics->getFisWC() == 1.0); - refDiploidFst = pNeutralStatistics->getFstWC(); // for use in haploid test below + pNeutralStatistics->calcPairwiseWeightedFst( + patchList, + nbIndsPerPop * patchList.size(), + nbLoci, + pSpecies, + pLandscape + ); + const double tol = 0.000001; + assert(abs(pNeutralStatistics->getWeightedFst() - pNeutralStatistics->getFstWC()) < tol); + + refDiploidFst = pNeutralStatistics->getFstWC(); // for use in further tests below } // Case 2/2: variation within < between @@ -847,7 +858,7 @@ void testNeutralStats() { assert(calcError < 0.0001); } - // THe Fst is a haploid sample equals that of a diploid sample if: + // The Fst is a haploid sample equals that of a diploid sample if: // 1 - allelic frequencies are equal // 2 - the diploid sample has no heterozygotes // (reference diploid Fst has already been calculated above) From 6eb36c08ff562f97515a27586f80ad314421ab23 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 2 Sep 2024 11:50:48 +0100 Subject: [PATCH 234/332] Weir & Cockerham > Weir&Hill if heterozygotes present --- unit_tests/testNeutralStats.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index 72c369c..4ef31bd 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -481,7 +481,7 @@ void testNeutralStats() { assert(pNeutralStatistics->getPairwiseFst(0, 1) == 0.0); } - double refDiploidFst; // for use in further tests below + double refWeirCockerhamDiploidFst; // for use in further tests below // In strictly homozygote samples: // 1. Fis = 1 (maximum inbreeding) @@ -583,7 +583,7 @@ void testNeutralStats() { const double tol = 0.000001; assert(abs(pNeutralStatistics->getWeightedFst() - pNeutralStatistics->getFstWC()) < tol); - refDiploidFst = pNeutralStatistics->getFstWC(); // for use in further tests below + refWeirCockerhamDiploidFst = pNeutralStatistics->getFstWC(); // for use in further tests below } // Case 2/2: variation within < between @@ -678,8 +678,10 @@ void testNeutralStats() { } } - // In a strictly heterozygote sample, Fis = -1 - // + if there is no variation between individuals, Fst = 0 + // In a strictly heterozygote sample, + // 1. Fis = -1 + // 2. If there is no variation between individuals, Fst = 0 + // 3. Weir & Cockerham 1984 estimator > Weir & Hill 2002 { // Patch setup const int nbPatches = 2; @@ -756,6 +758,18 @@ void testNeutralStats() { ); assert(pNeutralStatistics->getFstWC() == 0.0); assert(pNeutralStatistics->getFisWC() == -1.0); + + pNeutralStatistics->calcPairwiseWeightedFst( + patchList, + nbIndsPerPop* patchList.size(), + nbLoci, + pSpecies, + pLandscape + ); + assert(pNeutralStatistics->getWeightedFst() < pNeutralStatistics->getFstWC()); + // Weir and Hill is still equal to Weir and Cockerham full homozygote case + const double tol = 0.000001; + assert(abs(pNeutralStatistics->getWeightedFst() - refWeirCockerhamDiploidFst) < tol); } // Fst calculation is correct for an ordinary sample @@ -941,7 +955,7 @@ void testNeutralStats() { pSpecies, pLandscape ); - assert(pNeutralStatistics->getFstWC() == refDiploidFst); + assert(pNeutralStatistics->getFstWC() == refWeirCockerhamDiploidFst); } } From 739beeba64c8ebd7929f2821625b385148bc7595 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 2 Sep 2024 13:23:36 +0100 Subject: [PATCH 235/332] population-specific estimates average to weri & hill, fix #76 --- unit_tests/testNeutralStats.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index 4ef31bd..fb295d0 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -675,6 +675,19 @@ void testNeutralStats() { ); assert(pNeutralStatistics->getFstWC() > 0.0); assert(pNeutralStatistics->getFisWC() == 1.0); + + // Weir & Hill population-specific estimates average to the (Weir & Hill) global estimator + pNeutralStatistics->calcPairwiseWeightedFst( + patchList, + nbIndsPerPop* patchList.size(), + nbLoci, + pSpecies, + pLandscape + ); + const double pop1Fst = pNeutralStatistics->getPairwiseFst(0, 0); + const double pop2Fst = pNeutralStatistics->getPairwiseFst(1, 1); + assert((pop1Fst + pop2Fst) / 2.0 == pNeutralStatistics->getWeightedFst()); + } } From f76c10ebc8fda3e2ee4e96b671f186f9313d8217 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 2 Sep 2024 14:50:23 +0100 Subject: [PATCH 236/332] nb of offspring dying matches HW expectations, fix #56 --- SpeciesTrait.cpp | 25 +++++++++++++++ SpeciesTrait.h | 1 + unit_tests/testIndividual.cpp | 3 +- unit_tests/testPopulation.cpp | 60 +++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 2 deletions(-) diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 6ffd4c1..5ae7afc 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -220,6 +220,31 @@ SpeciesTrait* createTestEmigSpTrait(const set& genePositions, const bool& i return spTr; } +SpeciesTrait* createTestGenLoadTrait(const set& genePositions, const bool& isDiploid) { + // Create species trait + const map distParams{ + pair{GenParamType::MIN, 0.0}, + pair{GenParamType::MAX, 1.0} + }; + SpeciesTrait* spTr = new SpeciesTrait( + TraitType::GENETIC_LOAD, + sex_t::NA, + genePositions, + ExpressionType::MULTIPLICATIVE, + DistributionType::UNIFORM, + distParams, + DistributionType::UNIFORM, + distParams, + true, // isInherited + 0.0, // mutation rate + DistributionType::UNIFORM, + distParams, + isDiploid ? 2 : 1, + false + ); + return spTr; +} + SpeciesTrait* createTestNeutralSpTrait(const float& maxAlleleVal, const set& genePositions, const bool& isDiploid) { const map distParams{ diff --git a/SpeciesTrait.h b/SpeciesTrait.h index 9761332..1a87b02 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -84,6 +84,7 @@ class SpeciesTrait { // Create a default set of gene positions ranging from zero to genome size set createTestGenePositions(const int genomeSz); SpeciesTrait* createTestEmigSpTrait(const set& genePositions, const bool& isDiploid); +SpeciesTrait* createTestGenLoadTrait(const set& genePositions, const bool& isDiploid); SpeciesTrait* createTestNeutralSpTrait(const float& maxAlleleVal, const set& genePositions, const bool& isDiploid); #endif // RSDEBUG diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 5e6d2cb..3b17d0c 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -1221,10 +1221,9 @@ void testIndividual() { assert(trfrTr.rho <= 1.0); } - // Case 3 - Transfer with Sotchastic Movement Simulator + // Case 3 - Transfer with Stochastic Movement Simulator { const int genomeSz = 2; - const bool isDiploid{ true }; // haploid, simpler check const float mutationRate = 0.0; // no mutations diff --git a/unit_tests/testPopulation.cpp b/unit_tests/testPopulation.cpp index 6acb5f5..702ea9f 100644 --- a/unit_tests/testPopulation.cpp +++ b/unit_tests/testPopulation.cpp @@ -217,6 +217,66 @@ void testPopulation() assert(abs(obsFreqHeteroZ - exptdFreqHeteroZ) < tolerance); } } + + // Genetic load meets Hardy-Weinberg expectation + // If a lethal (s = 1) recessive (h = 0) allele starts at freq 0.6, + // then (if no mutations) the prop. of unviable homozygote offspring should be 0.36 + { + const float initFreqA = 0.6; + const float sA = 1.0; // lethal + const float hA = 0.0; // fully recessive + const float sB = 0.0; // benign + const float hB = 1.0; // fully dominant + float mutationRate = 0.0; + const float localK = 10000.0; + const int initialNbInds = localK; + const float tolerance = 0.015; // high tolerance, still a lot of stochasticity + const float expectedFreqAA = initFreqA * initFreqA; + + // Simple genetic layout + const bool isDiploid{ true }; // HW only applies to diploids + const int genomeSz = 1; + const set genePositions = { 0 }; + const float maxAlleleVal = 1; + unsigned char alleleA = char(0); + unsigned char alleleB = char(1); + auto genotypeAA = createTestGenotype(genomeSz, true, sA, sA, hA, hA); + auto genotypeBB = createTestGenotype(genomeSz, true, sB, sB, hB, hB); + + Landscape* pLandscape = new Landscape; + Patch* pPatch = pLandscape->newPatch(1); + Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + pPatch->addCell(pCell, 0, 0); + + Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefaultDiploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + { }, "none", { }, 0 // no sampling + ); + SpeciesTrait* spTr = createTestGenLoadTrait(genePositions, isDiploid); + pSpecies->addTrait(TraitType::GENETIC_LOAD, *spTr); + + // Initialise population with + Population pop = Population(pSpecies, pPatch, 0, 1); + for (int i = 0; i < initialNbInds; i++) { + Individual* pInd = new Individual(pCell, pPatch, 1, 0, 0, 0.5, false, 1); + pInd->setUpGenes(pSpecies, 1.0); + if (i < initialNbInds * initFreqA) + pInd->overrideGenotype(GENETIC_LOAD1, genotypeAA); + else + pInd->overrideGenotype(GENETIC_LOAD1, genotypeBB); + pop.recruit(pInd); + } + + // Check allele frequencies conform to HW + pop.reproduction(localK, 1, 1); + pop.fledge(); // replace initial pop with juveniles + double obsFreqUnviable = 1 - pop.getNInds() / localK; + assert(abs(obsFreqUnviable - expectedFreqAA) < tolerance); + } } #endif //RSDEBUG \ No newline at end of file From b306fb1be9335771e64b7622ee7fe5b13bc0eee9 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 2 Sep 2024 14:51:53 +0100 Subject: [PATCH 237/332] higher tolerance --- unit_tests/testPopulation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unit_tests/testPopulation.cpp b/unit_tests/testPopulation.cpp index 702ea9f..3bc64de 100644 --- a/unit_tests/testPopulation.cpp +++ b/unit_tests/testPopulation.cpp @@ -230,7 +230,7 @@ void testPopulation() float mutationRate = 0.0; const float localK = 10000.0; const int initialNbInds = localK; - const float tolerance = 0.015; // high tolerance, still a lot of stochasticity + const float tolerance = 0.02; // high tolerance, still a lot of stochasticity const float expectedFreqAA = initFreqA * initFreqA; // Simple genetic layout From 1cfb768c424b36b02e5c112243c57de82d8960bf Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 2 Sep 2024 18:11:20 +0100 Subject: [PATCH 238/332] reorganise neutral genetics output --- Community.cpp | 73 +++++++++++++++------------ Community.h | 14 +++--- Model.cpp | 108 +++++++++++++++++++++------------------- NeutralStatsManager.cpp | 60 +++++++++++++++------- Parameters.cpp | 14 +++--- Parameters.h | 9 ++-- Species.cpp | 2 +- 7 files changed, 156 insertions(+), 124 deletions(-) diff --git a/Community.cpp b/Community.cpp index 0935edf..149cbb5 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1602,7 +1602,7 @@ void Community::sampleIndividuals(Species* pSpecies) { // Open population level Fstat output file // ---------------------------------------------------------------------------------------- -bool Community::openWCFstatFile(Species* pSpecies, int landNr) +bool Community::openNeutralOutputFile(Species* pSpecies, int landNr) { if (landNr == -999) { // close the file if (outwcfstat.is_open()) outwcfstat.close(); @@ -1624,7 +1624,7 @@ bool Community::openWCFstatFile(Species* pSpecies, int landNr) name = paramsSim->getDir(2) + "Sim" + to_string(sim.simulation) + "_neutralGenetics.txt"; } outwcfstat.open(name.c_str()); - outwcfstat << "Rep\tYear\tRepSeason\tnExtantPatches\tnIndividuals\tfst\tfis\tfit\tmeanAllelePerLocus\tmeanAllelePerLocusPatches\tmeanFixedLoci\tmeanFixedLociPatches\tmeanObHeterozygosity"; + outwcfstat << "Rep\tYear\tRepSeason\tnExtantPatches\tnIndividuals\tFstWC\tFisWC\tFitWC\tFstWH\tmeanAllelePerLocus\tmeanAllelePerLocusPatches\tmeanFixedLoci\tmeanFixedLociPatches\tmeanObHeterozygosity"; outwcfstat << endl; return outwcfstat.is_open(); @@ -1635,7 +1635,7 @@ bool Community::openWCFstatFile(Species* pSpecies, int landNr) // in general population neutral genetics output file // ---------------------------------------------------------------------------------------- -bool Community::openWCPerLocusFstatFile(Species* pSpecies, Landscape* pLandscape, const int landNr, const int rep) +bool Community::openPerLocusFstFile(Species* pSpecies, Landscape* pLandscape, const int landNr, const int rep) { const set patchList = pSpecies->getSamplePatches(); @@ -1661,7 +1661,7 @@ bool Community::openWCPerLocusFstatFile(Species* pSpecies, Landscape* pLandscape } outperlocusfstat.open(name.c_str()); - outperlocusfstat << "Year\tRepSeason\tlocus\tfst\tfis\tfit\tpopHet"; + outperlocusfstat << "Year\tRepSeason\tlocus\tFst\tFis\tFit\tpopHet"; for (int patchId : patchList) { outperlocusfstat << "\tpatch_" + to_string(patchId) + "_Het"; } @@ -1674,7 +1674,7 @@ bool Community::openWCPerLocusFstatFile(Species* pSpecies, Landscape* pLandscape // open pairwise fst file // ---------------------------------------------------------------------------------------- -bool Community::openPairwiseFSTFile(Species* pSpecies, Landscape* pLandscape, const int landNr, const int rep) { +bool Community::openPairwiseFstFile(Species* pSpecies, Landscape* pLandscape, const int landNr, const int rep) { const set patchList = pSpecies->getSamplePatches(); @@ -1699,7 +1699,7 @@ bool Community::openPairwiseFSTFile(Species* pSpecies, Landscape* pLandscape, co name = paramsSim->getDir(2) + "Sim" + to_string(sim.simulation) + "_Rep" + to_string(rep) + "_pairwisePatchNeutralGenetics.txt"; } outpairwisefst.open(name.c_str()); - outpairwisefst << "Year\tRepSeason\tpatchA\tpatchB\tfst"; + outpairwisefst << "Year\tRepSeason\tpatchA\tpatchB\tFst"; outpairwisefst << endl; return outpairwisefst.is_open(); @@ -1709,19 +1709,27 @@ bool Community::openPairwiseFSTFile(Species* pSpecies, Landscape* pLandscape, co // Write population level FST results file // ---------------------------------------------------------------------------------------- -void Community::writeWCFstatFile(int rep, int yr, int gen) { +void Community::writeNeutralOutputFile(int rep, int yr, int gen, bool outWeirCockerham, bool outWeirHill) { outwcfstat << rep << "\t" << yr << "\t" << gen << "\t"; outwcfstat << pNeutralStatistics->getNbPopulatedSampledPatches() << "\t" << pNeutralStatistics->getTotalNbSampledInds() << "\t"; - outwcfstat << pNeutralStatistics->getFstWC() << "\t" - << pNeutralStatistics->getFisWC() << "\t" - << pNeutralStatistics->getFitWC() << "\t"; - outwcfstat << pNeutralStatistics->getMeanNbAllPerLocus() - << "\t" << pNeutralStatistics->getMeanNbAllPerLocusPerPatch() << "\t" - << pNeutralStatistics->getTotalFixdAlleles() - << "\t" << pNeutralStatistics->getMeanFixdAllelesPerPatch() - << "\t" << pNeutralStatistics->getHo(); + + if (outWeirCockerham) { + outwcfstat << pNeutralStatistics->getFstWC() << "\t" + << pNeutralStatistics->getFisWC() << "\t" + << pNeutralStatistics->getFitWC() << "\t"; + } + else outwcfstat << "N/A" << "\t" << "N/A" << "\t" << "N/A" << "\t"; + + if (outWeirHill) outwcfstat << pNeutralStatistics->getWeightedFst() << "\t"; + else outwcfstat << "N/A" << "\t"; + + outwcfstat << pNeutralStatistics->getMeanNbAllPerLocus() << "\t" + << pNeutralStatistics->getMeanNbAllPerLocusPerPatch() << "\t" + << pNeutralStatistics->getTotalFixdAlleles() << "\t" + << pNeutralStatistics->getMeanFixdAllelesPerPatch() << "\t" + << pNeutralStatistics->getHo(); outwcfstat << endl; } @@ -1730,7 +1738,7 @@ void Community::writeWCFstatFile(int rep, int yr, int gen) { // Write per locus FST results file // ---------------------------------------------------------------------------------------- -void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList) +void Community::writePerLocusFstatFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList) { const set positions = pSpecies->getSpTrait(NEUTRAL)->getGenePositions(); @@ -1753,7 +1761,7 @@ void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const if (pPop != 0) { popSize = pPop->sampleSize(); if (popSize == 0) { - outperlocusfstat << "\t" << "NA"; + outperlocusfstat << "\t" << "N/A"; } else { for (int a = 0; a < nAlleles; ++a) { @@ -1764,7 +1772,7 @@ void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const } } else { - outperlocusfstat << "\t" << "NA"; + outperlocusfstat << "\t" << "N/A"; } } ++thisLocus; @@ -1776,7 +1784,7 @@ void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const // ---------------------------------------------------------------------------------------- // Write pairwise FST results file // ---------------------------------------------------------------------------------------- -void Community::writePairwiseFSTFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList) { +void Community::writePairwiseFstFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList) { // within patch fst (diagonal of matrix) int i = 0; @@ -1809,7 +1817,7 @@ void Community::writePairwiseFSTFile(Species* pSpecies, const int yr, const int // ---------------------------------------------------------------------------------------- -void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool fstat, bool perLocus, bool pairwise) { +void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool outWeirCockerham, bool outWeirHill) { const int maxNbNeutralAlleles = pSpecies->getSpTrait(NEUTRAL)->getNbNeutralAlleles(); const int nLoci = (int)pSpecies->getNPositionsForTrait(NEUTRAL); @@ -1831,23 +1839,24 @@ void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, pNeutralStatistics = make_unique(patchList.size(), nLoci); pNeutralStatistics->updateAllNeutralTables(pSpecies, pLandscape, patchList); + pNeutralStatistics->calculateHo(patchList, nInds, nLoci, pSpecies, pLandscape); + pNeutralStatistics->calculatePerLocusHo(patchList, nInds, nLoci, pSpecies, pLandscape); + pNeutralStatistics->calcAllelicDiversityMetrics(patchList, nInds, pSpecies, pLandscape); - if (fstat) { - pNeutralStatistics->calculateHo(patchList, nInds, nLoci, pSpecies, pLandscape); - pNeutralStatistics->calcAllelicDiversityMetrics(patchList, nInds, pSpecies, pLandscape); + if (outWeirCockerham) { pNeutralStatistics->calculateFstatWC(patchList, nInds, nLoci, maxNbNeutralAlleles, pSpecies, pLandscape); - writeWCFstatFile(rep, yr, gen); } - - if (perLocus) { - pNeutralStatistics->calcPerLocusMeanSquaresFst(patchList, nInds, nLoci, maxNbNeutralAlleles, pSpecies, pLandscape); - pNeutralStatistics->calculatePerLocusHo(patchList, nInds, nLoci, pSpecies, pLandscape); - writeWCPerLocusFstatFile(pSpecies, yr, gen, maxNbNeutralAlleles, nLoci, patchList); + if (outWeirHill) { + pNeutralStatistics->calcPairwiseWeightedFst(patchList, nInds, nLoci, pSpecies, pLandscape); } - if (pairwise) { - pNeutralStatistics->calcPairwiseWeightedFst(patchList, nInds, nLoci, pSpecies, pLandscape); - writePairwiseFSTFile(pSpecies, yr, gen, maxNbNeutralAlleles, nLoci, patchList); + writeNeutralOutputFile(rep, yr, gen, outWeirCockerham, outWeirHill); + + if (outWeirCockerham) { + writePerLocusFstatFile(pSpecies, yr, gen, maxNbNeutralAlleles, nLoci, patchList); + } + if (outWeirHill) { + writePairwiseFstFile(pSpecies, yr, gen, maxNbNeutralAlleles, nLoci, patchList); } } diff --git a/Community.h b/Community.h index ded1685..2de09d9 100644 --- a/Community.h +++ b/Community.h @@ -194,17 +194,17 @@ class Community { void outputGeneValues(const int& year, const int& gen, Species* pSpecies); //control neutral stat output - void outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool fstat, bool perLocus, bool pairwise); + void outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, bool outWeirCockerham, bool outWeirHill); //file openers - bool openWCFstatFile(Species* pSpecies, const int landNr); - bool openWCPerLocusFstatFile(Species* pSpecies, Landscape* pLandscape, const int landNr, const int rep); - bool openPairwiseFSTFile(Species* pSpecies, Landscape* pLandscape, const int landNr, const int rep); + bool openNeutralOutputFile(Species* pSpecies, const int landNr); + bool openPerLocusFstFile(Species* pSpecies, Landscape* pLandscape, const int landNr, const int rep); + bool openPairwiseFstFile(Species* pSpecies, Landscape* pLandscape, const int landNr, const int rep); //file writers - void writeWCFstatFile(int rep, int yr, int gen); - void writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList); - void writePairwiseFSTFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList); + void writeNeutralOutputFile(int rep, int yr, int gen, bool outWeirCockerham, bool outWeirHill); + void writePerLocusFstatFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList); + void writePairwiseFstFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList); private: Landscape* pLandscape; diff --git a/Model.cpp b/Model.cpp index c7b3e8f..6bd5110 100644 --- a/Model.cpp +++ b/Model.cpp @@ -125,15 +125,15 @@ int RunModel(Landscape* pLandscape, int seqsim) int npatches = pLandscape->patchCount(); for (int i = 0; i < npatches; i++) { ppp = pLandscape->getPatchData(i); - #if RSWIN64 - #if LINUX_CLUSTER +#if RSWIN64 +#if LINUX_CLUSTER pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES - #else +#else SubCommunity* pSubComm = pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES - #endif - #else +#endif +#else pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES - #endif +#endif } if (sim.patchSamplingOption == "random") { // Then patches must be resampled for new landscape @@ -181,8 +181,8 @@ int RunModel(Landscape* pLandscape, int seqsim) if (!pLandscape->outConnectHeaders(0)) { filesOK = false; } - if (sim.outputWCFstat) { // open neutral genetics file - if (!pComm->openWCFstatFile(pSpecies, ppLand.landNum)) { + if (sim.outputWeirCockerham) { // open neutral genetics file + if (!pComm->openNeutralOutputFile(pSpecies, ppLand.landNum)) { filesOK = false; } } @@ -203,14 +203,14 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->outTraitsRowsHeaders(pSpecies, -999); if (sim.outConnect && ppLand.patchModel) pLandscape->outConnectHeaders(-999); - if (sim.outputWCFstat) { - pComm->openWCFstatFile(pSpecies, -999); + if (sim.outputWeirCockerham) { + pComm->openNeutralOutputFile(pSpecies, -999); } - #if RS_RCPP && !R_CMD +#if RS_RCPP && !R_CMD return Rcpp::List::create(Rcpp::Named("Errors") = 666); - #else +#else return 666; - #endif +#endif } if (env.stoch && !env.local) { @@ -237,9 +237,9 @@ int RunModel(Landscape* pLandscape, int seqsim) bool updateland = false; int landIx = 0; // landscape change index - #if BATCH && RS_RCPP && !R_CMD +#if BATCH && RS_RCPP && !R_CMD Rcpp::Rcout << "RunModel(): completed initialisation " << endl; - #endif +#endif // open a new individuals file for each replicate if (sim.outInds) @@ -251,23 +251,23 @@ int RunModel(Landscape* pLandscape, int seqsim) } // open a new genetics file for each replicate for per locus and pairwise stats - if (sim.outputPerLocusWCFstat) { - pComm->openWCPerLocusFstatFile(pSpecies, pLandscape, ppLand.landNum, rep); + if (sim.outputWeirCockerham) { + pComm->openPerLocusFstFile(pSpecies, pLandscape, ppLand.landNum, rep); } - if (sim.outputPairwiseFst) { - pComm->openPairwiseFSTFile(pSpecies, pLandscape, ppLand.landNum, rep); + if (sim.outputWeirHill) { + pComm->openPairwiseFstFile(pSpecies, pLandscape, ppLand.landNum, rep); } - #if RS_RCPP +#if RS_RCPP // open a new movement paths file for each replicate if (sim.outPaths) pLandscape->outPathsHeaders(rep, 0); - #endif +#endif // years loop for (yr = 0; yr < sim.years; yr++) { - #if RS_RCPP && !R_CMD +#if RS_RCPP && !R_CMD Rcpp::checkUserInterrupt(); - #endif +#endif bool updateCC = false; if (yr < 4 || (yr < 31 && yr % 10 == 0) @@ -277,11 +277,11 @@ int RunModel(Landscape* pLandscape, int seqsim) || (yr < 300001 && yr % 100000 == 0) || (yr < 3000001 && yr % 1000000 == 0) ) { - #if RS_RCPP && !R_CMD +#if RS_RCPP && !R_CMD Rcpp::Rcout << "Starting year " << yr << "..." << endl; - #else +#else cout << "Starting year " << yr << endl; - #endif +#endif } if (init.seedType == 0 && init.freeType < 2) { // apply any range restrictions @@ -331,7 +331,7 @@ int RunModel(Landscape* pLandscape, int seqsim) Cell* pCell; patchchange = pLandscape->getPatchChange(ixpchchg++); while (patchchange.chgnum <= landIx && ixpchchg <= npatchchanges) { - // move cell from original patch to new patch + // move cell from original patch to new patch pCell = pLandscape->findCell(patchchange.x, patchchange.y); if (patchchange.oldpatch != 0) { // not matrix pPatch = pLandscape->findPatch(patchchange.oldpatch); @@ -435,9 +435,9 @@ int RunModel(Landscape* pLandscape, int seqsim) list_outPop.push_back(pComm->addYearToPopList(rep, yr), "rep" + std::to_string(rep) + "_year" + std::to_string(yr)); } #endif - // apply local extinction for generation 0 only - // CHANGED TO *BEFORE* RANGE & POPN OUTPUT PRODUCTION IN v1.1, - // SO THAT NOS. OF JUVENILES BORN CAN BE REPORTED + // apply local extinction for generation 0 only + // CHANGED TO *BEFORE* RANGE & POPN OUTPUT PRODUCTION IN v1.1, + // SO THAT NOS. OF JUVENILES BORN CAN BE REPORTED if (!ppLand.patchModel && gen == 0) { if (env.localExt) pComm->localExtinction(0); if (grad.gradient && grad.gradType == 3) pComm->localExtinction(1); @@ -484,25 +484,25 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outInds && yr >= sim.outStartInd && yr % sim.outIntInd == 0) pComm->outInds(rep, yr, gen, -1); - if ((sim.outputGeneValues || sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat) + if ((sim.outputGeneValues || sim.outputWeirCockerham || sim.outputWeirHill) && yr >= sim.outStartGenetics && yr % sim.outputGeneticInterval == 0) { simParams sim = paramsSim->getSim(); - if (sim.patchSamplingOption != "list" && sim.patchSamplingOption != "random") { - // then patches must be re-sampled every gen - int nbToSample = pSpecies->getNbPatchesToSample(); - auto patchesToSample = pLandscape->samplePatches(sim.patchSamplingOption, nbToSample, pSpecies); - pSpecies->setSamplePatchList(patchesToSample); - } - // otherwise always use the user-specified list (even if patches are empty) + if (sim.patchSamplingOption != "list" && sim.patchSamplingOption != "random") { + // then patches must be re-sampled every gen + int nbToSample = pSpecies->getNbPatchesToSample(); + auto patchesToSample = pLandscape->samplePatches(sim.patchSamplingOption, nbToSample, pSpecies); + pSpecies->setSamplePatchList(patchesToSample); + } + // otherwise always use the user-specified list (even if patches are empty) pComm->sampleIndividuals(pSpecies); if (sim.outputGeneValues) { pComm->outputGeneValues(yr, gen, pSpecies); } - if (sim.outputWCFstat || sim.outputPairwiseFst || sim.outputPerLocusWCFstat) { - pComm->outNeutralGenetics(pSpecies, rep, yr, gen, sim.outputWCFstat, sim.outputPerLocusWCFstat, sim.outputPairwiseFst); + if (sim.outputWeirCockerham || sim.outputWeirHill) { + pComm->outNeutralGenetics(pSpecies, rep, yr, gen, sim.outputWeirCockerham, sim.outputWeirHill); } } if (dem.stageStruct) { @@ -548,7 +548,7 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->resetPopns(); - //Reset the gradient optimum + //Reset the gradient optimum if (grad.gradient) paramsGrad->resetOptY(); pLandscape->resetLandLimits(); @@ -560,7 +560,7 @@ int RunModel(Landscape* pLandscape, int seqsim) Cell* pCell; patchchange = pLandscape->getPatchChange(ixpchchg++); while (patchchange.chgnum <= 666666 && ixpchchg <= npatchchanges) { - // move cell from original patch to new patch + // move cell from original patch to new patch pCell = pLandscape->findCell(patchchange.x, patchchange.y); if (patchchange.oldpatch != 0) { // not matrix pPatch = pLandscape->findPatch(patchchange.oldpatch); @@ -612,10 +612,10 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->openOutGenesFile(false, -999, rep); } - if (sim.outputPerLocusWCFstat) //close per locus file - pComm->openWCPerLocusFstatFile(pSpecies, pLandscape, -999, rep); - if (sim.outputPairwiseFst) //close per locus file - pComm->openPairwiseFSTFile(pSpecies, pLandscape, -999, rep); + if (sim.outputWeirCockerham) //close per locus file + pComm->openPerLocusFstFile(pSpecies, pLandscape, -999, rep); + if (sim.outputWeirHill) //close per locus file + pComm->openPairwiseFstFile(pSpecies, pLandscape, -999, rep); if (sim.saveVisits) { pLandscape->outVisits(rep, ppLand.landNum); @@ -656,9 +656,13 @@ int RunModel(Landscape* pLandscape, int seqsim) // they can still be open if the simulation was stopped by the user if (sim.outInds) pComm->outInds(0, 0, 0, -999); if (sim.outputGeneValues) pComm->openOutGenesFile(0, -999, 0); - if (sim.outputWCFstat) pComm->openWCFstatFile(pSpecies, -999); - if (sim.outputPerLocusWCFstat) pComm->openWCPerLocusFstatFile(pSpecies, pLandscape, -999, 0); - if (sim.outputPairwiseFst) pComm->openPairwiseFSTFile(pSpecies, pLandscape, -999, 0); + if (sim.outputWeirCockerham || sim.outputWeirHill) { + pComm->openNeutralOutputFile(pSpecies, -999); + } + if (sim.outputWeirCockerham) { + pComm->openPerLocusFstFile(pSpecies, pLandscape, -999, 0); + } + if (sim.outputWeirHill) pComm->openPairwiseFstFile(pSpecies, pLandscape, -999, 0); delete pComm; pComm = 0; @@ -1715,11 +1719,11 @@ void OutParameters(Landscape* pLandscape) if (sim.outStartInd > 0) outPar << " starting year " << sim.outStartInd; outPar << endl; } - if (sim.outputWCFstat || sim.outputPairwiseFst) { + if (sim.outputWeirCockerham || sim.outputWeirHill) { outPar << "Neutral genetics - every " << sim.outputGeneticInterval << " year"; if (sim.outputGeneticInterval > 1) outPar << "s"; - if (sim.outputPairwiseFst) outPar << " outputting pairwise patch fst"; - if (sim.outputPerLocusWCFstat) outPar << " outputting per locus fst "; + if (sim.outputWeirHill) outPar << " outputting pairwise patch fst"; + if (sim.outputWeirCockerham) outPar << " outputting per locus fst "; outPar << endl; } diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 894c043..e6d2ac0 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -30,6 +30,8 @@ NeutralStatsManager::NeutralStatsManager(const int& nbSampledPatches, const int nLoci) { this->pairwiseFstMatrix = PatchMatrix(nbSampledPatches, nbSampledPatches); commNeutralCountTables.reserve(nLoci); //don't have to be pointers, not shared or moved + + perLocusFst = perLocusFis = perLocusFit = vector(nLoci, 0.0); } // ---------------------------------------------------------------------------------------- @@ -282,6 +284,9 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int unsigned int nbPops = 0; const int totalSampleSize = nbSampledIndsInComm; // r * n_bar + // Reset per-locus vectors between generations + perLocusFst = perLocusFis = perLocusFit = vector(nLoci, 0.0); + for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); @@ -308,46 +313,63 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int double var; double s2, pBar, hBar; - double s2Denom = 1.0 / ((nbPops - 1) * nBar); + double s2Denom = (nbPops - 1) * nBar; double rTerm = static_cast(nbPops - 1) / nbPops; double hBarFactor = (2 * nBar - 1) / (4 * nBar); - double a = 0, b = 0, c = 0, intermediateTerm; - for (int thisLocus = 0; thisLocus < nLoci; ++thisLocus) { - for (int allele = 0; allele < nAlleles; ++allele) { + double numFst = 0.0, numFis = 0.0, numFit = 0.0; + double denomFst = 0.0, denomFis = 0.0, denomFit = 0.0; + + double a_l = 0, b_l = 0, c_l = 0, intermediateTerm; + for (int l = 0; l < nLoci; ++l) { + for (int u = 0; u < nAlleles; ++u) { s2 = hBar = 0; - pBar = commNeutralCountTables[thisLocus].getFrequency(allele); + pBar = commNeutralCountTables[l].getFrequency(u); for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop != 0) { - var = pPop->getAlleleFrequency(thisLocus, allele) - pBar; + var = pPop->getAlleleFrequency(l, u) - pBar; var *= var; s2 += var * pPop->sampleSize(); - hBar += pPop->getHeteroTally(thisLocus, allele); // n_i * h_i + hBar += pPop->getHeteroTally(l, u); // n_i * h_i } } //end for pop - s2 *= s2Denom; - hBar *= inverseNtotal; // / (r * n_bar) + s2 /= s2Denom; + hBar /= static_cast(totalSampleSize); // / (r * n_bar) intermediateTerm = pBar * (1 - pBar) - rTerm * s2; - a += s2 - inverseNbar * (intermediateTerm - 0.25 * hBar); - b += intermediateTerm - hBarFactor * hBar; - c += hBar; + a_l += s2 - inverseNbar * (intermediateTerm - 0.25 * hBar); + b_l += intermediateTerm - hBarFactor * hBar; + c_l += hBar; + } // end for allele + + a_l *= nBar / nC; + b_l *= nBar / nBarMinusOne; + c_l *= 0.5; + + perLocusFst[l] = a_l / (a_l + b_l + c_l); + perLocusFis[l] = (b_l + c_l) == 0.0 ? 0.0 : b_l / (b_l + c_l); + perLocusFit[l] = a_l + b_l / (a_l + b_l + c_l); + + numFst += a_l; + numFis += b_l; + numFit += a_l + b_l; + denomFst += a_l + b_l + c_l; + denomFis += b_l + c_l; + } // end for locus - a *= nBar / nC; - b *= nBar / nBarMinusOne; - c *= 0.5; + denomFit = denomFst; // same quantity - fst = a / (a + b + c); // theta hat in eq. 1 in WC 1984 - fis = (b + c == 0.0) ? 0.0 : b / (b + c); // f hat - fit = (a + b) / (a + b + c); // F hat + fst = numFst / denomFst; // theta hat in eq. 1 in WC 1984 + fis = (denomFis == 0.0) ? 0.0 : numFis / denomFis; // f hat + fit = numFit / denomFit; // F hat } - else { // zero or one sampled pops, cannot compute F stats + else { // zero or one sampled pops, cannot compute F-stats fst = 0.0; fis = 0.0; fit = 0.0; diff --git a/Parameters.cpp b/Parameters.cpp index 6b47f06..0513ded 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -223,7 +223,7 @@ paramSim::paramSim(void) { batchMode = absorbing = false; outRange = outOccup = outPop = outInds = false; outTraitsCells = outTraitsRows = outConnect = false; - outputWCFstat = outputPerLocusWCFstat = outputPairwiseFst = false; + outputWeirCockerham = outputWeirHill = false; saveMaps = false; saveTraitMaps = false; saveVisits = false; #if RS_RCPP @@ -273,12 +273,11 @@ void paramSim::setSim(simParams s) { fixReplicateSeed = s.fixReplicateSeed; } -void paramSim::setGeneticSim(string patchSamplingOption, bool outputGeneticValues, bool outputWCFstat, bool outputPerLocusWCFstat, bool outputPairwiseFst, int outputStartGenetics, int outputGeneticInterval) { +void paramSim::setGeneticSim(string patchSamplingOption, bool outputGeneticValues, bool outputWeirCockerham, bool outputWeirHill, int outputStartGenetics, int outputGeneticInterval) { this->patchSamplingOption = patchSamplingOption; this->outputGenes = outputGeneticValues; - this->outputWCFstat = outputWCFstat; - this->outputPerLocusWCFstat = outputPerLocusWCFstat; - this->outputPairwiseFst = outputPairwiseFst; + this->outputWeirCockerham = outputWeirCockerham; + this->outputWeirHill = outputWeirHill; this->outputStartGenetics = outputStartGenetics; this->outputGeneticInterval = outputGeneticInterval; } @@ -312,9 +311,8 @@ simParams paramSim::getSim(void) { #endif s.patchSamplingOption = patchSamplingOption; s.outputGeneValues = outputGenes; - s.outputWCFstat = outputWCFstat; - s.outputPerLocusWCFstat = outputPerLocusWCFstat; - s.outputPairwiseFst = outputPairwiseFst; + s.outputWeirCockerham = outputWeirCockerham; + s.outputWeirHill = outputWeirHill; s.outStartGenetics = outputStartGenetics; s.outputGeneticInterval = outputGeneticInterval; diff --git a/Parameters.h b/Parameters.h index afbdea9..fffe64c 100644 --- a/Parameters.h +++ b/Parameters.h @@ -329,7 +329,7 @@ struct simParams { bool fixReplicateSeed; string patchSamplingOption; bool outputGeneValues; - bool outputWCFstat, outputPerLocusWCFstat, outputPairwiseFst; + bool outputWeirCockerham, outputWeirHill; int outputGeneticInterval, outStartGenetics; }; @@ -345,7 +345,7 @@ class paramSim { paramSim(void); ~paramSim(void); void setSim(simParams); - void setGeneticSim(string patchSamplingOption, bool outputGeneticValues, bool outputWCFstat, bool outputPerLocusWCFstat, bool outputPairwiseFst, int outputStartGenetics, int outputGeneticInterval); + void setGeneticSim(string patchSamplingOption, bool outputGeneticValues, bool outputWeirCockerham, bool outputWeirHill, int outputStartGenetics, int outputGeneticInterval); simParams getSim(void); int getSimNum(void); void setViews(simView); @@ -409,9 +409,8 @@ class paramSim { bool fixReplicateSeed; string patchSamplingOption; bool outputGenes; - bool outputWCFstat; - bool outputPerLocusWCFstat; - bool outputPairwiseFst; + bool outputWeirCockerham; + bool outputWeirHill; int outputStartGenetics; int outputGeneticInterval; }; diff --git a/Species.cpp b/Species.cpp index 96e207c..9d40655 100644 --- a/Species.cpp +++ b/Species.cpp @@ -450,7 +450,7 @@ void Species::addTrait(TraitType traitType, const SpeciesTrait& trait) { default: { cout << endl << ("Error:: Too many genetic load traits in Traits file, max = 5 \n"); - break; //should return false + break; } } } From 62a7d5c971fa6878bbeffb190f2a46a3e5f82d55 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 2 Sep 2024 18:12:45 +0100 Subject: [PATCH 239/332] rm unused function --- NeutralStatsManager.cpp | 171 ---------------------------------------- NeutralStatsManager.h | 1 - 2 files changed, 172 deletions(-) diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index e6d2ac0..3b23dde 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -376,177 +376,6 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int } } -// ---------------------------------------------------------------------------------------- -// Fstat Weir & Cockerham using Mean square approach. Similar to implementation in Hierfstat -// ---------------------------------------------------------------------------------------- -void NeutralStatsManager::calcPerLocusMeanSquaresFst(set const& patchList, const int nInds, const int nLoci, const int maxNbAllelesPerLocus, Species* pSpecies, Landscape* pLandscape) { - - double sumWeights = 0; - unsigned int nbExtantPops = 0; - const int ploidy = pSpecies->isDiploid() ? 2 : 1; - const int totSampleSize = nInds * ploidy; - - for (int patchId : patchList) { - const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - if (pPop != 0) { - int ni = pPop->sampleSize() * ploidy; - if (ni > 0) { - nbExtantPops++; - sumWeights += static_cast(ni * ni) / totSampleSize; - } - } - } - - // per locus stats, resize should only happen in first timestep of calculation: - if (perLocusFst.size() == 0) - perLocusFst.resize(nLoci); - if (perLocusFis.size() == 0) - perLocusFis.resize(nLoci); - if (perLocusFit.size() == 0) - perLocusFit.resize(nLoci); - - if (nbExtantPops > 1) { - vector nbAllelesEachLocus(nLoci); - bool** alleleExistsMatrix = new bool* [nLoci]; - for (int i = 0; i < nLoci; ++i) - alleleExistsMatrix[i] = new bool[maxNbAllelesPerLocus]; - - int nbAllelesInComm = 0; - for (int locus = 0; locus < nLoci; ++locus) { - nbAllelesEachLocus[locus] = 0; - for (int allele = 0; allele < maxNbAllelesPerLocus; ++allele) { - int count = 0; - for (int patchId : patchList) { - const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - if (pPop != 0) count += pPop->getAlleleTally(locus, allele); - } - alleleExistsMatrix[locus][allele] = count != 0; - nbAllelesEachLocus[locus] += count != 0; - } - nbAllelesInComm += nbAllelesEachLocus[locus]; - } - - // n, and nal are given by pop_sizes, same num ind typed at all loci in each patch - // nc is the same for each locus - // nt is given by tot_size, same tot num of ind typed for all loci - - //SSG: het/2 for each allele - vector SSG(nbAllelesInComm); - vector SSP(nbAllelesInComm); - vector SSi(nbAllelesInComm); - - int totalAlleleCounter = 0; - double het, pi, var, pBar; - int popSize; - - for (int locus = 0; locus < nLoci; ++locus) { - for (int allele = 0; allele < maxNbAllelesPerLocus && totalAlleleCounter < nbAllelesInComm; ++allele) { - - if (alleleExistsMatrix[locus][allele] == false) continue; //do not consider alleles not present in the pop - SSG[totalAlleleCounter] = 0; - SSi[totalAlleleCounter] = 0; - SSP[totalAlleleCounter] = 0; - - for (int patchId : patchList) { - const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - if (pPop == 0) popSize = 0; - else popSize = pPop->sampleSize(); - if (popSize == 0) continue; // skip empty patches - - het = pPop->getHeteroTally(locus, allele); // ni * h_i - pi = pPop->getAlleleFrequency(locus, allele); - pBar = commNeutralCountTables[locus].getFrequency(allele); - var = pi - pBar; //(p_liu - pbar_u)^2 - var *= var; - - SSG[totalAlleleCounter] += het; // numerator MSG - SSi[totalAlleleCounter] += 2 * popSize * pi * (1 - pi) - het / 2; // numerator - SSP[totalAlleleCounter] += 2 * popSize * var; // numerator MSP - } - totalAlleleCounter++; - } - } - - if (totalAlleleCounter != nbAllelesInComm) - throw runtime_error("Error:: allele counter and total number of alleles differ in WC mean squared Fstat calculation \n"); - - vector MSG(nbAllelesInComm); - vector MSP(nbAllelesInComm); - vector MSI(nbAllelesInComm); - vector sigw(nbAllelesInComm); - vector siga(nbAllelesInComm); - vector sigb(nbAllelesInComm); - - double SIGA = 0, SIGB = 0, SIGW = 0; - - if (nbAllelesInComm != nLoci) { // more than one allele per locus - double nc = (totSampleSize - sumWeights) / (nbExtantPops - 1); - int MSiDenom = nInds == nbExtantPops ? 1 : nInds - nbExtantPops; // avoid /0 if exactly 1 ind per pop - - for (int i = 0; i < nbAllelesInComm; ++i) { - - MSG[i] = SSG[i] / (2 * nInds); - MSP[i] = SSP[i] / (nbExtantPops - 1); - MSI[i] = SSi[i] / MSiDenom; - - siga[i] = (MSP[i] - MSI[i]) / (2 * nc); - sigb[i] = 0.5 * (MSI[i] - MSG[i]); - sigw[i] = MSG[i]; - - SIGA += siga[i]; - SIGB += sigb[i]; - SIGW += sigw[i]; - } - - double locusSIGA, locusSIGB, locusSIGW; - int alleleCounter; - for (int locus = 0; locus < nLoci; ++locus) { - alleleCounter = 0; - locusSIGA = locusSIGB = locusSIGW = 0; - - for (int allele = 0; allele < nbAllelesEachLocus[locus]; ++allele) { - locusSIGA += siga[alleleCounter]; - locusSIGB += sigb[alleleCounter]; - locusSIGW += sigw[alleleCounter]; - alleleCounter++; - } - perLocusFst[locus] = locusSIGA / (locusSIGA + locusSIGB + locusSIGW); - perLocusFis[locus] = locusSIGB / (locusSIGB + locusSIGW); - perLocusFit[locus] = (locusSIGA + locusSIGB) / (locusSIGA + locusSIGB + locusSIGW); - } - - // Total F-stats - fst = SIGA / (SIGA + SIGB + SIGW); - fit = (SIGA + SIGB) / (SIGA + SIGB + SIGW); - fis = SIGB / (SIGB + SIGW); - } - else { // no variation: only 1 allele (wildtype) at each locus - // so don't calculate to avoid division by zero - fst = 0; - fis = 0; - fit = 0; - } - - // Deallocate matrix - for (int i = 0; i < nLoci; ++i) - delete[]alleleExistsMatrix[i]; - delete[]alleleExistsMatrix; - } - else { // zero or one sampled pops, cannot calculate Fst - for (int locus = 0; locus < nLoci; ++locus) { - perLocusFst[locus] = 0.0; - perLocusFis[locus] = 0.0; - perLocusFit[locus] = 0.0; - } - fst = 0; - fis = 0; - fit = 0; - } -} - // ---------------------------------------------------------------------------------------- // Patch pairwise Fst // Computes the weighted within and between patch Fst's as well as the overall Fst (Theta). diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index ca7d2c7..42e19ed 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -101,7 +101,6 @@ class NeutralStatsManager { // F-stats calculations void calculateFstatWC(set const& patchList, const int nInds, const int nLoci, const int nAlleles, Species* pSpecies, Landscape* pLandscape); - void calcPerLocusMeanSquaresFst(set const& patchList, const int nInds, const int nLoci, const int nAlleles, Species* pSpecies, Landscape* pLandscape); void calcPairwiseWeightedFst(set const& patchList, const int nInds, const int nLoci, Species* pSpecies, Landscape* pLandscape); // Getters From e6c977fa72fc4eb179b10000f3541d65bd3c0c17 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 3 Sep 2024 14:13:45 +0100 Subject: [PATCH 240/332] doc update --- Community.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Community.cpp b/Community.cpp index 149cbb5..2b012f6 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1661,7 +1661,7 @@ bool Community::openPerLocusFstFile(Species* pSpecies, Landscape* pLandscape, co } outperlocusfstat.open(name.c_str()); - outperlocusfstat << "Year\tRepSeason\tlocus\tFst\tFis\tFit\tpopHet"; + outperlocusfstat << "Year\tRepSeason\tLocus\tFst\tFis\tFit\tHet"; for (int patchId : patchList) { outperlocusfstat << "\tpatch_" + to_string(patchId) + "_Het"; } From 9fabc91115bda0642572b735ca5d38ca4c15d05e Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 3 Sep 2024 16:17:13 +0100 Subject: [PATCH 241/332] per locus fst are computed separately, fix #72 --- NeutralStatsManager.cpp | 7 ++- unit_tests/testNeutralStats.cpp | 87 +++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 2 deletions(-) diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 3b23dde..e20c2f4 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -311,7 +311,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int inverseNbar = 1.0 / nBarMinusOne; inverseNtotal = 1.0 / totalSampleSize; - double var; + double var, intermediateTerm; double s2, pBar, hBar; double s2Denom = (nbPops - 1) * nBar; double rTerm = static_cast(nbPops - 1) / nbPops; @@ -320,8 +320,11 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int double numFst = 0.0, numFis = 0.0, numFit = 0.0; double denomFst = 0.0, denomFis = 0.0, denomFit = 0.0; - double a_l = 0, b_l = 0, c_l = 0, intermediateTerm; for (int l = 0; l < nLoci; ++l) { + + // Sums of a_u, b_u, c_u for all alleles u at locus l + double a_l = 0, b_l = 0, c_l = 0; + for (int u = 0; u < nAlleles; ++u) { s2 = hBar = 0; diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index fb295d0..ea9eb3b 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -970,6 +970,93 @@ void testNeutralStats() { ); assert(pNeutralStatistics->getFstWC() == refWeirCockerhamDiploidFst); } + + // Multi-locus case + // First locus has no variation between individuals, all heterozygotes (Fst = 0) + // Second locus has different fixed alleles between both populations (Fst = 1) + { + // Patch setup + const int nbPatches = 2; + const int nbIndsPerPop = 10; + // Genetic setup + const int genomeSz = 3; + const bool isDiploid{ true }; + const set genePositions = { 0, 2 }; // position 1 is arbitrarily empty + const float maxAlleleVal = 1; + unsigned char alleleValPopA = char(0); + unsigned char alleleValPopB = char(1); + map> genotypePop1; + map> genotypePop2; + // First locus: all heterozygotes, same genotype + genotypePop1.emplace(0, vector{alleleValPopA, alleleValPopB}); + genotypePop2.emplace(0, vector{alleleValPopA, alleleValPopB}); + // Second locus: different fixed alleles + genotypePop1.emplace(2, vector{alleleValPopA, alleleValPopA}); + genotypePop2.emplace(2, vector{alleleValPopB, alleleValPopB}); + + // Create two-patches landscape + Landscape* pLandscape = new Landscape; + vector patches(nbPatches); + vector cells(nbPatches); + set patchList; + for (int i = 0; i < nbPatches; i++) { + patches[i] = pLandscape->newPatch(i); + cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + patches[i]->addCell(cells[i], 0, 0); + patchList.insert(patches[i]->getPatchNum()); + } + const string indSampling = "all"; + const set stgToSample = { 1 }; + + // Create species trait structure + Species* pSpecies = new Species(); + pSpecies->setDemogr(createDefaultDiploidDemogrParams()); + pSpecies->setGeneticParameters( + set{genomeSz - 1}, // single chromosome + genomeSz, + 0.0, // no recombination + patchList, + indSampling, + stgToSample, + 1 + ); + const int nbLoci = genePositions.size(); + SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); + pSpecies->addTrait(TraitType::NEUTRAL, *spTr); + + // Initialise populations + const int indStg = 1; + for (int p = 0; p < patches.size(); p++) { + Population* pPop = new Population(pSpecies, patches[p], 0, 1); + // create individuals and add to pop + for (int i = 0; i < nbIndsPerPop; i++) { + Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + pInd->setUpGenes(pSpecies, 1.0); + pInd->overrideGenotype(NEUTRAL, p == 0 ? genotypePop1 : genotypePop2); + pPop->recruit(pInd); + } + pPop->sampleIndsWithoutReplacement(indSampling, { indStg }); + } + + // Compute F-stats + auto pNeutralStatistics = make_unique(nbPatches, nbLoci); + pNeutralStatistics->updateAllNeutralTables( + pSpecies, + pLandscape, + patchList + ); + const int maxNbNeutralAlleles = static_cast(maxAlleleVal) + 1; + pNeutralStatistics->calculateFstatWC( + patchList, + nbIndsPerPop * patchList.size(), + nbLoci, + maxNbNeutralAlleles, + pSpecies, + pLandscape + ); + assert(pNeutralStatistics->getPerLocusFst(0) == 0.0); + assert(pNeutralStatistics->getPerLocusFst(1) == 1.0); + } } #endif // RSDEBUG \ No newline at end of file From 1317d2fec0351e904c20e84e879893801b7bb71a Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Wed, 4 Sep 2024 09:07:37 +0200 Subject: [PATCH 242/332] bugfix for github check renamed trfrRules to transferRules --- Population.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Population.cpp b/Population.cpp index 9d36a58..d479682 100644 --- a/Population.cpp +++ b/Population.cpp @@ -878,7 +878,7 @@ void Population::emigration(float localK) stageParams sstruct = pSpecies->getStageParams(); emigRules emig = pSpecies->getEmigRules(); emigTraits eparams; - trfrRules trfr = pSpecies->getTrfr(); + transferRules trfr = pSpecies->getTransferRules(); indStats ind; // to avoid division by zero, assume carrying capacity is at least one individual From 4ec1690a09bcbfdc740242a625b5eafe165151fd Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Wed, 4 Sep 2024 09:24:43 +0200 Subject: [PATCH 243/332] added unit_tests in CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1de0c03..6f10756 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ if (NOT batchmode) # that is, RScore as a standalone set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) - add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Management.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) + add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Management.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp "unit_tests/testIndividual.cpp" "unit_tests/testNeutralStats.cpp" "unit_tests/testPopulation.cpp") else() # that is, RScore compiled as library within RangeShifter_batch add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Management.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) From 3dcd269422276d07b4d3a437e8e0378b86136d2a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 4 Sep 2024 13:52:38 +0100 Subject: [PATCH 244/332] fix list reading --- Population.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Population.cpp b/Population.cpp index ec80930..4c3db0b 100644 --- a/Population.cpp +++ b/Population.cpp @@ -828,7 +828,8 @@ void Population::sampleIndsWithoutReplacement(string strNbToSample, const set toAdd = getIndividualsInStage(stage); + stagedInds.insert(stagedInds.begin(), toAdd.begin(), toAdd.end()); } if (strNbToSample == "all") { From 17107902b9397cb784998a74560cfc91af6e4a38 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 4 Sep 2024 15:19:58 +0100 Subject: [PATCH 245/332] fix patch headers for perLocusNeutralGenetics --- Community.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Community.cpp b/Community.cpp index 2b012f6..54b4c15 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1637,7 +1637,15 @@ bool Community::openNeutralOutputFile(Species* pSpecies, int landNr) bool Community::openPerLocusFstFile(Species* pSpecies, Landscape* pLandscape, const int landNr, const int rep) { - const set patchList = pSpecies->getSamplePatches(); + set patchList = pSpecies->getSamplePatches(); + if (patchList.size() == 0) { + // list of patches is not known yet and may change every generation, + // e.g. for randomOccupied sampling option + // instead, header patch numbers range from 1 to nb of sampled patches + for (int i = 0; i < pSpecies->getNbPatchesToSample(); i++) { + patchList.emplace(i + 1); + } + } if (landNr == -999) { // close the file if (outperlocusfstat.is_open()) outperlocusfstat.close(); From f431f71416472fba244928286c194c7d9287cb86 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 5 Sep 2024 12:29:33 +0100 Subject: [PATCH 246/332] fix output for only weir&hill case --- Community.cpp | 3 ++- Model.cpp | 2 +- NeutralStatsManager.cpp | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Community.cpp b/Community.cpp index 54b4c15..d07b7a9 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1830,7 +1830,7 @@ void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, const int maxNbNeutralAlleles = pSpecies->getSpTrait(NEUTRAL)->getNbNeutralAlleles(); const int nLoci = (int)pSpecies->getNPositionsForTrait(NEUTRAL); const set patchList = pSpecies->getSamplePatches(); - int nInds = 0; + int nInds = 0, nbPops = 0; for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); @@ -1840,6 +1840,7 @@ void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); if (pPop != 0) { // empty patches do not contribute nInds += pPop->sampleSize(); + nbPops++; } } diff --git a/Model.cpp b/Model.cpp index 6bd5110..a85dbc1 100644 --- a/Model.cpp +++ b/Model.cpp @@ -181,7 +181,7 @@ int RunModel(Landscape* pLandscape, int seqsim) if (!pLandscape->outConnectHeaders(0)) { filesOK = false; } - if (sim.outputWeirCockerham) { // open neutral genetics file + if (sim.outputWeirCockerham || sim.outputWeirHill) { // open neutral genetics file if (!pComm->openNeutralOutputFile(pSpecies, ppLand.landNum)) { filesOK = false; } diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index e20c2f4..0021bee 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -412,6 +412,7 @@ void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, con double denominator = 0; double sumWeights = 0; + totalNbSampledInds = nInds; totSize = nInds; // Calculate weight (n_ic) terms @@ -430,6 +431,8 @@ void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, con numeratorPairwiseFst[i][j] = 0; } + nbExtantPops = nbPops; + if (nbPops > 1) { // Calculate Fst numerators and denominators double p, pq, pBar, sqDist, num; From 505a3adc63d8dcae58726ea74ed4935bd12a6739 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 5 Sep 2024 15:33:32 +0100 Subject: [PATCH 247/332] scrap empty initialise --- NeutralTrait.cpp | 4 +--- NeutralTrait.h | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/NeutralTrait.cpp b/NeutralTrait.cpp index 41229fa..e5b32cc 100644 --- a/NeutralTrait.cpp +++ b/NeutralTrait.cpp @@ -52,11 +52,9 @@ NeutralTrait::NeutralTrait(SpeciesTrait* P) initialiseUniform(maxNeutralVal); break; } - case NONE: - break; default: { - throw logic_error("wrong parameter value for parameter \"initialisation of neutral trait\", must be left as default (#) or uniform \n"); + throw logic_error("wrong parameter value for parameter \"initialisation of neutral trait\", must be left uniform \n"); break; //should return false } } diff --git a/NeutralTrait.h b/NeutralTrait.h index 61db526..82419a5 100644 --- a/NeutralTrait.h +++ b/NeutralTrait.h @@ -66,7 +66,7 @@ class NeutralTrait : public QuantitativeTrait { map> genes; // Initialisation - void initialiseUniform(int max); //other option is that mutations map is empty until a mutation happens, default when empty is to return a 0 value for wildtype + void initialiseUniform(int max); // Immutable features, set at initialisation // and passed down to every subsequent trait copy From 5627cd330dc6b61d229fb7405d1e7d054915cc46 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 5 Sep 2024 16:14:45 +0100 Subject: [PATCH 248/332] fix issue if init max is larger than mutation max --- SpeciesTrait.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/SpeciesTrait.h b/SpeciesTrait.h index 1a87b02..bde77bd 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -54,7 +54,13 @@ class SpeciesTrait { int getNbNeutralAlleles() const { if (!traitType == NEUTRAL) throw logic_error("getNbNeutralAlleles() should only be called for neutral traits."); - else return getMutationParameters().find(MAX)->second + 1; // possible values range from 0 to MAX + else { + int maxAlleleVal = max( + getMutationParameters().find(MAX)->second + 1, + getInitialParameters().find(MAX)->second + 1 + ); // possible values range from 0 to MAX + return maxAlleleVal; + } } private: From 3e9ee12ad2d5ca0b0a9b0d9da9525fa63b991312 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 5 Sep 2024 16:15:05 +0100 Subject: [PATCH 249/332] dodge infinite loop is mutation max is zero --- NeutralTrait.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/NeutralTrait.cpp b/NeutralTrait.cpp index e5b32cc..e89ae54 100644 --- a/NeutralTrait.cpp +++ b/NeutralTrait.cpp @@ -109,10 +109,12 @@ void NeutralTrait::mutate_KAM() if (it == genes.end()) throw runtime_error("Locus selected for mutation doesn't exist."); auto currentChar = it->second[whichChromosome]; // current allele - do { - mut = (unsigned char)pRandom->IRandom(0, maxNeutralVal); - } while (mut == currentChar); // new allele value is different - + if (maxNeutralVal > 0) { // dodge the infinite loop + do { + mut = (unsigned char)pRandom->IRandom(0, maxNeutralVal); + } while (mut == currentChar); // new allele value is different + } + else mut = 0; it->second[whichChromosome] = mut; //overwrite with new value } } From adf77af2446b6a1b7162c9b1675d9e5d98356274 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 5 Sep 2024 16:50:02 +0100 Subject: [PATCH 250/332] add a bit more info if total extinction happens --- Model.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Model.cpp b/Model.cpp index a85dbc1..262715a 100644 --- a/Model.cpp +++ b/Model.cpp @@ -515,7 +515,11 @@ int RunModel(Landscape* pLandscape, int seqsim) } // end of the generation loop totalInds = pComm->totalInds(); - if (totalInds <= 0) { yr++; break; } + if (totalInds <= 0) { + cout << "All populations went extinct." << endl; + yr++; + break; + } // Connectivity Matrix if (sim.outConnect && ppLand.patchModel @@ -533,7 +537,12 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->outInds(rep, yr, -1, -1); // list any individuals dying having reached maximum age pComm->survival(1, 0, 1); // delete any such individuals totalInds = pComm->totalInds(); - if (totalInds <= 0) { yr++; break; } + if (totalInds <= 0) { + cout << "All populations went extinct." << endl; + yr++; + break; + + } } } // end of the years loop From bdab3ffe2c1e8fad56a6f6fe9e899553d781f27d Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 6 Sep 2024 13:44:18 +0100 Subject: [PATCH 251/332] why force setting move process to true?? --- Individual.cpp | 14 ++------------ Individual.h | 2 -- Population.cpp | 19 ++++++------------- 3 files changed, 8 insertions(+), 27 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 122cd68..0c84023 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -78,17 +78,6 @@ Individual::~Individual(void) { if (path != 0) delete path; } - -Individual* Individual::traitClone(Cell* pCell, Patch* pPatch, float probmale, bool movt, short moveType) { - - Individual* myTraitClone = new Individual(pCell, pPatch, 0, 0, 0, probmale, movt, moveType); - myTraitClone->pEmigTraits = make_unique(*pEmigTraits); - myTraitClone->pSettleTraits = make_unique(*pSettleTraits); - myTraitClone->pTrfrData->clone(*pTrfrData); - - return myTraitClone; -} - void Individual::setEmigTraits(const emigTraits& emig) { pEmigTraits = make_unique(emig); } @@ -389,7 +378,8 @@ void Individual::setSettPatch(const settlePatch s) { } void Individual::setEmigTraits(Species* pSpecies, bool sexDep, bool densityDep) { - emigTraits e; e.d0 = e.alpha = e.beta = 0.0; + emigTraits e; + e.d0 = e.alpha = e.beta = 0.0; if (sexDep) { if (this->getSex() == MAL) { e.d0 = this->getTrait(E_D0_M)->express(); diff --git a/Individual.h b/Individual.h index feac20c..6aa9adf 100644 --- a/Individual.h +++ b/Individual.h @@ -233,8 +233,6 @@ class Individual { void inherit(Species* pSpecies, const Individual* mother); // haploid - Individual* traitClone(Cell*, Patch*, float, bool, short); - void setEmigTraits(Species* pSpecies, bool sexDep, bool densityDep); void setTransferTraits(Species* pSpecies, transferRules trfr, int resol); diff --git a/Population.cpp b/Population.cpp index 4c3db0b..0a90555 100644 --- a/Population.cpp +++ b/Population.cpp @@ -174,14 +174,10 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) } } else age = stg; -#if RSDEBUG - // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... - inds.push_back(new Individual(pCell, pPatch, stg, age, sstruct.repInterval, - probmale, true, trfr.moveType)); -#else + inds.push_back(new Individual(pCell, pPatch, stg, age, sstruct.repInterval, - probmale, trfr.moveModel, trfr.moveType)); -#endif + probmale, trfr.usesMovtProc, trfr.moveType)); + sex = inds[nindivs + i]->getSex(); if (pSpecies->getNTraits() > 0) { // individual variation - set up genetics @@ -757,12 +753,9 @@ void Population::reproduction(const float localK, const float envval, const int pCell = pPatch->getRandomCell(); for (int j = 0; j < njuvs; j++) { Individual* newJuv; -#if RSDEBUG - // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... - newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, true, trfr.moveType); -#else - newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.moveModel, trfr.moveType); -#endif + + newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.usesMovtProc, trfr.moveType); + if (pSpecies->getNTraits() > 0) { newJuv->inheritTraits(pSpecies, inds[i], father, resol); } From 9035771c59a10511ef5e63fe51f3cd2a52333ee9 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 6 Sep 2024 15:09:33 +0100 Subject: [PATCH 252/332] only set goal bias if enabled --- Individual.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Individual.cpp b/Individual.cpp index 0c84023..d638228 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -508,8 +508,8 @@ void Individual::setIndSMSTraits(Species* pSpecies) { double dp, gb, alphaDB, betaDB; dp = gb = alphaDB = betaDB = 0.0; dp = getTrait(SMS_DP)->express(); - gb = getTrait(SMS_GB)->express(); if (s.goalType == 2) { + gb = getTrait(SMS_GB)->express(); alphaDB = getTrait(SMS_ALPHADB)->express(); betaDB = getTrait(SMS_BETADB)->express(); } From 6312d4aca20fedd198f2a1f46f6eac800ed6158a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 10 Sep 2024 11:19:57 +0100 Subject: [PATCH 253/332] unnecessary arrays --- NeutralStatsManager.cpp | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 0021bee..44cd01b 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -113,12 +113,9 @@ void NeutralStatsManager::calcAllelicDiversityMetrics(set const& patchList, double meanAllelicDivInPatch = 0; bool alleleExistsInPop = 0; - bool** alleleExistsInCommTable; - alleleExistsInCommTable = new bool* [nLoci]; + vector> alleleExistsInCommTable(nLoci); for (i = 0; i < nLoci; ++i) { - alleleExistsInCommTable[i] = new bool[nAlleles]; - for (j = 0; j < nAlleles; ++j) - alleleExistsInCommTable[i][j] = 0; + alleleExistsInCommTable[i] = vector(nAlleles, false); } // Compute mean nb alleles per locus per patch @@ -133,7 +130,7 @@ void NeutralStatsManager::calcAllelicDiversityMetrics(set const& patchList, for (j = 0; j < nAlleles; ++j) { alleleExistsInPop = pPop->getAlleleTally(i, j) != 0; nbAllelesInPatch += alleleExistsInPop; - alleleExistsInCommTable[i][j] |= alleleExistsInPop; // OR operator + alleleExistsInCommTable[i][j] = alleleExistsInCommTable[i][j] || alleleExistsInPop; } // add mean nb of alleles per locus for Patch k to the pop mean meanAllelicDivInPatch += static_cast(nbAllelesInPatch) / nLoci; @@ -148,11 +145,7 @@ void NeutralStatsManager::calcAllelicDiversityMetrics(set const& patchList, for (j = 0; j < nAlleles; ++j) meanNbAllelesPerLocus += alleleExistsInCommTable[i][j]; meanNbAllelesPerLocus /= nLoci; - // Clear table - for (i = 0; i < nLoci; ++i) - delete[] alleleExistsInCommTable[i]; - delete[] alleleExistsInCommTable; - + // Compute number of fixed loci per patch // mean number of loci that are fixed at pop level per pop meanNbFixedLociPerPatch = 0; @@ -405,8 +398,8 @@ void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, con //init vector popWeights(nPatches); vector popSizes(nPatches); - double** numeratorPairwiseFst = new double* [nPatches]; - for (int i = 0; i < nPatches; i++) numeratorPairwiseFst[i] = new double[nPatches]; + vector> numeratorPairwiseFst(nPatches); + for (int i = 0; i < nPatches; i++) numeratorPairwiseFst[i].resize(nPatches); double totSize; double numeratorWeightedFst = 0; double denominator = 0; @@ -510,10 +503,6 @@ void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, con else { weightedFst = 0.0; } - - // Deallocate pairwise Fst matrix - for (int i = 0; i < nPatches; i++) delete[] numeratorPairwiseFst[i]; - delete[] numeratorPairwiseFst; } else { // zero or one pop, cannot calculate Fst // pairwiseFstMatrix keeps default values (0) From fe428f170d1135361efd0d94ec230dacaa81b3d1 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 10 Sep 2024 11:45:51 +0100 Subject: [PATCH 254/332] trying out smart pointers --- Cell.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Cell.cpp b/Cell.cpp index 85fa78c..7f1e566 100644 --- a/Cell.cpp +++ b/Cell.cpp @@ -182,7 +182,9 @@ unsigned long int Cell::getVisits(void) { return visits; } // Initial species distribution cell functions DistCell::DistCell(int xx, int yy) { - x = xx; y = yy; initialise = false; + x = xx; + y = yy; + initialise = false; } DistCell::~DistCell() { @@ -201,7 +203,10 @@ bool DistCell::toInitialise(locn loc) { bool DistCell::selected(void) { return initialise; } locn DistCell::getLocn(void) { - locn loc; loc.x = x; loc.y = y; return loc; + locn loc; + loc.x = x; + loc.y = y; + return loc; } //--------------------------------------------------------------------------- From 807eff037651a4efd8720e1fadebdc37dc9814af Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 10 Sep 2024 12:04:54 +0100 Subject: [PATCH 255/332] replace RSDEBUG with standard NDEBUG --- Community.cpp | 14 +++++++------- DispersalTrait.cpp | 6 +++--- DispersalTrait.h | 6 +++--- GeneticFitnessTrait.cpp | 4 ++-- GeneticFitnessTrait.h | 2 +- Individual.cpp | 6 +++--- Individual.h | 4 ++-- Landscape.cpp | 12 ++++++------ Landscape.h | 2 +- Model.cpp | 6 +++--- Model.h | 2 +- NeutralTrait.cpp | 4 ++-- NeutralTrait.h | 4 ++-- Parameters.h | 2 +- Patch.cpp | 8 -------- Patch.h | 2 +- Population.cpp | 12 ++++++------ Population.h | 6 +++--- QuantitativeTrait.h | 2 +- RSrandom.cpp | 25 ++++++++++++++----------- RSrandom.h | 6 +++--- Species.cpp | 4 ++-- Species.h | 4 ++-- SpeciesTrait.cpp | 5 ++--- SpeciesTrait.h | 5 ++--- SubCommunity.cpp | 4 ---- unit_tests/testIndividual.cpp | 4 ++-- unit_tests/testNeutralStats.cpp | 4 ++-- unit_tests/testPopulation.cpp | 4 ++-- 29 files changed, 79 insertions(+), 90 deletions(-) diff --git a/Community.cpp b/Community.cpp index d07b7a9..9c3a08e 100644 --- a/Community.cpp +++ b/Community.cpp @@ -411,7 +411,7 @@ void Community::dispersal(short landIx, short nextseason) void Community::dispersal(short landIx) #endif // RS_RCPP { -#if RSDEBUG +#ifndef NDEBUG time_t t0, t1, t2; t0 = time(0); #endif @@ -424,7 +424,7 @@ void Community::dispersal(short landIx) for (int i = 0; i < nsubcomms; i++) { // all populations subComms[i]->initiateDispersal(matrix); } -#if RSDEBUG +#ifndef NDEBUG t1 = time(0); DEBUGLOG << "Community::dispersal(): this=" << this << " nsubcomms=" << nsubcomms << " initiation time=" << t1 - t0 << endl; @@ -445,7 +445,7 @@ void Community::dispersal(short landIx) matrix->completeDispersal(pLandscape, sim.outConnect); } while (ndispersers > 0); -#if RSDEBUG +#ifndef NDEBUG DEBUGLOG << "Community::dispersal(): matrix=" << matrix << endl; t2 = time(0); DEBUGLOG << "Community::dispersal(): transfer time=" << t2 - t1 << endl; @@ -508,7 +508,7 @@ void Community::createOccupancy(int nrows, int reps) { void Community::updateOccupancy(int row, int rep) { -#if RSDEBUG +#ifndef NDEBUG DEBUGLOG << "Community::updateOccupancy(): row=" << row << endl; #endif int nsubcomms = (int)subComms.size(); @@ -630,7 +630,7 @@ bool Community::outRangeHeaders(Species* pSpecies, int landNr) transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); -#if RSDEBUG +#ifndef NDEBUG DEBUGLOG << "Community::outRangeHeaders(): simulation=" << sim.simulation << " sim.batchMode=" << sim.batchMode << " landNr=" << landNr << endl; @@ -720,7 +720,7 @@ bool Community::outRangeHeaders(Species* pSpecies, int landNr) } outrange << endl; -#if RSDEBUG +#ifndef NDEBUG DEBUGLOG << "Community::outRangeHeaders(): finished" << endl; #endif @@ -730,7 +730,7 @@ bool Community::outRangeHeaders(Species* pSpecies, int landNr) // Write record to range file void Community::outRange(Species* pSpecies, int rep, int yr, int gen) { -#if RSDEBUG +#ifndef NDEBUG DEBUGLOG << "Community::outRange(): rep=" << rep << " yr=" << yr << " gen=" << gen << endl; #endif diff --git a/DispersalTrait.cpp b/DispersalTrait.cpp index be66d93..5d27cb9 100644 --- a/DispersalTrait.cpp +++ b/DispersalTrait.cpp @@ -462,7 +462,7 @@ float DispersalTrait::getDomCoefAtLocus(short whichChromosome, int position) con return it->second[whichChromosome]->getDominanceCoef(); } -#if RSDEBUG // Testing only +#ifndef NDEBUG // Testing only // Get allele ID at locus int DispersalTrait::getAlleleIDAtLocus(short whichChromosome, int position) const { @@ -473,7 +473,7 @@ int DispersalTrait::getAlleleIDAtLocus(short whichChromosome, int position) cons } #endif -#if RSDEBUG +#ifndef NDEBUG // Create a default set of alleles for testing // @@ -500,4 +500,4 @@ map>> createTestGenotype( } return genotype; } -#endif // RSDEBUG \ No newline at end of file +#endif // NDEBUG \ No newline at end of file diff --git a/DispersalTrait.h b/DispersalTrait.h index 76a76ab..97bde41 100644 --- a/DispersalTrait.h +++ b/DispersalTrait.h @@ -46,7 +46,7 @@ class DispersalTrait : public QuantitativeTrait { int countHeterozygoteLoci() const; bool isHeterozygoteAtLocus(int locus) const override; -#if RSDEBUG // for testing only +#ifndef NDEBUG // for testing only void overwriteGenes(map>> genSeq) { genes = genSeq; } @@ -95,7 +95,7 @@ class DispersalTrait : public QuantitativeTrait { float expressAdditive(); }; -#if RSDEBUG +#ifndef NDEBUG // Test utilities map>> createTestGenotype( @@ -105,6 +105,6 @@ map>> createTestGenotype( const float domCoeffA = 1.0, // default for dispersal traits const float domCoeffB = 1.0 ); -#endif //RSDEBUG +#endif // NDEBUG #endif // DISPTRAITH \ No newline at end of file diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index 2de095f..c3b4fbf 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -434,7 +434,7 @@ float GeneticFitnessTrait::getDomCoefAtLocus(short whichChromosome, int position return it->second[whichChromosome] == 0 ? wildType->getDominanceCoef() : it->second[whichChromosome]->getDominanceCoef(); } -#if RSDEBUG // Testing only +#ifndef NDEBUG // Testing only // Get allele ID at locus int GeneticFitnessTrait::getAlleleIDAtLocus(short whichChromosome, int position) const { auto it = genes.find(position); @@ -443,4 +443,4 @@ int GeneticFitnessTrait::getAlleleIDAtLocus(short whichChromosome, int position) return it->second[whichChromosome].get()->getId(); } -#endif // RSDEBUG \ No newline at end of file +#endif // NDEBUG \ No newline at end of file diff --git a/GeneticFitnessTrait.h b/GeneticFitnessTrait.h index ebb6e76..3db23cf 100644 --- a/GeneticFitnessTrait.h +++ b/GeneticFitnessTrait.h @@ -49,7 +49,7 @@ class GeneticFitnessTrait : public QuantitativeTrait { virtual float getDomCoefAtLocus(short chromosome, int position) const override; virtual int countHeterozygoteLoci() const; virtual bool isHeterozygoteAtLocus(int locus) const override; -#if RSDEBUG // for testing only +#ifndef NDEBUG // for testing only int getAlleleIDAtLocus(short whichChromosome, int position) const; #endif diff --git a/Individual.cpp b/Individual.cpp index d638228..393a357 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -738,7 +738,7 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, const bool ny = yrand + dist * cos(rndangle); if (nx < 0.0) newX = -1; else newX = (int)nx; if (ny < 0.0) newY = -1; else newY = (int)ny; -#if RSDEBUG +#ifndef NDEBUG if (path != 0) (path->year)++; #endif loopsteps++; @@ -1596,7 +1596,7 @@ double cauchy(double location, double scale) { //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -#if RSDEBUG +#ifndef NDEBUG // Testing utilities Cell* Individual::getCurrCell() const { @@ -1664,5 +1664,5 @@ void Individual::overrideGenotype(TraitType whichTrait, const mapgetGenes() = newGenotype; }; -#endif // RSDEBUG +#endif // NDEBUG diff --git a/Individual.h b/Individual.h index 6aa9adf..b7485b6 100644 --- a/Individual.h +++ b/Individual.h @@ -341,7 +341,7 @@ class Individual { const int // year ); #endif -#if RSDEBUG +#ifndef NDEBUG // Testing utilities Cell* getCurrCell() const; void setInitAngle(const float angle); @@ -395,7 +395,7 @@ double wrpcauchy(double location, double rho = exp(double(-1))); extern RSrandom* pRandom; -#if RSDEBUG +#ifndef NDEBUG extern ofstream DEBUGLOG; #endif diff --git a/Landscape.cpp b/Landscape.cpp index 05d9a9b..013d171 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -1125,7 +1125,7 @@ int Landscape::readLandChange(int filenum, bool costs) #endif { -#if RSDEBUG +#ifndef NDEBUG DEBUGLOG << "Landscape::readLandChange(): filenum=" << filenum << " costs=" << int(costs) << endl; #endif @@ -1600,7 +1600,7 @@ void Landscape::createCostsChgMatrix(void) } void Landscape::recordCostChanges(int landIx) { -#if RSDEBUG +#ifndef NDEBUG DEBUGLOG << "Landscape::recordCostChanges(): landIx=" << landIx << endl; #endif if (costsChgMatrix == 0) return; // should not occur @@ -2289,7 +2289,7 @@ int Landscape::readCosts(string fname) int maxcost = 0; -#if RSDEBUG +#ifndef NDEBUG #if BATCH DEBUGLOG << "Landscape::readCosts(): fname=" << fname << endl; #endif @@ -2529,7 +2529,7 @@ void Landscape::outPathsHeaders(int rep, int option) outMovePaths << "Year\tIndID\tStep\tx\ty\tStatus" << endl; } else { -#if RSDEBUG +#ifndef NDEBUG DEBUGLOG << "RunModel(): UNABLE TO OPEN MOVEMENT PATHS FILE" << endl; #endif outMovePaths.clear(); @@ -2650,7 +2650,7 @@ void Landscape::outVisits(int rep, int landNr) { //--------------------------------------------------------------------------- -#if RSDEBUG +#ifndef NDEBUG // Debug only: shortcut setup utilities Landscape createLandscapeFromCells(vector cells, const landParams& lp, Species sp) { @@ -2687,7 +2687,7 @@ landParams createDefaultLandParams(const int& dim) { void testLandscape() { // test coordinate system... } -#endif // RSDEBUG +#endif // NDEBUG //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- diff --git a/Landscape.h b/Landscape.h index 2af686d..f075471 100644 --- a/Landscape.h +++ b/Landscape.h @@ -530,7 +530,7 @@ extern paramInit* paramsInit; extern paramSim* paramsSim; extern RSrandom* pRandom; -#if RSDEBUG +#ifndef NDEBUG extern ofstream DEBUGLOG; landParams createDefaultLandParams(const int& dim); void testLandscape(); diff --git a/Model.cpp b/Model.cpp index 262715a..48f4e99 100644 --- a/Model.cpp +++ b/Model.cpp @@ -409,7 +409,7 @@ int RunModel(Landscape* pLandscape, int seqsim) for (int gen = 0; gen < dem.repSeasons; gen++) // generation loop { -#if RSDEBUG +#ifndef NDEBUG // TEMPORARY RANDOM STREAM CHECK if (yr % 1 == 0) { @@ -718,13 +718,13 @@ bool CheckDirectory(void) //For outputs and population visualisations pre-reproduction void PreReproductionOutput(Landscape* pLand, Community* pComm, int rep, int yr, int gen) { -#if RSDEBUG +#ifndef NDEBUG landParams ppLand = pLand->getLandParams(); #endif simParams sim = paramsSim->getSim(); simView v = paramsSim->getViews(); -#if RSDEBUG +#ifndef NDEBUG DEBUGLOG << "PreReproductionOutput(): 11111 rep=" << rep << " yr=" << yr << " gen=" << gen << " landNum=" << ppLand.landNum << " maxX=" << ppLand.maxX << " maxY=" << ppLand.maxY << endl; diff --git a/Model.h b/Model.h index fd34697..ff2d191 100644 --- a/Model.h +++ b/Model.h @@ -61,7 +61,7 @@ using namespace std::filesystem; #endif -#if RSDEBUG +#ifndef NDEBUG extern ofstream DEBUGLOG; #endif diff --git a/NeutralTrait.cpp b/NeutralTrait.cpp index e89ae54..fb77350 100644 --- a/NeutralTrait.cpp +++ b/NeutralTrait.cpp @@ -290,7 +290,7 @@ float NeutralTrait::getAlleleValueAtLocus(short whichChromosome, int position) c return it->second[whichChromosome]; } -#if RSDEBUG // Testing only +#ifndef NDEBUG // Testing only // Get allele ID at locus int NeutralTrait::getAlleleIDAtLocus(short whichChromosome, int position) const { // for neutral genes this is the same as the allele value @@ -318,4 +318,4 @@ map> createTestNeutralGenotype( return genotype; } -#endif // RSDEBUG \ No newline at end of file +#endif // NDEBUG \ No newline at end of file diff --git a/NeutralTrait.h b/NeutralTrait.h index 82419a5..85eaec2 100644 --- a/NeutralTrait.h +++ b/NeutralTrait.h @@ -53,7 +53,7 @@ class NeutralTrait : public QuantitativeTrait { virtual int countHeterozygoteLoci() const; virtual bool isHeterozygoteAtLocus(int locus) const override; -#if RSDEBUG // for testing only +#ifndef NDEBUG // for testing only int getAlleleIDAtLocus(short whichChromosome, int position) const; #endif @@ -86,7 +86,7 @@ class NeutralTrait : public QuantitativeTrait { }; -#if RSDEBUG // for testing purposes only +#ifndef NDEBUG // for testing purposes only map> createTestNeutralGenotype( const int genomeSz, const bool isDiploid, const unsigned char valAlleleA, diff --git a/Parameters.h b/Parameters.h index fffe64c..fe480d2 100644 --- a/Parameters.h +++ b/Parameters.h @@ -415,7 +415,7 @@ class paramSim { int outputGeneticInterval; }; -#if RSDEBUG +#ifndef NDEBUG extern ofstream DEBUGLOG; #endif diff --git a/Patch.cpp b/Patch.cpp index f482879..93b5cf2 100644 --- a/Patch.cpp +++ b/Patch.cpp @@ -294,10 +294,6 @@ void Patch::resetPossSettlers(void) { // Record the presence of a potential settler within the Patch void Patch::incrPossSettler(Species* pSpecies, int sex) { -#if RSDEBUG - //DEBUGLOG << "Patch::incrPossSettler(): 5555: patchNum = " << patchNum - // << " sex = " << sex << endl; -#endif // NOTE: THE FOLLOWING OPERATION WILL NEED TO BE MADE SPECIES-SPECIFIC... if (sex >= 0 && sex < gMaxNbSexes) { nTemp[sex]++; @@ -306,10 +302,6 @@ void Patch::incrPossSettler(Species* pSpecies, int sex) { // Get number of a potential settlers within the Patch int Patch::getPossSettlers(Species* pSpecies, int sex) { -#if RSDEBUG - //DEBUGLOG << "Patch::getPossSettlers(): 5555: patchNum = " << patchNum - // << " sex = " << sex << endl; -#endif // NOTE: THE FOLLOWING OPERATION WILL NEED TO BE MADE SPECIES-SPECIFIC... if (sex >= 0 && sex < gMaxNbSexes) return nTemp[sex]; else return 0; diff --git a/Patch.h b/Patch.h index 1285daf..5dc4738 100644 --- a/Patch.h +++ b/Patch.h @@ -166,7 +166,7 @@ class Patch { extern paramStoch* paramsStoch; extern RSrandom* pRandom; -#if RSDEBUG +#ifndef NDEBUG extern ofstream DEBUGLOG; #endif diff --git a/Population.cpp b/Population.cpp index 0a90555..87f7223 100644 --- a/Population.cpp +++ b/Population.cpp @@ -671,7 +671,7 @@ void Population::reproduction(const float localK, const float envval, const int for (int j = 0; j < njuvs; j++) { Individual* newJuv; -#if RSDEBUG +#ifndef NDEBUG // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, true, trfr.moveType); #else @@ -1519,11 +1519,11 @@ void Population::clean(void) shuffle(inds.begin(), inds.end(), pRandom->getRNG()); #else -#if !RSDEBUG - // do not randomise individuals in RSDEBUG mode, as the function uses rand() +#ifdef NDEBUG + // do not randomise individuals in DEBUG mode, as the function uses rand() // and therefore the randomisation will differ between identical runs of RS shuffle(inds.begin(), inds.end(), pRandom->getRNG()); -#endif // !RSDEBUG +#endif // NDEBUG #endif // RS_RCPP } @@ -1699,7 +1699,7 @@ void Population::outIndsHeaders(int rep, int landNr, bool patchModel) outInds << "\tS0\tAlphaS\tBetaS"; } outInds << "\tDistMoved"; -#if RSDEBUG +#ifndef NDEBUG // ALWAYS WRITE NO. OF STEPS outInds << "\tNsteps"; #else @@ -1814,7 +1814,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, + (natalloc.y - loc.y) * (natalloc.y - loc.y))); outInds << "\t" << d; } -#if RSDEBUG +#ifndef NDEBUG // ALWAYS WRITE NO. OF STEPS steps = inds[i]->getSteps(); outInds << "\t" << steps.year; diff --git a/Population.h b/Population.h index ac978b3..7370ba0 100644 --- a/Population.h +++ b/Population.h @@ -229,10 +229,10 @@ class Population { vector countNbHeterozygotesEachLocus(); double computeHs(); -#if RSDEBUG +#ifndef NDEBUG // Testing only void clearInds() { inds.clear(); } // empty inds vector to avoid deallocating individual is used separately in test -#endif // RSDEBUG +#endif // NDEBUG private: short nStages; @@ -258,7 +258,7 @@ extern paramInit* paramsInit; extern paramSim* paramsSim; extern RSrandom* pRandom; -#if RSDEBUG +#ifndef NDEBUG extern ofstream DEBUGLOG; #endif diff --git a/QuantitativeTrait.h b/QuantitativeTrait.h index 7d0a0e4..1ab22c2 100644 --- a/QuantitativeTrait.h +++ b/QuantitativeTrait.h @@ -26,7 +26,7 @@ class QuantitativeTrait { virtual bool isHeterozygoteAtLocus(int loci) const = 0; virtual float express() = 0; virtual ~QuantitativeTrait() { } -#if RSDEBUG // for testing only +#ifndef NDEBUG // for testing only virtual int getAlleleIDAtLocus(short whichChromosome, int position) const = 0; #endif }; diff --git a/RSrandom.cpp b/RSrandom.cpp index 14758cc..ac1931b 100644 --- a/RSrandom.cpp +++ b/RSrandom.cpp @@ -26,7 +26,7 @@ #if !RS_RCPP -#if RSDEBUG +#ifndef NDEBUG #include "Parameters.h" extern paramSim* paramsSim; // ofstream RSRANDOMLOG; @@ -36,8 +36,8 @@ int RS_random_seed = 0; // C'tor RSrandom::RSrandom() { -#if RSDEBUG - // fixed seed +#ifndef NDEBUG + // fixed seed RS_random_seed = 666; #else // random seed @@ -48,11 +48,11 @@ RSrandom::RSrandom() { #else RS_random_seed = std::time(NULL); #endif -#endif // RSDEBUG +#endif // NDEBUG -#if BATCH && RSDEBUG +#ifndef NDEBUG DEBUGLOG << "RSrandom::RSrandom(): RS_random_seed=" << RS_random_seed << endl; -#endif // RSDEBUG +#endif // set up Mersenne Twister RNG gen = new mt19937(RS_random_seed); @@ -143,7 +143,8 @@ void RSrandom::fixNewSeed(int seed) { //--------------- 3.) R package version of RSrandom.cpp -#if RSDEBUG +#ifndef NDEBUG + #include "Parameters.h" extern paramSim* paramsSim; //ofstream RSRANDOMLOG; @@ -167,14 +168,14 @@ RSrandom::RSrandom(std::int64_t seed) std::random_device device; random_seed[2] = device(); #endif -#if BATCH && RSDEBUG +#ifndef NDEBUG DEBUGLOG << "RSrandom::RSrandom(): Generated random seed = "; #endif } else { // fixed seed random_seed[2] = seed; -#if BATCH && RSDEBUG +#ifndef NDEBUG DEBUGLOG << "RSrandom::RSrandom(): Use fixed seed = "; #endif } @@ -317,7 +318,8 @@ double RSrandom::Cauchy(double loc, double scale) { #endif // RS_RCPP -#if RSDEBUG && !RS_RCPP +#ifndef NDEBUG +#if !RS_RCPP void testRSrandom() { { @@ -339,5 +341,6 @@ double RSrandom::Cauchy(double loc, double scale) { assert(bern_trial == 0 || bern_trial == 1); } } -#endif // RSDEBUG +#endif +#endif // NDEBUG //--------------------------------------------------------------------------- diff --git a/RSrandom.h b/RSrandom.h index 0991483..ebbd95d 100644 --- a/RSrandom.h +++ b/RSrandom.h @@ -43,7 +43,7 @@ using namespace std; -#if RSDEBUG +#ifndef NDEBUG extern ofstream DEBUGLOG; #endif @@ -133,9 +133,9 @@ class RSrandom { #endif // !RS_RCPP -#if RSDEBUG +#ifndef NDEBUG void testRSrandom(); -#endif // RSDEBUG +#endif // NDEBUG //--------------------------------------------------------------------------- diff --git a/Species.cpp b/Species.cpp index 9d40655..80c1a1a 100644 --- a/Species.cpp +++ b/Species.cpp @@ -791,7 +791,7 @@ void Species::setSamplePatchList(const set& samplePatchList) { //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -#if RSDEBUG +#ifndef NDEBUG // For testing purposes only demogrParams createDefaultHaploidDemogrParams() { @@ -818,4 +818,4 @@ demogrParams createDefaultDiploidDemogrParams() { return d; } -#endif // RSDEBUG +#endif // NDEBUG diff --git a/Species.h b/Species.h index 5a82d1d..87124d3 100644 --- a/Species.h +++ b/Species.h @@ -573,11 +573,11 @@ class Species { //--------------------------------------------------------------------------- -#if RSDEBUG +#ifndef NDEBUG // For testing purposes only demogrParams createDefaultHaploidDemogrParams(); demogrParams createDefaultDiploidDemogrParams(); -#endif RSDEBUG +#endif NDEBUG //--------------------------------------------------------------------------- #endif diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 5ae7afc..8818cd3 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -185,8 +185,7 @@ bool SpeciesTrait::isValidTraitVal(const float& val) const { } } -#if RSDEBUG -// Testing only +#ifndef NDEBUG // Testing only // Create a default set of gene positions ranging from zero to genome size set createTestGenePositions(const int genomeSz) { @@ -271,4 +270,4 @@ SpeciesTrait* createTestNeutralSpTrait(const float& maxAlleleVal, const set return spTr; } -#endif // RSDEBUG +#endif // NDEBUG diff --git a/SpeciesTrait.h b/SpeciesTrait.h index bde77bd..43b7943 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -85,13 +85,12 @@ class SpeciesTrait { map mutationParameters; }; -#if RSDEBUG // Testing only - +#ifndef NDEBUG // Testing only // Create a default set of gene positions ranging from zero to genome size set createTestGenePositions(const int genomeSz); SpeciesTrait* createTestEmigSpTrait(const set& genePositions, const bool& isDiploid); SpeciesTrait* createTestGenLoadTrait(const set& genePositions, const bool& isDiploid); SpeciesTrait* createTestNeutralSpTrait(const float& maxAlleleVal, const set& genePositions, const bool& isDiploid); -#endif // RSDEBUG +#endif // NDEBUG #endif // SPECIESTRAITH \ No newline at end of file diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 7d5bd4c..a11a652 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -434,10 +434,6 @@ void SubCommunity::ageIncrement(void) { // Find the population of a given species in a given patch Population* SubCommunity::findPop(Species* pSp, Patch* pPch) { -#if RSDEBUG - DEBUGLOG << "SubCommunity::findPop(): this=" << this - << endl; -#endif Population* pPop = 0; popStats pop; diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 3b17d0c..7e186b0 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -1,4 +1,4 @@ -#if RSDEBUG +#ifndef NDEBUG #include "../Individual.h" #include "../Population.h" @@ -1338,4 +1338,4 @@ void testIndividual() { } -#endif //RSDEBUG \ No newline at end of file +#endif //NDEBUG \ No newline at end of file diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index ea9eb3b..e01cdca 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -1,4 +1,4 @@ -#if RSDEBUG +#ifndef NDEBUG #include "../Community.h" @@ -1059,4 +1059,4 @@ void testNeutralStats() { } } -#endif // RSDEBUG \ No newline at end of file +#endif // NDEBUG \ No newline at end of file diff --git a/unit_tests/testPopulation.cpp b/unit_tests/testPopulation.cpp index 3bc64de..366c63c 100644 --- a/unit_tests/testPopulation.cpp +++ b/unit_tests/testPopulation.cpp @@ -1,4 +1,4 @@ -#if RSDEBUG +#ifndef NDEBUG #include "../Individual.h" #include "../Population.h" @@ -279,4 +279,4 @@ void testPopulation() } } -#endif //RSDEBUG \ No newline at end of file +#endif // NDEBUG \ No newline at end of file From 05e8a42322cc54f54438ad2a4849ced2fbf9f898 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 10 Sep 2024 13:40:52 +0100 Subject: [PATCH 256/332] fix missed renaming in release mode --- Population.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Population.cpp b/Population.cpp index 87f7223..f47464b 100644 --- a/Population.cpp +++ b/Population.cpp @@ -675,7 +675,7 @@ void Population::reproduction(const float localK, const float envval, const int // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, true, trfr.moveType); #else - newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.moveModel, trfr.moveType); + newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.usesMovtProc, trfr.moveType); #endif if (pSpecies->getNTraits() > 0) { @@ -1703,7 +1703,7 @@ void Population::outIndsHeaders(int rep, int landNr, bool patchModel) // ALWAYS WRITE NO. OF STEPS outInds << "\tNsteps"; #else - if (trfr.moveModel) outInds << "\tNsteps"; + if (trfr.usesMovtProc) outInds << "\tNsteps"; #endif outInds << endl; } @@ -1819,7 +1819,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, steps = inds[i]->getSteps(); outInds << "\t" << steps.year; #else - if (trfr.moveModel) { + if (trfr.usesMovtProc) { steps = inds[i]->getSteps(); outInds << "\t" << steps.year; } From 390765dfafd4e78d08a041ebdf1388743467b7bf Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 10 Sep 2024 14:59:29 +0100 Subject: [PATCH 257/332] rm last mentions of RSDEBUG --- CMakeLists.txt | 4 ---- RSrandom.cpp | 8 +++++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index daf71b1..8557f61 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,10 +20,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") add_compile_definitions("LINUX_CLUSTER") endif() -# Debug Mode by default, unless "release" is passed -if(NOT DEFINED release) - add_compile_definitions(RSDEBUG) -endif() if(NOT batchmode) target_include_directories(RScore PUBLIC "${PROJECT_BINARY_DIR}") diff --git a/RSrandom.cpp b/RSrandom.cpp index ac1931b..c7e309f 100644 --- a/RSrandom.cpp +++ b/RSrandom.cpp @@ -128,7 +128,7 @@ double RSrandom::Gamma(double shape, double scale) { //scale = mean/shape, shap double RSrandom::NegExp(double mean) { double r1 = 0.0000001 + this->Random() * (1.0 - 0.0000001); - double x = (-1.0 * mean) * log(r1); // for LINUX_CLUSTER + double x = (-1.0 * mean) * log(r1); return x; } @@ -181,8 +181,10 @@ RSrandom::RSrandom(std::int64_t seed) } RS_random_seed = random_seed[2]; -#if BATCH && RSDEBUG +#if BATCH +#ifndef NDEBUG DEBUGLOG << RS_random_seed << endl; +#endif #endif // set up Mersenne Twister random number generator with seed sequence @@ -259,7 +261,7 @@ double RSrandom::Gamma(double shape, double scale) { //scale = mean/shape, shap double RSrandom::NegExp(double mean) { double r1 = 0.0000001 + this->Random() * (1.0 - 0.0000001); - double x = (-1.0 * mean) * log(r1); // for LINUX_CLUSTER + double x = (-1.0 * mean) * log(r1); return x; } From d7306c0d362b234f65dcb7e2b58b289c679c9e44 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 11 Sep 2024 11:10:08 +0100 Subject: [PATCH 258/332] don't output gene values if genetics disabled --- Parameters.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Parameters.cpp b/Parameters.cpp index 0513ded..d987240 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -223,7 +223,7 @@ paramSim::paramSim(void) { batchMode = absorbing = false; outRange = outOccup = outPop = outInds = false; outTraitsCells = outTraitsRows = outConnect = false; - outputWeirCockerham = outputWeirHill = false; + outputGenes = outputWeirCockerham = outputWeirHill = false; saveMaps = false; saveTraitMaps = false; saveVisits = false; #if RS_RCPP From 5b606071118b2aed1faa6fba5eaabed82ce12160 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 11 Sep 2024 15:46:49 +0100 Subject: [PATCH 259/332] are these macro conditions necessary? --- Model.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Model.cpp b/Model.cpp index 48f4e99..f644178 100644 --- a/Model.cpp +++ b/Model.cpp @@ -125,15 +125,8 @@ int RunModel(Landscape* pLandscape, int seqsim) int npatches = pLandscape->patchCount(); for (int i = 0; i < npatches; i++) { ppp = pLandscape->getPatchData(i); -#if RSWIN64 -#if LINUX_CLUSTER pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES -#else - SubCommunity* pSubComm = pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES -#endif -#else pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES -#endif } if (sim.patchSamplingOption == "random") { // Then patches must be resampled for new landscape From 63059313fa970e689a4dba6ff080174dcdf4f2cf Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 11 Sep 2024 16:15:10 +0100 Subject: [PATCH 260/332] drop RSWIN64, except inside RCPP --- CMakeLists.txt | 3 --- Landscape.cpp | 24 ++++++++++++------------ Model.cpp | 7 ------- Parameters.h | 4 ---- 4 files changed, 12 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8557f61..0af07cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,9 +12,6 @@ else() # that is, RScore compiled as library within RangeShifter_batch add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) endif() -# pass config definitions to compiler -target_compile_definitions(RScore PRIVATE RSWIN64) - # enable LINUX_CLUSTER macro on Linux + macOS if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") add_compile_definitions("LINUX_CLUSTER") diff --git a/Landscape.cpp b/Landscape.cpp index 013d171..4a7f01f 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -171,14 +171,14 @@ int InitDist::readDistribution(string distfile) { #endif // open distribution file -#if !RS_RCPP || RSWIN64 - dfile.open(distfile.c_str()); -#else +#if RS_RCPP dfile.open(distfile, std::ios::binary); if (spdistraster.utf) { // apply BOM-sensitive UTF-16 facet dfile.imbue(std::locale(dfile.getloc(), new std::codecvt_utf16)); } +#else + dfile.open(distfile.c_str()); #endif if (!dfile.is_open()) return 21; @@ -1790,26 +1790,26 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string initParams init = paramsInit->getInit(); // open habitat file and optionally also patch file -#if !RS_RCPP || RSWIN64 - hfile.open(habfile.c_str()); -#else +#if RS_RCPP hfile.open(habfile, std::ios::binary); if (landraster.utf) { // apply BOM-sensitive UTF-16 facet hfile.imbue(std::locale(hfile.getloc(), new std::codecvt_utf16)); } +#else + hfile.open(habfile.c_str()); #endif if (!hfile.is_open()) return 11; if (fileNum == 0) { if (patchModel) { -#if !RS_RCPP || RSWIN64 - pfile.open(pchfile.c_str()); -#else +#if RS_RCPP pfile.open(pchfile, std::ios::binary); if (patchraster.utf) { // apply BOM-sensitive UTF-16 facet pfile.imbue(std::locale(pfile.getloc(), new std::codecvt_utf16)); } +#else + pfile.open(pchfile.c_str()); #endif if (!pfile.is_open()) { hfile.close(); hfile.clear(); @@ -2296,14 +2296,14 @@ int Landscape::readCosts(string fname) #endif // open cost file // open cost file -#if !RS_RCPP || RSWIN64 - costs.open(fname.c_str()); -#else +#if RS_RCPP costs.open(fname, std::ios::binary); if (costsraster.utf) { // apply BOM-sensitive UTF-16 facet costs.imbue(std::locale(costs.getloc(), new std::codecvt_utf16)); } +#else + costs.open(fname.c_str()); #endif // read headers and check that they correspond to the landscape ones costs >> header; diff --git a/Model.cpp b/Model.cpp index f644178..644d9b0 100644 --- a/Model.cpp +++ b/Model.cpp @@ -784,13 +784,6 @@ void OutParameters(Landscape* pLandscape) outPar << "RangeShifter 2.0 "; -#if !RS_RCPP -#if RSWIN64 - outPar << " - 64 bit implementation"; -#else - outPar << " - 32 bit implementation"; -#endif -#endif outPar << endl; outPar << "================ "; diff --git a/Parameters.h b/Parameters.h index fe480d2..7bd2569 100644 --- a/Parameters.h +++ b/Parameters.h @@ -74,11 +74,7 @@ constexpr int gMaxNbSexes = 2; // maximum number of sexes permitted #if RS_RCPP typedef intptr_t intptr; #else -#if RSWIN64 typedef unsigned long long intptr; -#else -typedef unsigned int intptr; -#endif #endif // RS_RCPP #if RS_RCPP From 209ad5e15c3aeafc24bd5e26986e572708853a36 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 12 Sep 2024 11:09:20 +0100 Subject: [PATCH 261/332] wrong default value --- NeutralTrait.h | 2 +- Parameters.h | 5 ----- Species.h | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/NeutralTrait.h b/NeutralTrait.h index 85eaec2..160abb0 100644 --- a/NeutralTrait.h +++ b/NeutralTrait.h @@ -90,7 +90,7 @@ class NeutralTrait : public QuantitativeTrait { map> createTestNeutralGenotype( const int genomeSz, const bool isDiploid, const unsigned char valAlleleA, - const unsigned char valAlleleB = -99.9 // if haploid + const unsigned char valAlleleB = char(0) // if haploid ); #endif diff --git a/Parameters.h b/Parameters.h index 7bd2569..b17c4a5 100644 --- a/Parameters.h +++ b/Parameters.h @@ -48,14 +48,9 @@ #ifndef ParametersH #define ParametersH - //#if LINUX_CLUSTER - //#include - //#else #include -//#endif #include #include -//#include #include #include #include diff --git a/Species.h b/Species.h index 87124d3..d2b7714 100644 --- a/Species.h +++ b/Species.h @@ -577,7 +577,7 @@ class Species { // For testing purposes only demogrParams createDefaultHaploidDemogrParams(); demogrParams createDefaultDiploidDemogrParams(); -#endif NDEBUG +#endif // NDEBUG //--------------------------------------------------------------------------- #endif From 84fa7c6948315c17b81900ab236e7e167c16043a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 19 Sep 2024 15:13:23 +0100 Subject: [PATCH 262/332] fix possible division by zero --- NeutralStatsManager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 44cd01b..7ae03ee 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -441,8 +441,9 @@ void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, con pBar = commNeutralCountTables[l].getFrequency(u); sqDist = p - pBar; //(p_liu - pbar_u)^2 sqDist *= sqDist; - - num = pq * popSizes[i] / (popSizes[i] - 1); // eq. 8 Weir & Hill 2002 + + num = pq * popSizes[i] ; // eq. 8 Weir & Hill 2002 + num /= popSizes[i] == 1 ? 1 : popSizes[i] - 1; // avoid division by zero numeratorPairwiseFst[i][i] += num; numeratorWeightedFst += num * popSizes[i]; // see equ. 9, Weir & Hill 2002 denominator += popSizes[i] * sqDist + popWeights[i] * pq; //common denominator @@ -498,7 +499,7 @@ void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, con // Estimator of global Fst weighted by sample sizes (beta_W in eq. 9 in WH 2002) if (denominator != 0) { - weightedFst = 1 - (numeratorWeightedFst * sumWeights) / (denominator * totSize); // beta_w in Eq. 9 in WH 2002 + weightedFst = 1 - (numeratorWeightedFst * sumWeights) / (denominator * totSize); // beta_w in Eq. 9 in WH 2002 } else { weightedFst = 0.0; From 64177e2710e960bd3a0ded4e57f14411a84b1c0a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 23 Sep 2024 17:51:54 +0100 Subject: [PATCH 263/332] fix misleading variable names --- SubCommunity.cpp | 176 +++++++++++++++++++++++++---------------------- 1 file changed, 92 insertions(+), 84 deletions(-) diff --git a/SubCommunity.cpp b/SubCommunity.cpp index a11a652..72f9c6e 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -695,10 +695,10 @@ bool SubCommunity::outTraitsHeaders(Landscape* pLandscape, Species* pSpecies, in } if (pSpecies->getNbGenLoadTraits() > 0) { if (gMaxNbSexes > 1) { - outtraits << "\tF_meanProbViable\tF_stdProbViable\tM_meanProbViable\tM_stdProbViable"; + outtraits << "\tF_meanGenFitness\tF_stdGenFitness\tM_meanGenFitness\tM_stdGenFitness"; } else { - outtraits << "\tmeanProbViable\tstdProbViable"; + outtraits << "\tmeanGenFitness\tstdGenFitness"; } } @@ -710,7 +710,7 @@ bool SubCommunity::outTraitsHeaders(Landscape* pLandscape, Species* pSpecies, in // Write records to traits file and return aggregated sums traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int gen, bool commlevel) { - int popsize, ngenes; + int popsize, ploidy; landParams land = pLandscape->getLandParams(); simParams sim = paramsSim->getSim(); bool writefile = false; @@ -762,37 +762,37 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge if (emig.indVar) { if (emig.sexDep) { // must be a sexual species - ngenes = 2; + ploidy = 2; } else { if (dem.repType == 0) { // asexual reproduction - ngenes = 1; + ploidy = 1; } else { // sexual reproduction - ngenes = 1; + ploidy = 1; } } double mnD0[2], mnAlpha[2], mnBeta[2], sdD0[2], sdAlpha[2], sdBeta[2]; - for (int iGene = 0; iGene < ngenes; iGene++) { - mnD0[iGene] = mnAlpha[iGene] = mnBeta[iGene] = sdD0[iGene] = sdAlpha[iGene] = sdBeta[iGene] = 0.0; + for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { + mnD0[whichChromosome] = mnAlpha[whichChromosome] = mnBeta[whichChromosome] = sdD0[whichChromosome] = sdAlpha[whichChromosome] = sdBeta[whichChromosome] = 0.0; // individuals may have been counted by sex if there was // sex dependency in another dispersal phase - if (ngenes == 2) popsize = indTraitsSums.ninds[iGene]; + if (ploidy == 2) popsize = indTraitsSums.ninds[whichChromosome]; else popsize = indTraitsSums.ninds[0] + indTraitsSums.ninds[1]; if (popsize > 0) { - mnD0[iGene] = indTraitsSums.sumD0[iGene] / (double)popsize; - mnAlpha[iGene] = indTraitsSums.sumAlpha[iGene] / (double)popsize; - mnBeta[iGene] = indTraitsSums.sumBeta[iGene] / (double)popsize; + mnD0[whichChromosome] = indTraitsSums.sumD0[whichChromosome] / (double)popsize; + mnAlpha[whichChromosome] = indTraitsSums.sumAlpha[whichChromosome] / (double)popsize; + mnBeta[whichChromosome] = indTraitsSums.sumBeta[whichChromosome] / (double)popsize; if (popsize > 1) { - sdD0[iGene] = indTraitsSums.ssqD0[iGene] / (double)popsize - mnD0[iGene] * mnD0[iGene]; - if (sdD0[iGene] > 0.0) sdD0[iGene] = sqrt(sdD0[iGene]); else sdD0[iGene] = 0.0; - sdAlpha[iGene] = indTraitsSums.ssqAlpha[iGene] / (double)popsize - mnAlpha[iGene] * mnAlpha[iGene]; - if (sdAlpha[iGene] > 0.0) sdAlpha[iGene] = sqrt(sdAlpha[iGene]); else sdAlpha[iGene] = 0.0; - sdBeta[iGene] = indTraitsSums.ssqBeta[iGene] / (double)popsize - mnBeta[iGene] * mnBeta[iGene]; - if (sdBeta[iGene] > 0.0) sdBeta[iGene] = sqrt(sdBeta[iGene]); else sdBeta[iGene] = 0.0; + sdD0[whichChromosome] = indTraitsSums.ssqD0[whichChromosome] / (double)popsize - mnD0[whichChromosome] * mnD0[whichChromosome]; + if (sdD0[whichChromosome] > 0.0) sdD0[whichChromosome] = sqrt(sdD0[whichChromosome]); else sdD0[whichChromosome] = 0.0; + sdAlpha[whichChromosome] = indTraitsSums.ssqAlpha[whichChromosome] / (double)popsize - mnAlpha[whichChromosome] * mnAlpha[whichChromosome]; + if (sdAlpha[whichChromosome] > 0.0) sdAlpha[whichChromosome] = sqrt(sdAlpha[whichChromosome]); else sdAlpha[whichChromosome] = 0.0; + sdBeta[whichChromosome] = indTraitsSums.ssqBeta[whichChromosome] / (double)popsize - mnBeta[whichChromosome] * mnBeta[whichChromosome]; + if (sdBeta[whichChromosome] > 0.0) sdBeta[whichChromosome] = sqrt(sdBeta[whichChromosome]); else sdBeta[whichChromosome] = 0.0; } else { - sdD0[iGene] = sdAlpha[iGene] = sdBeta[iGene] = 0.0; + sdD0[whichChromosome] = sdAlpha[whichChromosome] = sdBeta[whichChromosome] = 0.0; } } } @@ -820,58 +820,58 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge if (trfr.indVar) { if (trfr.usesMovtProc) { // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ngenes = 1; + ploidy = 1; } else { if (trfr.sexDep) { // must be a sexual species - ngenes = 2; + ploidy = 2; } else { - ngenes = 1; + ploidy = 1; } } double mnDist1[2], mnDist2[2], mnProp1[2], mnStepL[2], mnRho[2]; double sdDist1[2], sdDist2[2], sdProp1[2], sdStepL[2], sdRho[2]; double mnDP[2], mnGB[2], mnAlphaDB[2], mnBetaDB[2]; double sdDP[2], sdGB[2], sdAlphaDB[2], sdBetaDB[2]; - for (int iGene = 0; iGene < ngenes; iGene++) { - mnDist1[iGene] = mnDist2[iGene] = mnProp1[iGene] = mnStepL[iGene] = mnRho[iGene] = 0.0; - sdDist1[iGene] = sdDist2[iGene] = sdProp1[iGene] = sdStepL[iGene] = sdRho[iGene] = 0.0; - mnDP[iGene] = mnGB[iGene] = mnAlphaDB[iGene] = mnBetaDB[iGene] = 0.0; - sdDP[iGene] = sdGB[iGene] = sdAlphaDB[iGene] = sdBetaDB[iGene] = 0.0; + for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { + mnDist1[whichChromosome] = mnDist2[whichChromosome] = mnProp1[whichChromosome] = mnStepL[whichChromosome] = mnRho[whichChromosome] = 0.0; + sdDist1[whichChromosome] = sdDist2[whichChromosome] = sdProp1[whichChromosome] = sdStepL[whichChromosome] = sdRho[whichChromosome] = 0.0; + mnDP[whichChromosome] = mnGB[whichChromosome] = mnAlphaDB[whichChromosome] = mnBetaDB[whichChromosome] = 0.0; + sdDP[whichChromosome] = sdGB[whichChromosome] = sdAlphaDB[whichChromosome] = sdBetaDB[whichChromosome] = 0.0; // individuals may have been counted by sex if there was // sex dependency in another dispersal phase - if (ngenes == 2) popsize = indTraitsSums.ninds[iGene]; + if (ploidy == 2) popsize = indTraitsSums.ninds[whichChromosome]; else popsize = indTraitsSums.ninds[0] + indTraitsSums.ninds[1]; if (popsize > 0) { - mnDist1[iGene] = indTraitsSums.sumDist1[iGene] / (double)popsize; - mnDist2[iGene] = indTraitsSums.sumDist2[iGene] / (double)popsize; - mnProp1[iGene] = indTraitsSums.sumProp1[iGene] / (double)popsize; - mnStepL[iGene] = indTraitsSums.sumStepL[iGene] / (double)popsize; - mnRho[iGene] = indTraitsSums.sumRho[iGene] / (double)popsize; - mnDP[iGene] = indTraitsSums.sumDP[iGene] / (double)popsize; - mnGB[iGene] = indTraitsSums.sumGB[iGene] / (double)popsize; - mnAlphaDB[iGene] = indTraitsSums.sumAlphaDB[iGene] / (double)popsize; - mnBetaDB[iGene] = indTraitsSums.sumBetaDB[iGene] / (double)popsize; + mnDist1[whichChromosome] = indTraitsSums.sumDist1[whichChromosome] / (double)popsize; + mnDist2[whichChromosome] = indTraitsSums.sumDist2[whichChromosome] / (double)popsize; + mnProp1[whichChromosome] = indTraitsSums.sumProp1[whichChromosome] / (double)popsize; + mnStepL[whichChromosome] = indTraitsSums.sumStepL[whichChromosome] / (double)popsize; + mnRho[whichChromosome] = indTraitsSums.sumRho[whichChromosome] / (double)popsize; + mnDP[whichChromosome] = indTraitsSums.sumDP[whichChromosome] / (double)popsize; + mnGB[whichChromosome] = indTraitsSums.sumGB[whichChromosome] / (double)popsize; + mnAlphaDB[whichChromosome] = indTraitsSums.sumAlphaDB[whichChromosome] / (double)popsize; + mnBetaDB[whichChromosome] = indTraitsSums.sumBetaDB[whichChromosome] / (double)popsize; if (popsize > 1) { - sdDist1[iGene] = indTraitsSums.ssqDist1[iGene] / (double)popsize - mnDist1[iGene] * mnDist1[iGene]; - if (sdDist1[iGene] > 0.0) sdDist1[iGene] = sqrt(sdDist1[iGene]); else sdDist1[iGene] = 0.0; - sdDist2[iGene] = indTraitsSums.ssqDist2[iGene] / (double)popsize - mnDist2[iGene] * mnDist2[iGene]; - if (sdDist2[iGene] > 0.0) sdDist2[iGene] = sqrt(sdDist2[iGene]); else sdDist2[iGene] = 0.0; - sdProp1[iGene] = indTraitsSums.ssqProp1[iGene] / (double)popsize - mnProp1[iGene] * mnProp1[iGene]; - if (sdProp1[iGene] > 0.0) sdProp1[iGene] = sqrt(sdProp1[iGene]); else sdProp1[iGene] = 0.0; - sdStepL[iGene] = indTraitsSums.ssqStepL[iGene] / (double)popsize - mnStepL[iGene] * mnStepL[iGene]; - if (sdStepL[iGene] > 0.0) sdStepL[iGene] = sqrt(sdStepL[iGene]); else sdStepL[iGene] = 0.0; - sdRho[iGene] = indTraitsSums.ssqRho[iGene] / (double)popsize - mnRho[iGene] * mnRho[iGene]; - if (sdRho[iGene] > 0.0) sdRho[iGene] = sqrt(sdRho[iGene]); else sdRho[iGene] = 0.0; - sdDP[iGene] = indTraitsSums.ssqDP[iGene] / (double)popsize - mnDP[iGene] * mnDP[iGene]; - if (sdDP[iGene] > 0.0) sdDP[iGene] = sqrt(sdDP[iGene]); else sdDP[iGene] = 0.0; - sdGB[iGene] = indTraitsSums.ssqGB[iGene] / (double)popsize - mnGB[iGene] * mnGB[iGene]; - if (sdGB[iGene] > 0.0) sdGB[iGene] = sqrt(sdGB[iGene]); else sdGB[iGene] = 0.0; - sdAlphaDB[iGene] = indTraitsSums.ssqAlphaDB[iGene] / (double)popsize - mnAlphaDB[iGene] * mnAlphaDB[iGene]; - if (sdAlphaDB[iGene] > 0.0) sdAlphaDB[iGene] = sqrt(sdAlphaDB[iGene]); else sdAlphaDB[iGene] = 0.0; - sdBetaDB[iGene] = indTraitsSums.ssqBetaDB[iGene] / (double)popsize - mnBetaDB[iGene] * mnBetaDB[iGene]; - if (sdBetaDB[iGene] > 0.0) sdBetaDB[iGene] = sqrt(sdBetaDB[iGene]); else sdBetaDB[iGene] = 0.0; + sdDist1[whichChromosome] = indTraitsSums.ssqDist1[whichChromosome] / (double)popsize - mnDist1[whichChromosome] * mnDist1[whichChromosome]; + if (sdDist1[whichChromosome] > 0.0) sdDist1[whichChromosome] = sqrt(sdDist1[whichChromosome]); else sdDist1[whichChromosome] = 0.0; + sdDist2[whichChromosome] = indTraitsSums.ssqDist2[whichChromosome] / (double)popsize - mnDist2[whichChromosome] * mnDist2[whichChromosome]; + if (sdDist2[whichChromosome] > 0.0) sdDist2[whichChromosome] = sqrt(sdDist2[whichChromosome]); else sdDist2[whichChromosome] = 0.0; + sdProp1[whichChromosome] = indTraitsSums.ssqProp1[whichChromosome] / (double)popsize - mnProp1[whichChromosome] * mnProp1[whichChromosome]; + if (sdProp1[whichChromosome] > 0.0) sdProp1[whichChromosome] = sqrt(sdProp1[whichChromosome]); else sdProp1[whichChromosome] = 0.0; + sdStepL[whichChromosome] = indTraitsSums.ssqStepL[whichChromosome] / (double)popsize - mnStepL[whichChromosome] * mnStepL[whichChromosome]; + if (sdStepL[whichChromosome] > 0.0) sdStepL[whichChromosome] = sqrt(sdStepL[whichChromosome]); else sdStepL[whichChromosome] = 0.0; + sdRho[whichChromosome] = indTraitsSums.ssqRho[whichChromosome] / (double)popsize - mnRho[whichChromosome] * mnRho[whichChromosome]; + if (sdRho[whichChromosome] > 0.0) sdRho[whichChromosome] = sqrt(sdRho[whichChromosome]); else sdRho[whichChromosome] = 0.0; + sdDP[whichChromosome] = indTraitsSums.ssqDP[whichChromosome] / (double)popsize - mnDP[whichChromosome] * mnDP[whichChromosome]; + if (sdDP[whichChromosome] > 0.0) sdDP[whichChromosome] = sqrt(sdDP[whichChromosome]); else sdDP[whichChromosome] = 0.0; + sdGB[whichChromosome] = indTraitsSums.ssqGB[whichChromosome] / (double)popsize - mnGB[whichChromosome] * mnGB[whichChromosome]; + if (sdGB[whichChromosome] > 0.0) sdGB[whichChromosome] = sqrt(sdGB[whichChromosome]); else sdGB[whichChromosome] = 0.0; + sdAlphaDB[whichChromosome] = indTraitsSums.ssqAlphaDB[whichChromosome] / (double)popsize - mnAlphaDB[whichChromosome] * mnAlphaDB[whichChromosome]; + if (sdAlphaDB[whichChromosome] > 0.0) sdAlphaDB[whichChromosome] = sqrt(sdAlphaDB[whichChromosome]); else sdAlphaDB[whichChromosome] = 0.0; + sdBetaDB[whichChromosome] = indTraitsSums.ssqBetaDB[whichChromosome] / (double)popsize - mnBetaDB[whichChromosome] * mnBetaDB[whichChromosome]; + if (sdBetaDB[whichChromosome] > 0.0) sdBetaDB[whichChromosome] = sqrt(sdBetaDB[whichChromosome]); else sdBetaDB[whichChromosome] = 0.0; } } } @@ -914,39 +914,41 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge if (sett.indVar) { if (sett.sexDep) { // must be a sexual species - ngenes = 2; + ploidy = 2; } else { if (dem.repType == 0) { // asexual reproduction - ngenes = 1; + ploidy = 1; } else { // sexual reproduction - ngenes = 1; + ploidy = 1; } } // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - // ngenes = 1; double mnS0[2], mnAlpha[2], mnBeta[2], sdS0[2], sdAlpha[2], sdBeta[2]; - for (int iGene = 0; iGene < ngenes; iGene++) { - mnS0[iGene] = mnAlpha[iGene] = mnBeta[iGene] = sdS0[iGene] = sdAlpha[iGene] = sdBeta[iGene] = 0.0; + for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { + mnS0[whichChromosome] = mnAlpha[whichChromosome] = mnBeta[whichChromosome] = sdS0[whichChromosome] = sdAlpha[whichChromosome] = sdBeta[whichChromosome] = 0.0; // individuals may have been counted by sex if there was // sex dependency in another dispersal phase - if (ngenes == 2) popsize = indTraitsSums.ninds[iGene]; + if (ploidy == 2) popsize = indTraitsSums.ninds[whichChromosome]; else popsize = indTraitsSums.ninds[0] + indTraitsSums.ninds[1]; + if (popsize > 0) { - mnS0[iGene] = indTraitsSums.sumS0[iGene] / (double)popsize; - mnAlpha[iGene] = indTraitsSums.sumAlphaS[iGene] / (double)popsize; - mnBeta[iGene] = indTraitsSums.sumBetaS[iGene] / (double)popsize; + + mnS0[whichChromosome] = indTraitsSums.sumS0[whichChromosome] / (double)popsize; + mnAlpha[whichChromosome] = indTraitsSums.sumAlphaS[whichChromosome] / (double)popsize; + mnBeta[whichChromosome] = indTraitsSums.sumBetaS[whichChromosome] / (double)popsize; + if (popsize > 1) { - sdS0[iGene] = indTraitsSums.ssqS0[iGene] / (double)popsize - mnS0[iGene] * mnS0[iGene]; - if (sdS0[iGene] > 0.0) sdS0[iGene] = sqrt(sdS0[iGene]); else sdS0[iGene] = 0.0; - sdAlpha[iGene] = indTraitsSums.ssqAlphaS[iGene] / (double)popsize - mnAlpha[iGene] * mnAlpha[iGene]; - if (sdAlpha[iGene] > 0.0) sdAlpha[iGene] = sqrt(sdAlpha[iGene]); else sdAlpha[iGene] = 0.0; - sdBeta[iGene] = indTraitsSums.ssqBetaS[iGene] / (double)popsize - mnBeta[iGene] * mnBeta[iGene]; - if (sdBeta[iGene] > 0.0) sdBeta[iGene] = sqrt(sdBeta[iGene]); else sdBeta[iGene] = 0.0; + sdS0[whichChromosome] = indTraitsSums.ssqS0[whichChromosome] / (double)popsize - mnS0[whichChromosome] * mnS0[whichChromosome]; + if (sdS0[whichChromosome] > 0.0) sdS0[whichChromosome] = sqrt(sdS0[whichChromosome]); else sdS0[whichChromosome] = 0.0; + sdAlpha[whichChromosome] = indTraitsSums.ssqAlphaS[whichChromosome] / (double)popsize - mnAlpha[whichChromosome] * mnAlpha[whichChromosome]; + if (sdAlpha[whichChromosome] > 0.0) sdAlpha[whichChromosome] = sqrt(sdAlpha[whichChromosome]); else sdAlpha[whichChromosome] = 0.0; + sdBeta[whichChromosome] = indTraitsSums.ssqBetaS[whichChromosome] / (double)popsize - mnBeta[whichChromosome] * mnBeta[whichChromosome]; + if (sdBeta[whichChromosome] > 0.0) sdBeta[whichChromosome] = sqrt(sdBeta[whichChromosome]); else sdBeta[whichChromosome] = 0.0; } else { - sdS0[iGene] = sdAlpha[iGene] = sdBeta[iGene] = 0.0; + sdS0[whichChromosome] = sdAlpha[whichChromosome] = sdBeta[whichChromosome] = 0.0; } } } @@ -967,32 +969,38 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge } } + // Genetic load if (pSpecies->getNbGenLoadTraits() > 0) { - ngenes = pSpecies->isDiploid() + 1; - double mnProbViable[2], sdProbViable[2]; - for (int iGene = 0; iGene < ngenes; iGene++) { - mnProbViable[iGene] = sdProbViable[iGene] = 0.0; - if (ngenes == 2) popsize = indTraitsSums.ninds[iGene]; + ploidy = pSpecies->isDiploid() + 1; + double mnGenFitness[2], sdGenFitness[2]; + + for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { + mnGenFitness[whichChromosome] = sdGenFitness[whichChromosome] = 0.0; + + if (ploidy == 2) popsize = indTraitsSums.ninds[whichChromosome]; else popsize = indTraitsSums.ninds[0] + indTraitsSums.ninds[1]; + if (popsize > 0) { - mnProbViable[iGene] = indTraitsSums.sumGeneticFitness[iGene] / (double)popsize; + + mnGenFitness[whichChromosome] = indTraitsSums.sumGeneticFitness[whichChromosome] / (double)popsize; if (popsize > 1) { - sdProbViable[iGene] = indTraitsSums.ssqGeneticFitness[iGene] / (double)popsize - mnProbViable[iGene] * mnProbViable[iGene]; - if (sdProbViable[iGene] > 0.0) sdProbViable[iGene] = sqrt(sdProbViable[iGene]); else sdProbViable[iGene] = 0.0; + sdGenFitness[whichChromosome] = indTraitsSums.ssqGeneticFitness[whichChromosome] / (double)popsize - mnGenFitness[whichChromosome] * mnGenFitness[whichChromosome]; + if (sdGenFitness[whichChromosome] > 0.0) sdGenFitness[whichChromosome] = sqrt(sdGenFitness[whichChromosome]); else sdGenFitness[whichChromosome] = 0.0; } else { - sdProbViable[iGene] = 0.0; + sdGenFitness[whichChromosome] = 0.0; } } } + if (writefile) { if (gMaxNbSexes > 1) { - outtraits << "\t" << mnProbViable[0] << "\t" << sdProbViable[0]; - outtraits << "\t" << mnProbViable[1] << "\t" << sdProbViable[1]; + outtraits << "\t" << mnGenFitness[0] << "\t" << sdGenFitness[0]; + outtraits << "\t" << mnGenFitness[1] << "\t" << sdGenFitness[1]; } else { // sex-independent - outtraits << "\t" << mnProbViable[0] << "\t" << sdProbViable[0]; + outtraits << "\t" << mnGenFitness[0] << "\t" << sdGenFitness[0]; } } } From e50907cd0f9f1a591533fa8ae7577e558eb52f1c Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 23 Sep 2024 18:09:42 +0100 Subject: [PATCH 264/332] output the right number of sexes for genetic load --- Population.cpp | 1 + SubCommunity.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Population.cpp b/Population.cpp index f47464b..5e64a15 100644 --- a/Population.cpp +++ b/Population.cpp @@ -306,6 +306,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { if (gMaxNbSexes > 1) g = sex; else g = 0; + ts.sumGeneticFitness[g] += inds[iInd]->getGeneticFitness(); ts.ssqGeneticFitness[g] += inds[iInd]->getGeneticFitness() * inds[iInd]->getGeneticFitness(); } diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 72f9c6e..d1892b7 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -694,7 +694,7 @@ bool SubCommunity::outTraitsHeaders(Landscape* pLandscape, Species* pSpecies, in } } if (pSpecies->getNbGenLoadTraits() > 0) { - if (gMaxNbSexes > 1) { + if (pSpecies->getDemogrParams().repType > 0) { outtraits << "\tF_meanGenFitness\tF_stdGenFitness\tM_meanGenFitness\tM_stdGenFitness"; } else { @@ -995,7 +995,7 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge } if (writefile) { - if (gMaxNbSexes > 1) { + if (pSpecies->getDemogrParams().repType > 0) { outtraits << "\t" << mnGenFitness[0] << "\t" << sdGenFitness[0]; outtraits << "\t" << mnGenFitness[1] << "\t" << sdGenFitness[1]; } From 0742a3b303dba215f7cf2962d6133cf5cfa2f745 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 25 Sep 2024 17:05:20 +0100 Subject: [PATCH 265/332] why --- Population.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Population.cpp b/Population.cpp index 5e64a15..334d0fb 100644 --- a/Population.cpp +++ b/Population.cpp @@ -672,12 +672,7 @@ void Population::reproduction(const float localK, const float envval, const int for (int j = 0; j < njuvs; j++) { Individual* newJuv; -#ifndef NDEBUG - // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... - newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, true, trfr.moveType); -#else newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.usesMovtProc, trfr.moveType); -#endif if (pSpecies->getNTraits() > 0) { newJuv->inheritTraits(pSpecies, inds[i], resol); From f72765ae8bad161bdc9e44f429743b08f6414a18 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 25 Sep 2024 17:07:01 +0100 Subject: [PATCH 266/332] if default repro is asexual then propmales should be zero --- Species.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Species.cpp b/Species.cpp index 80c1a1a..e6972fc 100644 --- a/Species.cpp +++ b/Species.cpp @@ -28,9 +28,10 @@ Species::Species(void) { // initialise demographic parameters - repType = 0; nStages = 2; + repType = 0; + nStages = 2; stageStruct = false; - propMales = 0.5; + propMales = 0.0; harem = 1.0; bc = 1.0; lambda = 1.5; From affc4da6aba9d0f6fa880ec577d1fc455c95d06a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 26 Sep 2024 16:25:28 +0100 Subject: [PATCH 267/332] merge batch and R versions of RSrandom --- RSrandom.cpp | 255 ++++++++++----------------------------------------- RSrandom.h | 80 ++++------------ 2 files changed, 64 insertions(+), 271 deletions(-) diff --git a/RSrandom.cpp b/RSrandom.cpp index c7e309f..81abf2a 100644 --- a/RSrandom.cpp +++ b/RSrandom.cpp @@ -19,49 +19,71 @@ * --------------------------------------------------------------------------*/ - #include "RSrandom.h" - - //--------------- 2.) New version of RSrandom.cpp - -#if !RS_RCPP - #ifndef NDEBUG #include "Parameters.h" extern paramSim* paramsSim; -// ofstream RSRANDOMLOG; #endif -int RS_random_seed = 0; - // C'tor +#if RS_RCPP +// if parameter seed is negative, a random seed will be generated, else it is used as seed +RSrandom::RSrandom(std::int64_t seed) +{ + // get seed + std::vector random_seed(3); + random_seed[0] = 1967593562; + random_seed[1] = 3271254416; + if (seed < 0) { + // random seed +#if RSWIN64 + random_seed[2] = std::time(NULL) + (seed * (-17)); +#else + std::random_device device; + random_seed[2] = device(); +#endif + } + else { + // fixed seed + random_seed[2] = seed; + } + + RS_random_seed = random_seed[2]; + + // set up Mersenne Twister random number generator with seed sequence + std::seed_seq seq(random_seed.begin(), random_seed.end()); + gen = new mt19937(seq); + + // Set up standard uniform distribution + pRandom01 = new uniform_real_distribution(0.0, 1.0); + // Set up standard normal distribution + pNormal = new normal_distribution(0.0, 1.0); +} +#else RSrandom::RSrandom() { + #ifndef NDEBUG // fixed seed - RS_random_seed = 666; + RS_random_seed = 666; #else - // random seed + // random seed #if LINUX_CLUSTER - std::random_device device; - RS_random_seed = device(); // old versions of g++ on Windows return a constant value within a given Windows - // session; in this case better use time stamp + std::random_device device; + RS_random_seed = device(); // old versions of g++ on Windows return a constant value within a given Windows + // session; in this case better use time stamp #else - RS_random_seed = std::time(NULL); + RS_random_seed = std::time(NULL); #endif #endif // NDEBUG -#ifndef NDEBUG - DEBUGLOG << "RSrandom::RSrandom(): RS_random_seed=" << RS_random_seed << endl; -#endif - - // set up Mersenne Twister RNG - gen = new mt19937(RS_random_seed); - - // Set up standard uniform distribution - pRandom01 = new uniform_real_distribution(0.0, 1.0); - // Set up standard normal distribution - pNormal = new normal_distribution(0.0, 1.0); + // set up Mersenne Twister RNG + gen = new mt19937(RS_random_seed); + // Set up standard uniform distribution + pRandom01 = new uniform_real_distribution(0.0, 1.0); + // Set up standard normal distribution + pNormal = new normal_distribution(0.0, 1.0); } +#endif // RS_RCPP RSrandom::~RSrandom(void) { delete gen; @@ -139,187 +161,6 @@ void RSrandom::fixNewSeed(int seed) { //-------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------- -#else // if RS_RCPP - -//--------------- 3.) R package version of RSrandom.cpp - -#ifndef NDEBUG - -#include "Parameters.h" -extern paramSim* paramsSim; -//ofstream RSRANDOMLOG; -#endif - -std::uint32_t RS_random_seed = 0; - -// C'tor -// if parameter seed is negative, a random seed will be generated, else it is used as seed -RSrandom::RSrandom(std::int64_t seed) -{ - // get seed - std::vector random_seed(3); - random_seed[0] = 1967593562; - random_seed[1] = 3271254416; - if (seed < 0) { - // random seed -#if RSWIN64 - random_seed[2] = std::time(NULL) + (seed * (-17)); -#else - std::random_device device; - random_seed[2] = device(); -#endif -#ifndef NDEBUG - DEBUGLOG << "RSrandom::RSrandom(): Generated random seed = "; -#endif - } - else { - // fixed seed - random_seed[2] = seed; -#ifndef NDEBUG - DEBUGLOG << "RSrandom::RSrandom(): Use fixed seed = "; -#endif - } - - RS_random_seed = random_seed[2]; -#if BATCH -#ifndef NDEBUG - DEBUGLOG << RS_random_seed << endl; -#endif -#endif - - // set up Mersenne Twister random number generator with seed sequence - std::seed_seq seq(random_seed.begin(), random_seed.end()); - gen = new mt19937(seq); - - // Set up standard uniform distribution - pRandom01 = new uniform_real_distribution(0.0, 1.0); - // Set up standard normal distribution - pNormal = new normal_distribution(0.0, 1.0); -} - -RSrandom::~RSrandom(void) { - delete gen; - if (pRandom01 != 0) delete pRandom01; - if (pNormal != 0) delete pNormal; -} - -mt19937 RSrandom::getRNG(void) { - // return random number generator - return *gen; -} - -double RSrandom::Random(void) { - // return random number between 0 and 1 - return pRandom01->operator()(*gen); -} - -int RSrandom::IRandom(int min, int max) { - // return random integer in the interval min <= x <= max - if (min == max) - return min; - - uniform_int_distribution unif(min, max); - return unif(*gen); -} - -float RSrandom::FRandom(float min, float max) { - if (min == max) - return min; - // return random double in the interval min <= x <= max - uniform_real_distribution unif(min, max); - return unif(*gen); -} - - int RSrandom::Bernoulli(double p) { - if (p < 0) throw runtime_error("Bernoulli's p cannot be negative.\n"); - if (p > 1) throw runtime_error("Bernoulli's p cannot be above 1.\n"); - return Random() < p; - } - - int RSrandom::Binomial(const int& n, const double& p) { - binomial_distribution binom(n, p); - return binom(*gen); - } - -double RSrandom::Normal(double mean, double sd) { - return mean + sd * pNormal->operator()(*gen); -} - -int RSrandom::Poisson(double mean) { - poisson_distribution poiss(mean); - return poiss(*gen); -} - -double RSrandom::Gamma(double shape, double scale) { //scale = mean/shape, shape must be positive and scale can be positive or negative - - gamma_distribution<> gamma(shape, abs(scale)); - - double x = gamma(*gen); - if (scale < 0) x = -x; - return x; -} - -double RSrandom::NegExp(double mean) { - double r1 = 0.0000001 + this->Random() * (1.0 - 0.0000001); - double x = (-1.0 * mean) * log(r1); - return x; -} - -void RSrandom::fixNewSeed(int seed) { - gen->seed(seed); -} - -/* ADDITIONAL DISTRIBUTIONS - -// Beta distribution - sample from two gamma distributions -double RSrandom::Beta(double p0,double p1) { - double g0,g1,beta; - if (p0 > 0.0 && p1 > 0.0) { // valid beta parameters - gamma_distribution gamma0(p0,1.0); - gamma_distribution gamma1(p1,1.0); - g0 = gamma0(*gen); - g1 = gamma1(*gen); - beta = g0 / (g0 + g1); - } - else { // return invalid value - beta = -666.0; - } - return beta; -} - -// Gamma distribution -double RSrandom::Gamma(double p0,double p1) { // using shape (=p0) and scale (=p1) - double p2,gamma; - if (p0 > 0.0 && p1 > 0.0) { // valid gamma parameters - p2 = 1.0 / p1; - gamma_distribution gamma0(p0,p2); // using shape/alpha (=p0) and rate/beta (=p2=1/p1) - gamma = gamma0(*gen); - } - else { // return invalid value - gamma = -666.0; - } -return gamma; -} - -// Cauchy distribution -double RSrandom::Cauchy(double loc, double scale) { - double res; - if (scale > 0.0) { // valid scale parameter - cauchy_distribution cauchy(loc,scale); - res = cauchy(*gen); - } - else { // return invalid value - res = -666.0; - } - return res; -} - - -*/ - -#endif // RS_RCPP - - #ifndef NDEBUG #if !RS_RCPP void testRSrandom() { diff --git a/RSrandom.h b/RSrandom.h index ebbd95d..dafa268 100644 --- a/RSrandom.h +++ b/RSrandom.h @@ -39,74 +39,32 @@ #include #include #include -#include "Utils.h" - -using namespace std; - -#ifndef NDEBUG -extern ofstream DEBUGLOG; -#endif - -#if !RS_RCPP -//--------------- 2.) New version of RSrandom.cpp - - #include #include +#include +#include "Utils.h" #if !LINUX_CLUSTER #include #endif -#include - -class RSrandom -{ - -public: - RSrandom(void); - ~RSrandom(void); - double Random(void); - int IRandom(int, int); - float FRandom(float, float); - int Bernoulli(double); - int Binomial(const int& n, const double& p); - double Normal(double, double); - double Gamma(double, double); - double NegExp(double); - int Poisson(double); - mt19937 getRNG(void); - void fixNewSeed(int); - -private: - mt19937* gen; - std::uniform_real_distribution<>* pRandom01; - std::normal_distribution<>* pNormal; -}; - - -//-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- - - - -//--------------- 3.) R package version of RSrandom.cpp - - -#else // if RS_RCPP +using namespace std; -#include -#include -#if RSWIN64 -#include +#if RS_RCPP +typedef uint32_t seed_t; +#else +typedef int seed_t; #endif -#include -class RSrandom { +class RSrandom +{ public: +#if !RS_RCPP + RSrandom(void); +#else RSrandom(std::int64_t); // if int is negative, a random seed will be generated, else it is used as seed +#endif ~RSrandom(void); - mt19937 getRNG(void); double Random(void); int IRandom(int, int); float FRandom(float, float); @@ -116,23 +74,17 @@ class RSrandom { double Gamma(double, double); double NegExp(double); int Poisson(double); + mt19937 getRNG(void); void fixNewSeed(int); - /* ADDITIONAL DISTRIBUTIONS - double Beta(double,double); - double Gamma(double,double); // !! make sure correct definition is used: using shape and scale (as defined here) OR using shape/alpha and rate/beta (=1/scale) - double Cauchy(double,double); - */ + seed_t getSeed() const { return RS_random_seed; }; private: + seed_t RS_random_seed; mt19937* gen; std::uniform_real_distribution<>* pRandom01; std::normal_distribution<>* pNormal; }; - - -#endif // !RS_RCPP - #ifndef NDEBUG void testRSrandom(); #endif // NDEBUG From 849c78f94049bb5d621e5eef8e4f5b943b1153d9 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 26 Sep 2024 16:28:28 +0100 Subject: [PATCH 268/332] seed goes in parameter output --- Model.cpp | 7 +++---- Model.h | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Model.cpp b/Model.cpp index 644d9b0..306432b 100644 --- a/Model.cpp +++ b/Model.cpp @@ -792,10 +792,9 @@ void OutParameters(Landscape* pLandscape) outPar << endl << endl; outPar << "BATCH MODE \t"; - if (sim.batchMode) outPar << "yes" << endl; else outPar << "no" << endl; -#if RS_RCPP - outPar << "SEED \t" << RS_random_seed << endl; -#endif + if (sim.batchMode) outPar << "yes" << endl; + else outPar << "no" << endl; + outPar << "SEED \t" << pRandom->getSeed() << endl; outPar << "REPLICATES \t" << sim.reps << endl; outPar << "YEARS \t" << sim.years << endl; outPar << "REPRODUCTIVE SEASONS / YEAR\t" << dem.repSeasons << endl; diff --git a/Model.h b/Model.h index ff2d191..c398852 100644 --- a/Model.h +++ b/Model.h @@ -113,7 +113,6 @@ extern string genfilename; // see Main.cpp (batch) extern RSrandom *pRandom; #if RS_RCPP -extern std::uint32_t RS_random_seed; extern string name_landscape, name_patch, name_costfile, name_sp_dist; #endif //--------------------------------------------------------------------------- From 71ca3a62a7c301983351f92aecaa9ef07e048568 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 26 Sep 2024 16:32:53 +0100 Subject: [PATCH 269/332] cleaning up --- Main.cpp | 1 - Model.cpp | 28 ---------------------------- 2 files changed, 29 deletions(-) diff --git a/Main.cpp b/Main.cpp index 5bb63d2..841f584 100644 --- a/Main.cpp +++ b/Main.cpp @@ -65,7 +65,6 @@ paramInit* paramsInit; paramSim* paramsSim; RSrandom* pRandom; ofstream DEBUGLOG; -ofstream MUTNLOG; vector hfnames; Species* pSpecies; Community* pComm; diff --git a/Model.cpp b/Model.cpp index 306432b..ba36992 100644 --- a/Model.cpp +++ b/Model.cpp @@ -42,7 +42,6 @@ int RunModel(Landscape* pLandscape, int seqsim) envStochParams env = paramsStoch->getStoch(); demogrParams dem = pSpecies->getDemogrParams(); stageParams sstruct = pSpecies->getStageParams(); - //emigRules emig = pSpecies->getEmig(); transferRules trfr = pSpecies->getTransferRules(); initParams init = paramsInit->getInit(); simParams sim = paramsSim->getSim(); @@ -402,20 +401,6 @@ int RunModel(Landscape* pLandscape, int seqsim) for (int gen = 0; gen < dem.repSeasons; gen++) // generation loop { -#ifndef NDEBUG - // TEMPORARY RANDOM STREAM CHECK - if (yr % 1 == 0) - { - DEBUGLOG << endl << "RunModel(): start of gen " << gen << " in year " << yr - << " for rep " << rep << " ("; - for (int i = 0; i < 5; i++) { - int rrrr = pRandom->IRandom(1000, 2000); - DEBUGLOG << " " << rrrr; - } - DEBUGLOG << " )" << endl; - } -#endif - // Output and pop. visualisation before reproduction if (v.viewPop || v.viewTraits || sim.outOccup || sim.outTraitsCells || sim.outTraitsRows || sim.saveMaps) @@ -711,22 +696,9 @@ bool CheckDirectory(void) //For outputs and population visualisations pre-reproduction void PreReproductionOutput(Landscape* pLand, Community* pComm, int rep, int yr, int gen) { -#ifndef NDEBUG - landParams ppLand = pLand->getLandParams(); -#endif simParams sim = paramsSim->getSim(); simView v = paramsSim->getViews(); -#ifndef NDEBUG - DEBUGLOG << "PreReproductionOutput(): 11111 rep=" << rep << " yr=" << yr << " gen=" << gen - << " landNum=" << ppLand.landNum << " maxX=" << ppLand.maxX << " maxY=" << ppLand.maxY - << endl; - DEBUGLOG << "PreReproductionOutput(): 11112 outRange=" << sim.outRange - << " outIntRange=" << sim.outIntRange - << " outPop=" << sim.outPop << " outIntPop=" << sim.outIntPop - << endl; -#endif - // trait outputs and visualisation if (v.viewTraits || ((sim.outTraitsCells && yr >= sim.outStartTraitCell && yr % sim.outIntTraitCell == 0) || From 17f92810948315616b0a24de69bb4da4f3e84f22 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 26 Sep 2024 16:44:35 +0100 Subject: [PATCH 270/332] by DEBUGLOG --- Community.cpp | 38 -------------------------------------- Individual.h | 4 ---- Landscape.cpp | 18 +----------------- Landscape.h | 1 - Main.cpp | 1 - Model.h | 4 ---- Parameters.h | 4 ---- Patch.h | 4 ---- Population.h | 4 ---- 9 files changed, 1 insertion(+), 77 deletions(-) diff --git a/Community.cpp b/Community.cpp index 9c3a08e..9197a54 100644 --- a/Community.cpp +++ b/Community.cpp @@ -411,11 +411,6 @@ void Community::dispersal(short landIx, short nextseason) void Community::dispersal(short landIx) #endif // RS_RCPP { -#ifndef NDEBUG - time_t t0, t1, t2; - t0 = time(0); -#endif - simParams sim = paramsSim->getSim(); int nsubcomms = (int)subComms.size(); @@ -424,11 +419,6 @@ void Community::dispersal(short landIx) for (int i = 0; i < nsubcomms; i++) { // all populations subComms[i]->initiateDispersal(matrix); } -#ifndef NDEBUG - t1 = time(0); - DEBUGLOG << "Community::dispersal(): this=" << this - << " nsubcomms=" << nsubcomms << " initiation time=" << t1 - t0 << endl; -#endif // dispersal is undertaken by all individuals now in the matrix patch // (even if not physically in the matrix) @@ -444,13 +434,6 @@ void Community::dispersal(short landIx) #endif // SEASONAL || RS_RCPP matrix->completeDispersal(pLandscape, sim.outConnect); } while (ndispersers > 0); - -#ifndef NDEBUG - DEBUGLOG << "Community::dispersal(): matrix=" << matrix << endl; - t2 = time(0); - DEBUGLOG << "Community::dispersal(): transfer time=" << t2 - t1 << endl; -#endif - } void Community::survival(short part, short option0, short option1) @@ -508,17 +491,12 @@ void Community::createOccupancy(int nrows, int reps) { void Community::updateOccupancy(int row, int rep) { -#ifndef NDEBUG - DEBUGLOG << "Community::updateOccupancy(): row=" << row << endl; -#endif int nsubcomms = (int)subComms.size(); for (int i = 0; i < nsubcomms; i++) { subComms[i]->updateOccupancy(row); } - commStats s = getStats(); occSuit[row][rep] = (float)s.occupied / (float)s.suitable; - } void Community::deleteOccupancy(int nrows) { @@ -630,12 +608,6 @@ bool Community::outRangeHeaders(Species* pSpecies, int landNr) transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); -#ifndef NDEBUG - DEBUGLOG << "Community::outRangeHeaders(): simulation=" << sim.simulation - << " sim.batchMode=" << sim.batchMode - << " landNr=" << landNr << endl; -#endif - if (sim.batchMode) { name = paramsSim->getDir(2) + "Batch" + to_string(sim.batchNum) + "_" @@ -719,22 +691,12 @@ bool Community::outRangeHeaders(Species* pSpecies, int landNr) } } outrange << endl; - -#ifndef NDEBUG - DEBUGLOG << "Community::outRangeHeaders(): finished" << endl; -#endif - return outrange.is_open(); } // Write record to range file void Community::outRange(Species* pSpecies, int rep, int yr, int gen) { -#ifndef NDEBUG - DEBUGLOG << "Community::outRange(): rep=" << rep - << " yr=" << yr << " gen=" << gen << endl; -#endif - landParams ppLand = pLandscape->getLandParams(); envStochParams env = paramsStoch->getStoch(); diff --git a/Individual.h b/Individual.h index b7485b6..b4117ed 100644 --- a/Individual.h +++ b/Individual.h @@ -395,10 +395,6 @@ double wrpcauchy(double location, double rho = exp(double(-1))); extern RSrandom* pRandom; -#ifndef NDEBUG -extern ofstream DEBUGLOG; -#endif - #if RS_RCPP extern ofstream outMovePaths; #endif diff --git a/Landscape.cpp b/Landscape.cpp index 4a7f01f..5ec8ded 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -1125,11 +1125,6 @@ int Landscape::readLandChange(int filenum, bool costs) #endif { -#ifndef NDEBUG - DEBUGLOG << "Landscape::readLandChange(): filenum=" << filenum << " costs=" << int(costs) - << endl; -#endif - #if RS_RCPP wstring header; #else @@ -1600,9 +1595,7 @@ void Landscape::createCostsChgMatrix(void) } void Landscape::recordCostChanges(int landIx) { -#ifndef NDEBUG - DEBUGLOG << "Landscape::recordCostChanges(): landIx=" << landIx << endl; -#endif + if (costsChgMatrix == 0) return; // should not occur costChange chg; @@ -2289,13 +2282,7 @@ int Landscape::readCosts(string fname) int maxcost = 0; -#ifndef NDEBUG -#if BATCH - DEBUGLOG << "Landscape::readCosts(): fname=" << fname << endl; -#endif -#endif // open cost file - // open cost file #if RS_RCPP costs.open(fname, std::ios::binary); if (costsraster.utf) { @@ -2529,9 +2516,6 @@ void Landscape::outPathsHeaders(int rep, int option) outMovePaths << "Year\tIndID\tStep\tx\ty\tStatus" << endl; } else { -#ifndef NDEBUG - DEBUGLOG << "RunModel(): UNABLE TO OPEN MOVEMENT PATHS FILE" << endl; -#endif outMovePaths.clear(); } } diff --git a/Landscape.h b/Landscape.h index f075471..ac7e258 100644 --- a/Landscape.h +++ b/Landscape.h @@ -531,7 +531,6 @@ extern paramSim* paramsSim; extern RSrandom* pRandom; #ifndef NDEBUG -extern ofstream DEBUGLOG; landParams createDefaultLandParams(const int& dim); void testLandscape(); #endif diff --git a/Main.cpp b/Main.cpp index 841f584..7329932 100644 --- a/Main.cpp +++ b/Main.cpp @@ -64,7 +64,6 @@ paramStoch* paramsStoch; paramInit* paramsInit; paramSim* paramsSim; RSrandom* pRandom; -ofstream DEBUGLOG; vector hfnames; Species* pSpecies; Community* pComm; diff --git a/Model.h b/Model.h index c398852..cd2323c 100644 --- a/Model.h +++ b/Model.h @@ -61,10 +61,6 @@ using namespace std::filesystem; #endif -#ifndef NDEBUG -extern ofstream DEBUGLOG; -#endif - #if RS_RCPP && !R_CMD Rcpp::List RunModel( Landscape*, // pointer to Landscape diff --git a/Parameters.h b/Parameters.h index b17c4a5..8090e2a 100644 --- a/Parameters.h +++ b/Parameters.h @@ -406,10 +406,6 @@ class paramSim { int outputGeneticInterval; }; -#ifndef NDEBUG -extern ofstream DEBUGLOG; -#endif - extern RSrandom* pRandom; //--------------------------------------------------------------------------- diff --git a/Patch.h b/Patch.h index 5dc4738..6900658 100644 --- a/Patch.h +++ b/Patch.h @@ -166,8 +166,4 @@ class Patch { extern paramStoch* paramsStoch; extern RSrandom* pRandom; -#ifndef NDEBUG -extern ofstream DEBUGLOG; -#endif - #endif diff --git a/Population.h b/Population.h index 7370ba0..6e05abd 100644 --- a/Population.h +++ b/Population.h @@ -258,10 +258,6 @@ extern paramInit* paramsInit; extern paramSim* paramsSim; extern RSrandom* pRandom; -#ifndef NDEBUG -extern ofstream DEBUGLOG; -#endif - //--------------------------------------------------------------------------- #endif From bc7ab3b8c0b3cd82ea449498a3163f2788048458 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 26 Sep 2024 22:39:08 +0100 Subject: [PATCH 271/332] pass some params as species args (w defaults) to de-clutter main --- Population.cpp | 4 +- Species.cpp | 88 +++++++++++++++++++------- Species.h | 107 ++++++++++++++++++++++++-------- unit_tests/testIndividual.cpp | 16 ++--- unit_tests/testNeutralStats.cpp | 28 ++++----- unit_tests/testPopulation.cpp | 4 +- 6 files changed, 172 insertions(+), 75 deletions(-) diff --git a/Population.cpp b/Population.cpp index 334d0fb..4b37c55 100644 --- a/Population.cpp +++ b/Population.cpp @@ -277,7 +277,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { break; } default: - throw runtime_error("moveModel enabled but moveType is neither 1 (SMS) or 2 (CRW)."); + throw runtime_error("usesMoveProcess is ON but moveType is neither 1 (SMS) or 2 (CRW)."); break; } } @@ -1223,7 +1223,7 @@ int Population::transfer(Landscape* pLandscape, short landIx) } #if RS_RCPP // write each individuals current movement step and status to paths file - if (trfr.moveModel && sim.outPaths) { + if (trfr.usesMovtProc && sim.outPaths) { if (nextseason >= sim.outStartPaths && nextseason % sim.outIntPaths == 0) { inds[i]->outMovePath(nextseason); } diff --git a/Species.cpp b/Species.cpp index e6972fc..c9b06ea 100644 --- a/Species.cpp +++ b/Species.cpp @@ -25,18 +25,20 @@ #include "Species.h" //--------------------------------------------------------------------------- -Species::Species(void) +Species::Species(const short& repro, const short& nbRepSeasons, const bool& hasStgStruct, const short& nStg, const bool& usesMovtProc, const short& movementType) : + repType{repro}, + repSeasons{nbRepSeasons}, + stageStruct{hasStgStruct}, + nStages{nStg}, + usesMovtProcess{usesMovtProc}, + moveType{movementType} { // initialise demographic parameters - repType = 0; - nStages = 2; - stageStruct = false; propMales = 0.0; harem = 1.0; bc = 1.0; lambda = 1.5; probRep = 1.0; - repSeasons = 1; repInterval = 0; maxAge = 1000; survival = 1; @@ -49,7 +51,9 @@ Species::Species(void) disperseOnLoss = false; for (int i = 0; i < gMaxNbStages; i++) { for (int j = 0; j < gMaxNbSexes; j++) { - fec[i][j] = 0.0; dev[i][j] = 0.0; surv[i][j] = 0.0; + fec[i][j] = 0.0; + dev[i][j] = 0.0; + surv[i][j] = 0.0; minAge[i][j] = 0; } } @@ -62,41 +66,68 @@ Species::Species(void) maxRK = 2.0; // initialise emigration parameters - densDepEmig = false; stgDepEmig = false; sexDepEmig = false; indVarEmig = false; + densDepEmig = false; + stgDepEmig = false; + sexDepEmig = false; + indVarEmig = false; emigStage = 0; for (int i = 0; i < gMaxNbStages; i++) { for (int j = 0; j < gMaxNbSexes; j++) { - d0[i][j] = 0.0; alphaEmig[i][j] = 0.0; betaEmig[i][j] = 1.0; + d0[i][j] = 0.0; + alphaEmig[i][j] = 0.0; + betaEmig[i][j] = 1.0; } } // initialise transfer parameters - moveModel = false; stgDepTrfr = false; sexDepTrfr = false; distMort = false; + stgDepTrfr = false; + sexDepTrfr = false; + distMort = false; indVarTrfr = false; twinKern = false; habMort = false; costMap = false; - moveType = 1; for (int i = 0; i < gMaxNbStages; i++) { for (int j = 0; j < gMaxNbSexes; j++) { - meanDist1[i][j] = 100.0f; meanDist2[i][j] = 1000.0f; probKern1[i][j] = 0.99f; + meanDist1[i][j] = 100.0f; + meanDist2[i][j] = 1000.0f; + probKern1[i][j] = 0.99f; } } - pr = 1; prMethod = 1; memSize = 1; goalType = 0; - dp = 1.0; gb = 1.0; alphaDB = 1.0; betaDB = 100000; - stepMort = 0.0; stepLength = 10.0; rho = 0.9f; - habStepMort = 0; habCost = 0; - //costMapFile = "NULL"; - fixedMort = 0.0; mortAlpha = 0.0; mortBeta = 1.0; + pr = 1; + prMethod = 1; + memSize = 1; + goalType = 0; + dp = 1.0; + gb = 1.0; + alphaDB = 1.0; + betaDB = 100000; + stepMort = 0.0; + stepLength = 10.0; + rho = 0.9f; + habStepMort = 0; + habCost = 0; + fixedMort = 0.0; + mortAlpha = 0.0; + mortBeta = 1.0; habDimTrfr = 0; straightenPath = false; fullKernel = false; // initialise settlement parameters - stgDepSett = false; sexDepSett = false; indVarSett = false; + stgDepSett = false; + sexDepSett = false; + indVarSett = false; for (int i = 0; i < gMaxNbStages; i++) { for (int j = 0; j < gMaxNbSexes; j++) { - densDepSett[i][j] = false; wait[i][j] = false; go2nbrLocn[i][j] = false; findMate[i][j] = false; - maxStepsYr[i][j] = 99999999; minSteps[i][j] = 0; maxSteps[i][j] = 99999999; - s0[i][j] = 1.0; alphaS[i][j] = 0.0; betaS[i][j] = 1.0; + densDepSett[i][j] = false; + wait[i][j] = false; + go2nbrLocn[i][j] = false; + findMate[i][j] = false; + maxStepsYr[i][j] = 99999999; + minSteps[i][j] = 0; + maxSteps[i][j] = 99999999; + s0[i][j] = 1.0; + alphaS[i][j] = 0.0; + betaS[i][j] = 1.0; } } // initialise attribute defaults @@ -548,7 +579,7 @@ float Species::getSpEmigD0(short stg, short sex) { // Transfer functions void Species::setTrfrRules(const transferRules t) { - moveModel = t.usesMovtProc; + usesMovtProcess = t.usesMovtProc; stgDepTrfr = t.stgDep; sexDepTrfr = t.sexDep; distMort = t.distMort; @@ -561,7 +592,7 @@ void Species::setTrfrRules(const transferRules t) { transferRules Species::getTransferRules(void) { transferRules t; - t.usesMovtProc = moveModel; t.stgDep = stgDepTrfr; t.sexDep = sexDepTrfr; + t.usesMovtProc = usesMovtProcess; t.stgDep = stgDepTrfr; t.sexDep = sexDepTrfr; t.distMort = distMort; t.indVar = indVarTrfr; t.twinKern = twinKern; t.habMort = habMort; @@ -795,6 +826,17 @@ void Species::setSamplePatchList(const set& samplePatchList) { #ifndef NDEBUG // For testing purposes only +Species* createDefaultSpecies() { + short repType = 0; + short repSeasons = 1; + bool stagestruct = false; + int nStages = 2; + bool usesMovtProc = false; + short movtType = 1; + Species* pSpecies = new Species(repType, repSeasons, stagestruct, nStages, usesMovtProc, movtType); + return pSpecies; +} + demogrParams createDefaultHaploidDemogrParams() { demogrParams d; d.repType = 0; diff --git a/Species.h b/Species.h index d2b7714..a71c96f 100644 --- a/Species.h +++ b/Species.h @@ -61,28 +61,45 @@ class SpeciesTrait; struct demogrParams { short repType; short repSeasons; - float propMales; float harem; float bc; float lambda; + float propMales; + float harem; + float bc; + float lambda; bool stageStruct; }; struct stageParams { - short nStages; short repInterval; short maxAge; short survival; + short nStages; + short repInterval; + short maxAge; + short survival; float probRep; - bool fecDens; bool fecStageDens; bool devDens; bool devStageDens; - bool survDens; bool survStageDens; bool disperseOnLoss; + bool fecDens; + bool fecStageDens; + bool devDens; + bool devStageDens; + bool survDens; + bool survStageDens; + bool disperseOnLoss; }; struct densDepParams { - float devCoeff; float survCoeff; + float devCoeff; + float survCoeff; }; // structures for emigration parameters struct emigRules { - bool densDep; bool stgDep; bool sexDep; bool indVar; + bool densDep; + bool stgDep; + bool sexDep; + bool indVar; short emigStage; short emigTrait[2]; }; struct emigTraits { - float d0; float alpha; float beta; + float d0; + float alpha; + float beta; emigTraits() : d0(0.0), alpha(0.0), beta(0.0) {}; @@ -101,11 +118,15 @@ struct emigTraits { // structures for transfer parameters struct transferRules { - bool usesMovtProc; bool stgDep; bool sexDep; - bool distMort; bool indVar; + bool usesMovtProc; + bool stgDep; + bool sexDep; + bool distMort; + bool indVar; bool twinKern; bool habMort; - short moveType; bool costMap; + short moveType; + bool costMap; short movtTrait[2]; }; struct trfrKernelParams { @@ -114,40 +135,66 @@ struct trfrKernelParams { float probKern1; }; struct trfrMortParams { - float fixedMort; float mortAlpha; float mortBeta; + float fixedMort; + float mortAlpha; + float mortBeta; }; struct trfrMovtParams { - short pr; short prMethod; short memSize; short goalType; - float dp; float gb; float alphaDB; int betaDB; - float stepMort; float stepLength; float rho; + short pr; + short prMethod; + short memSize; + short goalType; + float dp; + float gb; + float alphaDB; + int betaDB; + float stepMort; + float stepLength; + float rho; bool straightenPath; }; struct trfrCRWTraits { - float stepMort; - float stepLength; - float rho; - bool straightenPath; + float stepMort; + float stepLength; + float rho; + bool straightenPath; }; struct trfrSMSTraits { - short pr; short prMethod; short memSize; short goalType; - float dp; float gb; float alphaDB; int betaDB; float stepMort; + short pr; + short prMethod; + short memSize; + short goalType; + float dp; + float gb; + float alphaDB; + int betaDB; + float stepMort; bool straightenPath; }; // structures for settlement parameters struct settleType { - bool stgDep; bool sexDep; bool indVar; + bool stgDep; + bool sexDep; + bool indVar; short settTrait[2]; }; struct settleRules { - bool densDep; bool wait; bool go2nbrLocn; bool findMate; + bool densDep; + bool wait; + bool go2nbrLocn; + bool findMate; }; struct settleSteps { - int minSteps; int maxSteps; int maxStepsYr; + int minSteps; + int maxSteps; + int maxStepsYr; }; struct settleTraits { - float s0; float alpha; float beta; + float s0; + float alpha; + float beta; settleTraits() : s0(0.0), alpha(0.0), beta(0.0) {}; @@ -166,7 +213,14 @@ struct settleTraits { class Species { public: - Species(void); + Species( + const short& repro = 0, + const short& nbRepSeasons = 1, + const bool& hasStgStruct = false, + const short& nStg = 2, + const bool& usesMovtProc = false, + const short& movementType = 1 + ); ~Species(void); short getSpNum(void); @@ -511,7 +565,7 @@ class Species { // transfer parameters - bool moveModel; + bool usesMovtProcess; bool stgDepTrfr; bool sexDepTrfr; bool distMort; @@ -575,6 +629,7 @@ class Species { #ifndef NDEBUG // For testing purposes only +Species* createDefaultSpecies(); demogrParams createDefaultHaploidDemogrParams(); demogrParams createDefaultDiploidDemogrParams(); #endif // NDEBUG diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 7e186b0..34417ec 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -693,7 +693,7 @@ void testIndividual() { const float recombinationRate = 0.01; const int genomeSz = 10; - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setGeneticParameters( set{genomeSz-2, genomeSz - 1}, // two chromosomes genomeSz, @@ -750,7 +750,7 @@ void testIndividual() { // Species-level paramters const int genomeSz = 6; - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setGeneticParameters( set{genomeSz - 1}, // one chromosome genomeSz, @@ -842,7 +842,7 @@ void testIndividual() { // Species-level paramters const int genomeSz = 1; - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setGeneticParameters( set{genomeSz - 1}, // one chromosome genomeSz, @@ -912,7 +912,7 @@ void testIndividual() { // Species-level paramters const int genomeSz = 1; - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setGeneticParameters( set{genomeSz - 1}, // one chromosome genomeSz, @@ -965,7 +965,7 @@ void testIndividual() { // Species-level paramters const int genomeSz = 1; - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setGeneticParameters( set{genomeSz - 1}, // one chromosome genomeSz, @@ -1027,7 +1027,7 @@ void testIndividual() { Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); // Genome-level settings - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setGeneticParameters( set{genomeSz - 1}, // one chromosome genomeSz, @@ -1149,7 +1149,7 @@ void testIndividual() { Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); // Genome-level settings - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setGeneticParameters( set{genomeSz - 1}, // one chromosome genomeSz, @@ -1231,7 +1231,7 @@ void testIndividual() { Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); // Genome-level settings - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setGeneticParameters( set{genomeSz - 1}, // one chromosome genomeSz, diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index e01cdca..b8a63ed 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -17,7 +17,7 @@ void testNeutralStats() { // Create genetic structure const int genomeSz = 4; - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setDemogr(createDefaultHaploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome @@ -64,7 +64,7 @@ void testNeutralStats() { // Create genetic structure const int genomeSz = 4; - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setDemogr(createDefaultDiploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome @@ -111,7 +111,7 @@ void testNeutralStats() { // Create genetic structure const int genomeSz = 4; - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setDemogr(createDefaultDiploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome @@ -173,7 +173,7 @@ void testNeutralStats() { } // Create species trait structure - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setDemogr(createDefaultDiploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome @@ -219,7 +219,7 @@ void testNeutralStats() { patchList.insert(patches[i]->getPatchNum()); } // Create species trait structure - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); const bool isDiploid = true; const set genePositions = { 0 }; const float maxAlleleVal = 0; @@ -275,7 +275,7 @@ void testNeutralStats() { const set stgToSample = { 1 }; // Create species trait structure - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setDemogr(createDefaultDiploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome @@ -349,7 +349,7 @@ void testNeutralStats() { const set stgToSample = { 1 }; // Create species trait structure - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setDemogr(createDefaultDiploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome @@ -423,7 +423,7 @@ void testNeutralStats() { const set stgToSample = { 1 }; // Create species trait structure - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setDemogr(createDefaultDiploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome @@ -525,7 +525,7 @@ void testNeutralStats() { const set stgToSample = { 1 }; // Create species trait structure - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setDemogr(createDefaultDiploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome @@ -628,7 +628,7 @@ void testNeutralStats() { const set stgToSample = { 1 }; // Create species trait structure - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setDemogr(createDefaultDiploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome @@ -724,7 +724,7 @@ void testNeutralStats() { const set stgToSample = { 1 }; // Create species trait structure - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setDemogr(createDefaultDiploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome @@ -835,7 +835,7 @@ void testNeutralStats() { const set stgToSample = { 1 }; // Create species trait structure - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setDemogr(createDefaultDiploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome @@ -923,7 +923,7 @@ void testNeutralStats() { const set stgToSample = { 1 }; // Create species trait structure - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setDemogr(createDefaultHaploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome @@ -1009,7 +1009,7 @@ void testNeutralStats() { const set stgToSample = { 1 }; // Create species trait structure - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setDemogr(createDefaultDiploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome diff --git a/unit_tests/testPopulation.cpp b/unit_tests/testPopulation.cpp index 366c63c..63054ad 100644 --- a/unit_tests/testPopulation.cpp +++ b/unit_tests/testPopulation.cpp @@ -34,7 +34,7 @@ void testPopulation() Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); pPatch->addCell(pCell, 0, 0); - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); pSpecies->setDemogr(createDefaultHaploidDemogrParams()); pSpecies->setGeneticParameters( set{genomeSz - 1}, // single chromosome @@ -93,7 +93,7 @@ void testPopulation() Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); pPatch->addCell(pCell, 0, 0); - Species* pSpecies = new Species(); + Species* pSpecies = createDefaultSpecies(); emigRules emig; emig.indVar = true; emig.sexDep = false; From cd4d91f91af133eb9991c25c16dccb5e0f239f85 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 27 Sep 2024 10:07:53 +0100 Subject: [PATCH 272/332] rm empty filestreams --- Main.cpp | 4 +--- Model.cpp | 19 ------------------- Model.h | 6 ------ 3 files changed, 1 insertion(+), 28 deletions(-) diff --git a/Main.cpp b/Main.cpp index 7329932..c60733f 100644 --- a/Main.cpp +++ b/Main.cpp @@ -56,15 +56,12 @@ void run_unit_tests() { } // Global vars -string habmapname, patchmapname, distnmapname; -string costmapname, genfilename; string landFile; paramGrad* paramsGrad; paramStoch* paramsStoch; paramInit* paramsInit; paramSim* paramsSim; RSrandom* pRandom; -vector hfnames; Species* pSpecies; Community* pComm; @@ -96,6 +93,7 @@ int _tmain(int argc, _TCHAR* argv[]) cerr << endl << "Error: " << e.what() << endl; } cout << "All tests have completed." << endl; + return 0; // if tests succeed, we are happy # endif // NDEBUG } diff --git a/Model.cpp b/Model.cpp index ba36992..e150b46 100644 --- a/Model.cpp +++ b/Model.cpp @@ -822,17 +822,6 @@ void OutParameters(Landscape* pLandscape) } #else if (sim.batchMode) outPar << " (see batch file) " << landFile << endl; - else { - outPar << habmapname << endl; - if (ppLand.rasterType == 1) { // habitat % cover - list additional layers - for (int i = 0; i < ppLand.nHab - 1; i++) { - outPar << " " << hfnames[i] << endl; - } - } - if (ppLand.patchModel) { - outPar << "PATCH FILE: " << patchmapname << endl; - } - } #endif outPar << "No. HABITATS:\t" << ppLand.nHab << endl; } @@ -854,8 +843,6 @@ void OutParameters(Landscape* pLandscape) if (chg.costfile != "none" && chg.costfile != "NULL") { outPar << "Costs : " << chg.costfile << endl; } - // outPar << "Change no. " << chg.chgnum << " in year " << chg.chgyear - // << " habitat map: " << chg.habfile << endl; } } outPar << endl << "SPECIES DISTRIBUTION LOADED: \t"; @@ -866,9 +853,6 @@ void OutParameters(Landscape* pLandscape) outPar << "FILE NAME: "; #if !RS_RCPP if (sim.batchMode) outPar << " (see batch file) " << landFile << endl; - else { - outPar << distnmapname << endl; - } #else outPar << name_sp_dist << endl; #endif @@ -1244,9 +1228,6 @@ void OutParameters(Landscape* pLandscape) straightenPath = move.straightenPath; if (trfr.costMap) { outPar << "SMS\tcosts from imported cost map" << endl; -#if !RS_RCPP - outPar << "FILE NAME: " << costmapname << endl; -#endif } else { outPar << "SMS\tcosts:" << endl; diff --git a/Model.h b/Model.h index cd2323c..c1dd261 100644 --- a/Model.h +++ b/Model.h @@ -100,12 +100,6 @@ extern Community* pComm; const bool batchMode = true; extern string landFile; -extern vector hfnames; -extern string habmapname; // see Main.cpp (batch) -extern string patchmapname; // see Main.cpp (batch) -extern string distnmapname; // see Main.cpp (batch) -extern string costmapname; // see Main.cpp (batch) -extern string genfilename; // see Main.cpp (batch) extern RSrandom *pRandom; #if RS_RCPP From bd593156682829b824bcd1e174f48f180c842baf Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 27 Sep 2024 12:53:43 +0100 Subject: [PATCH 273/332] more concise main --- Parameters.cpp | 9 +++------ Parameters.h | 3 +-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/Parameters.cpp b/Parameters.cpp index d987240..cc1de60 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -210,7 +210,9 @@ int paramInit::numInitInds(void) { return (int)initinds.size(); } // Simulation parameters -paramSim::paramSim(void) { +paramSim::paramSim(const string& pathToProjDir) : + dir{pathToProjDir} +{ simulation = 0; reps = years = 1; outIntRange = 1; @@ -232,7 +234,6 @@ paramSim::paramSim(void) { #endif viewLand = false; viewPatch = false; viewGrad = false; viewCosts = false; viewPop = false; viewTraits = false; viewPaths = false; viewGraph = false; - dir = ' '; } paramSim::~paramSim(void) { } @@ -339,10 +340,6 @@ simView paramSim::getViews(void) { return v; } -void paramSim::setDir(string s) { - dir = s; -} - // return directory name depending on option specified string paramSim::getDir(int option) { string s; diff --git a/Parameters.h b/Parameters.h index 8090e2a..bdde173 100644 --- a/Parameters.h +++ b/Parameters.h @@ -333,7 +333,7 @@ struct simView { class paramSim { public: - paramSim(void); + paramSim(const string& pathToProjDir); ~paramSim(void); void setSim(simParams); void setGeneticSim(string patchSamplingOption, bool outputGeneticValues, bool outputWeirCockerham, bool outputWeirHill, int outputStartGenetics, int outputGeneticInterval); @@ -341,7 +341,6 @@ class paramSim { int getSimNum(void); void setViews(simView); simView getViews(void); - void setDir(string); string getDir(int); #if RS_RCPP bool getReturnPopRaster(void); From dce4836bb0f1a318b39bc4796e2ad94a35492136 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 27 Sep 2024 13:08:51 +0100 Subject: [PATCH 274/332] check dir hidden from main --- Model.cpp | 20 +++++++++++++++----- Model.h | 4 +++- Population.cpp | 1 - 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Model.cpp b/Model.cpp index e150b46..c3f0ab7 100644 --- a/Model.cpp +++ b/Model.cpp @@ -673,23 +673,33 @@ bool is_directory(const char* pathname) { #endif //--------------------------------------------------------------------------- -bool CheckDirectory(void) +bool CheckDirectory(const string& pathToProjDir) { bool errorfolder = false; string subfolder; - subfolder = paramsSim->getDir(0) + "Inputs"; + subfolder = pathToProjDir + "Inputs"; const char* inputs = subfolder.c_str(); if (!is_directory(inputs)) errorfolder = true; - subfolder = paramsSim->getDir(0) + "Outputs"; + subfolder = pathToProjDir + "Outputs"; const char* outputs = subfolder.c_str(); if (!is_directory(outputs)) errorfolder = true; - subfolder = paramsSim->getDir(0) + "Output_Maps"; + subfolder = pathToProjDir + "Output_Maps"; const char* outputmaps = subfolder.c_str(); if (!is_directory(outputmaps)) errorfolder = true; - return errorfolder; + if (errorfolder) { + cout << endl << "***** Invalid working directory: " << pathToProjDir + << endl << endl; + cout << "***** Working directory must contain Inputs, Outputs and Output_Maps folders" + << endl << endl; + cout << "*****" << endl; + cout << "***** Simulation ABORTED" << endl; + cout << "*****" << endl; + return false; + } + else return true; } //--------------------------------------------------------------------------- diff --git a/Model.h b/Model.h index c1dd261..bc21004 100644 --- a/Model.h +++ b/Model.h @@ -72,7 +72,9 @@ int RunModel( int // sequential simulation number ); #endif // RS_RCPP && !R_CMD -bool CheckDirectory(void); + +bool CheckDirectory(const string& pathToProjDir); + void PreReproductionOutput( Landscape*, // pointer to Landscape Community*, // pointer to Community diff --git a/Population.cpp b/Population.cpp index 4b37c55..0f86885 100644 --- a/Population.cpp +++ b/Population.cpp @@ -543,7 +543,6 @@ void Population::reproduction(const float localK, const float envval, const int double expected; bool skipbreeding; - //envGradParams grad = paramsGrad->getGradient(); envStochParams env = paramsStoch->getStoch(); demogrParams dem = pSpecies->getDemogrParams(); stageParams sstruct = pSpecies->getStageParams(); From f1f6d9819a33633797029295606fe5f9913a1c5a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 27 Sep 2024 13:15:48 +0100 Subject: [PATCH 275/332] set batchnum out of main --- Parameters.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Parameters.h b/Parameters.h index bdde173..d8c211a 100644 --- a/Parameters.h +++ b/Parameters.h @@ -342,6 +342,10 @@ class paramSim { void setViews(simView); simView getViews(void); string getDir(int); + void setBatchNum(const int& batchNb) { + batchNum = batchNb; + batchMode = true; + } #if RS_RCPP bool getReturnPopRaster(void); bool getCreatePopFile(void); From 97f09b23e8ebc01b6c9d543287fe6c2e2ce5f971 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 27 Sep 2024 14:15:27 +0100 Subject: [PATCH 276/332] clean readParameters --- Model.h | 1 - Population.cpp | 28 ++++++++++------------------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/Model.h b/Model.h index bc21004..a8602da 100644 --- a/Model.h +++ b/Model.h @@ -100,7 +100,6 @@ extern paramSim* paramsSim; extern paramInit* paramsInit; extern Community* pComm; -const bool batchMode = true; extern string landFile; extern RSrandom *pRandom; diff --git a/Population.cpp b/Population.cpp index 0f86885..f10b59d 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1541,14 +1541,11 @@ bool Population::outPopHeaders(int landNr, bool patchModel) { // ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL demogrParams dem = pSpecies->getDemogrParams(); stageParams sstruct = pSpecies->getStageParams(); - if (sim.batchMode) { - name = paramsSim->getDir(2) - + "Batch" + to_string(sim.batchNum) + "_" - + "Sim" + to_string(sim.simulation) + "_Land" + to_string(landNr) + "_Pop.txt"; - } - else { - name = paramsSim->getDir(2) + "Sim" + to_string(sim.simulation) + "_Pop.txt"; - } + name = paramsSim->getDir(2) + + (sim.batchMode ? "Batch" + to_string(sim.batchNum) + "_" : "") + + "Batch" + to_string(sim.batchNum) + "_" + + "Sim" + to_string(sim.simulation) + "_Land" + to_string(landNr) + "_Pop.txt"; + outPop.open(name.c_str()); outPop << "Rep\tYear\tRepSeason"; if (patchModel) outPop << "\tPatchID\tNcells"; @@ -1655,16 +1652,11 @@ void Population::outIndsHeaders(int rep, int landNr, bool patchModel) settleType sett = pSpecies->getSettle(); simParams sim = paramsSim->getSim(); - if (sim.batchMode) { - name = paramsSim->getDir(2) - + "Batch" + to_string(sim.batchNum) + "_" - + "Sim" + to_string(sim.simulation) - + "_Land" + to_string(landNr) + "_Rep" + to_string(rep) + "_Inds.txt"; - } - else { - name = paramsSim->getDir(2) + "Sim" + to_string(sim.simulation) - + "_Rep" + to_string(rep) + "_Inds.txt"; - } + name = paramsSim->getDir(2) + + (sim.batchMode ? "Batch" + to_string(sim.batchNum) + "_" : "") + + "Sim" + to_string(sim.simulation) + + "_Land" + to_string(landNr) + "_Rep" + to_string(rep) + "_Inds.txt"; + outInds.open(name.c_str()); outInds << "Rep\tYear\tRepSeason\tSpecies\tIndID\tStatus"; if (patchModel) outInds << "\tNatal_patch\tPatchID"; From df1233ef5fd67119f1f7ab192e0b4e657d4b8da3 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Sun, 29 Sep 2024 21:28:52 +0100 Subject: [PATCH 277/332] default arg to let rscore run --- Parameters.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Parameters.h b/Parameters.h index d8c211a..a30d3a2 100644 --- a/Parameters.h +++ b/Parameters.h @@ -333,7 +333,7 @@ struct simView { class paramSim { public: - paramSim(const string& pathToProjDir); + paramSim(const string& pathToProjDir = ""); ~paramSim(void); void setSim(simParams); void setGeneticSim(string patchSamplingOption, bool outputGeneticValues, bool outputWeirCockerham, bool outputWeirHill, int outputStartGenetics, int outputGeneticInterval); From 5da938bd2654008d3b1d36c705236ffb6140f164 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 3 Oct 2024 11:13:56 +0100 Subject: [PATCH 278/332] only clear if closing file --- Community.cpp | 17 ++++++++--------- Model.cpp | 6 +++--- Population.cpp | 1 - SubCommunity.cpp | 1 - 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/Community.cpp b/Community.cpp index 9197a54..7298f4e 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1488,8 +1488,10 @@ Rcpp::IntegerMatrix Community::addYearToPopList(int rep, int yr) { // TODO: def bool Community::openOutGenesFile(const bool& isDiploid, const int landNr, const int rep) { if (landNr == -999) { // close the file - if (ofsGenes.is_open()) ofsGenes.close(); - ofsGenes.clear(); + if (ofsGenes.is_open()) { + ofsGenes.close(); + ofsGenes.clear(); + } return true; } string name; @@ -1510,14 +1512,11 @@ bool Community::openOutGenesFile(const bool& isDiploid, const int landNr, const } ofsGenes.open(name.c_str()); - ofsGenes << "Year\tGeneration\tIndID\ttraitType\tlocusPosition"; - if (isDiploid) { - ofsGenes << "\talleleValueA\tdomCoefA\talleleValueBA\tdomCoefB"; - } - else { - ofsGenes << "\talleleValueA\tdomCoefA"; - } + ofsGenes << "Year\tGeneration\tIndID\ttraitType\tlocusPosition" + << "\talleleValueA\tdomCoefA"; + if (isDiploid) ofsGenes << "\talleleValueB\tdomCoefB"; ofsGenes << endl; + return ofsGenes.is_open(); } diff --git a/Model.cpp b/Model.cpp index c3f0ab7..dcac24b 100644 --- a/Model.cpp +++ b/Model.cpp @@ -195,7 +195,7 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->outTraitsRowsHeaders(pSpecies, -999); if (sim.outConnect && ppLand.patchModel) pLandscape->outConnectHeaders(-999); - if (sim.outputWeirCockerham) { + if (sim.outputWeirCockerham || sim.outputWeirHill) { pComm->openNeutralOutputFile(pSpecies, -999); } #if RS_RCPP && !R_CMD @@ -238,8 +238,8 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->outInds(rep, 0, 0, ppLand.landNum); if (sim.outputGeneValues) { - if (!pComm->openOutGenesFile(pSpecies->isDiploid(), ppLand.landNum, rep)) - throw logic_error("Output gene value file could not be initialised."); + bool geneOutFileHasOpened = pComm->openOutGenesFile(pSpecies->isDiploid(), ppLand.landNum, rep); + if (!geneOutFileHasOpened) throw logic_error("Output gene value file could not be initialised."); } // open a new genetics file for each replicate for per locus and pairwise stats diff --git a/Population.cpp b/Population.cpp index f10b59d..d39912d 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1687,7 +1687,6 @@ void Population::outIndsHeaders(int rep, int landNr, bool patchModel) } outInds << "\tDistMoved"; #ifndef NDEBUG - // ALWAYS WRITE NO. OF STEPS outInds << "\tNsteps"; #else if (trfr.usesMovtProc) outInds << "\tNsteps"; diff --git a/SubCommunity.cpp b/SubCommunity.cpp index d1892b7..bb23b3d 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -565,7 +565,6 @@ void SubCommunity::outInds(Landscape* pLandscape, int rep, int yr, int gen, int if (landNr == -999) { // close the file // as all populations may have been deleted, set up a dummy one - // species is not necessary pPop = new Population(); pPop->outIndsHeaders(rep, -999, ppLand.patchModel); delete pPop; From cfd8f86bbdb1a0c86a04b9d6ddc30387b5efdb6b Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Tue, 8 Oct 2024 09:48:58 +0200 Subject: [PATCH 279/332] Updated variable names, which changed in new_genetics but haven't been changed yet if macro RSDEBUG was not active --- Model.cpp | 10 ++++---- Model.h | 2 +- Population.cpp | 62 +++++++++++++++++++++++++------------------------- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/Model.cpp b/Model.cpp index 5308957..3a72fec 100644 --- a/Model.cpp +++ b/Model.cpp @@ -56,7 +56,7 @@ int RunModel(Landscape* pLandscape, int seqsim) // NB this is an overhead here, but is necessary in case the identity of // suitable habitats has been changed from one simulation to another (GUI or batch) // substantial time savings may result during simulation in certain landscapes - // if using neutral markers, set up patches to sample from + // if using neutral markers, set up patches to sample from pLandscape->allocatePatches(pSpecies); } pComm = new Community(pLandscape); // set up community @@ -622,9 +622,9 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->openOutGenesFile(false, -999, rep); } - if (sim.outputWeirCockerham) //close per locus file + if (sim.outputWeirCockerham) //close per locus file pComm->openPerLocusFstFile(pSpecies, pLandscape, -999, rep); - if (sim.outputWeirHill) //close per locus file + if (sim.outputWeirHill) //close per locus file pComm->openPairwiseFstFile(pSpecies, pLandscape, -999, rep); if (sim.saveVisits) { @@ -674,7 +674,7 @@ int RunModel(Landscape* pLandscape, int seqsim) } if (sim.outputWeirHill) pComm->openPairwiseFstFile(pSpecies, pLandscape, -999, 0); - delete pComm; + delete pComm; pComm = 0; #if RS_RCPP && !R_CMD @@ -862,7 +862,7 @@ void OutParameters(Landscape* pLandscape) outPar << "PATCH FILE: " << name_patch << endl; } if (trfr.costMap) { - outPar << "COSTS FILE: " << name_costfile << endl; + outPar << "COSTS FILE: " << gNameCostFile << endl; } #else if (sim.batchMode) outPar << " (see batch file) " << landFile << endl; diff --git a/Model.h b/Model.h index 048bfc2..96aa4eb 100644 --- a/Model.h +++ b/Model.h @@ -116,7 +116,7 @@ extern RSrandom *pRandom; #if RS_RCPP extern std::uint32_t RS_random_seed; -extern string name_landscape, name_patch, name_costfile, name_sp_dist; +extern string name_landscape, name_patch, gNameCostFile, name_sp_dist; #endif //--------------------------------------------------------------------------- #endif diff --git a/Population.cpp b/Population.cpp index d479682..22a8a4a 100644 --- a/Population.cpp +++ b/Population.cpp @@ -57,7 +57,7 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) pPatch = pPch; // record the new population in the patch patchPopn pp = patchPopn(); - pp.pSp = (intptr)pSpecies; + pp.pSp = (intptr)pSpecies; pp.pPop = (intptr)this; pPatch->addPopn(pp); @@ -180,7 +180,7 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) probmale, true, trfr.moveType)); #else inds.push_back(new Individual(pCell, pPatch, stg, age, sstruct.repInterval, - probmale, trfr.moveModel, trfr.moveType)); + probmale, trfr.usesMovtProc, trfr.moveType)); #endif sex = inds[nindivs + i]->getSex(); if (pSpecies->getNTraits() > 0) { @@ -216,7 +216,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { for (int sex = 0; sex < gMaxNbSexes; sex++) { ts.ninds[sex] = 0; ts.sumD0[sex] = ts.ssqD0[sex] = 0.0; - ts.sumAlpha[sex] = ts.ssqAlpha[sex] = 0.0; + ts.sumAlpha[sex] = ts.ssqAlpha[sex] = 0.0; ts.sumBeta[sex] = ts.ssqBeta[sex] = 0.0; ts.sumDist1[sex] = ts.ssqDist1[sex] = 0.0; ts.sumDist2[sex] = ts.ssqDist2[sex] = 0.0; @@ -225,7 +225,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { ts.sumGB[sex] = ts.ssqGB[sex] = 0.0; ts.sumAlphaDB[sex] = ts.ssqAlphaDB[sex] = 0.0; ts.sumBetaDB[sex] = ts.ssqBetaDB[sex] = 0.0; - ts.sumStepL[sex] = ts.ssqStepL[sex] = 0.0; + ts.sumStepL[sex] = ts.ssqStepL[sex] = 0.0; ts.sumRho[sex] = ts.ssqRho[sex] = 0.0; ts.sumS0[sex] = ts.ssqS0[sex] = 0.0; ts.sumAlphaS[sex] = ts.ssqAlphaS[sex] = 0.0; @@ -240,20 +240,20 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { int ninds = (int)inds.size(); for (int iInd = 0; iInd < ninds; iInd++) { int sex = inds[iInd]->getSex(); - if (emig.sexDep || trfr.sexDep || sett.sexDep) - g = sex; + if (emig.sexDep || trfr.sexDep || sett.sexDep) + g = sex; else g = 0; ts.ninds[g] += 1; // emigration traits emigTraits e = inds[iInd]->getIndEmigTraits(); - if (emig.sexDep) g = sex; + if (emig.sexDep) g = sex; else g = 0; - ts.sumD0[g] += e.d0; + ts.sumD0[g] += e.d0; ts.ssqD0[g] += e.d0 * e.d0; - ts.sumAlpha[g] += e.alpha; + ts.sumAlpha[g] += e.alpha; ts.ssqAlpha[g] += e.alpha * e.alpha; - ts.sumBeta[g] += e.beta; + ts.sumBeta[g] += e.beta; ts.ssqBeta[g] += e.beta * e.beta; // transfer traits @@ -265,13 +265,13 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { { trfrSMSTraits sms = inds[iInd]->getIndSMSTraits(); g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ts.sumDP[g] += sms.dp; + ts.sumDP[g] += sms.dp; ts.ssqDP[g] += sms.dp * sms.dp; ts.sumGB[g] += sms.gb; ts.ssqGB[g] += sms.gb * sms.gb; ts.sumAlphaDB[g] += sms.alphaDB; ts.ssqAlphaDB[g] += sms.alphaDB * sms.alphaDB; - ts.sumBetaDB[g] += sms.betaDB; + ts.sumBetaDB[g] += sms.betaDB; ts.ssqBetaDB[g] += sms.betaDB * sms.betaDB; break; } @@ -281,7 +281,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT ts.sumStepL[g] += c.stepLength; ts.ssqStepL[g] += c.stepLength * c.stepLength; - ts.sumRho[g] += c.rho; + ts.sumRho[g] += c.rho; ts.ssqRho[g] += c.rho * c.rho; break; } @@ -292,28 +292,28 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { } else { trfrKernelParams k = inds[iInd]->getIndKernTraits(); - if (trfr.sexDep) g = sex; + if (trfr.sexDep) g = sex; else g = 0; - ts.sumDist1[g] += k.meanDist1; + ts.sumDist1[g] += k.meanDist1; ts.ssqDist1[g] += k.meanDist1 * k.meanDist1; ts.sumDist2[g] += k.meanDist2; ts.ssqDist2[g] += k.meanDist2 * k.meanDist2; - ts.sumProp1[g] += k.probKern1; + ts.sumProp1[g] += k.probKern1; ts.ssqProp1[g] += k.probKern1 * k.probKern1; } // settlement traits settleTraits s = inds[iInd]->getIndSettTraits(); - if (sett.sexDep) g = sex; + if (sett.sexDep) g = sex; else g = 0; // g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ts.sumS0[g] += s.s0; + ts.sumS0[g] += s.s0; ts.ssqS0[g] += s.s0 * s.s0; - ts.sumAlphaS[g] += s.alpha; + ts.sumAlphaS[g] += s.alpha; ts.ssqAlphaS[g] += s.alpha * s.alpha; - ts.sumBetaS[g] += s.beta; + ts.sumBetaS[g] += s.beta; ts.ssqBetaS[g] += s.beta * s.beta; - if (gMaxNbSexes > 1) g = sex; + if (gMaxNbSexes > 1) g = sex; else g = 0; ts.sumGeneticFitness[g] += inds[iInd]->getGeneticFitness(); ts.ssqGeneticFitness[g] += inds[iInd]->getGeneticFitness() * inds[iInd]->getGeneticFitness(); @@ -560,7 +560,7 @@ void Population::reproduction(const float localK, const float envval, const int settleType sett = pSpecies->getSettle(); if (dem.repType == 0) - nsexes = 1; + nsexes = 1; else nsexes = 2; @@ -684,7 +684,7 @@ void Population::reproduction(const float localK, const float envval, const int // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, true, trfr.moveType); #else - newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.moveModel, trfr.moveType); + newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.usesMovtProc, trfr.moveType); #endif if (pSpecies->getNTraits() > 0) { @@ -769,7 +769,7 @@ void Population::reproduction(const float localK, const float envval, const int // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, true, trfr.moveType); #else - newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.moveModel, trfr.moveType); + newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.usesMovtProc, trfr.moveType); #endif if (pSpecies->getNTraits() > 0) { newJuv->inheritTraits(pSpecies, inds[i], father, resol); @@ -891,7 +891,7 @@ void Population::emigration(float localK) // set up local copy of emigration probability table // used when there is no individual variability // NB - IT IS DOUBTFUL THIS CONTRIBUTES ANY SUBSTANTIAL TIME SAVING - if (dem.repType == 0) nsexes = 1; + if (dem.repType == 0) nsexes = 1; else nsexes = 2; double pbEmig[gMaxNbStages][gMaxNbSexes]; @@ -1026,7 +1026,7 @@ disperser Population::extractDisperser(int ix) { disperser d = disperser(); indStats ind = inds[ix]->getStats(); if (ind.status == 1) { // emigrant - d.pInd = inds[ix]; + d.pInd = inds[ix]; d.yes = true; inds[ix] = 0; nInds[ind.stage][ind.sex]--; @@ -1243,7 +1243,7 @@ int Population::transfer(Landscape* pLandscape, short landIx) } #if RS_RCPP // write each individuals current movement step and status to paths file - if (trfr.moveModel && sim.outPaths) { + if (trfr.usesMovtProc && sim.outPaths) { if (nextseason >= sim.outStartPaths && nextseason % sim.outIntPaths == 0) { inds[i]->outMovePath(nextseason); } @@ -1348,7 +1348,7 @@ void Population::survival0(float localK, short option0, short option1) // option0: 0 - stage 0 (juveniles) only // 1 - all stages // 2 - stage 1 and above (all non-juveniles) - // + // // option1: 0 - development only (when survival is annual) // 1 - development and survival // 2 - survival only (when survival is annual) @@ -1719,7 +1719,7 @@ void Population::outIndsHeaders(int rep, int landNr, bool patchModel) // ALWAYS WRITE NO. OF STEPS outInds << "\tNsteps"; #else - if (trfr.moveModel) outInds << "\tNsteps"; + if (trfr.usesMovtProc) outInds << "\tNsteps"; #endif outInds << endl; } @@ -1784,7 +1784,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, if (dem.stageStruct) outInds << "\t" << ind.age << "\t" << ind.stage; if (pSpecies->getNbGenLoadTraits() > 0) outInds << "\t" << inds[i]->getGeneticFitness(); - + if (emig.indVar) { emigTraits e = inds[i]->getIndEmigTraits(); if (emig.densDep) { @@ -1835,7 +1835,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, steps = inds[i]->getSteps(); outInds << "\t" << steps.year; #else - if (trfr.moveModel) { + if (trfr.usesMovtProc) { steps = inds[i]->getSteps(); outInds << "\t" << steps.year; } From 902f089dfed518048696ff0423a4e2136dd4c0bf Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 8 Oct 2024 17:07:22 +0100 Subject: [PATCH 280/332] drop useless allele ID to save memory --- Allele.h | 5 +---- DispersalTrait.cpp | 36 ------------------------------ DispersalTrait.h | 3 --- GeneticFitnessTrait.cpp | 42 +---------------------------------- GeneticFitnessTrait.h | 5 ----- NeutralTrait.cpp | 6 ----- NeutralTrait.h | 7 ++---- Population.cpp | 4 ++-- QuantitativeTrait.h | 5 ----- unit_tests/testIndividual.cpp | 6 ++--- 10 files changed, 9 insertions(+), 110 deletions(-) diff --git a/Allele.h b/Allele.h index 90a6007..fa4ad00 100644 --- a/Allele.h +++ b/Allele.h @@ -2,15 +2,12 @@ #define ALLELEH class Allele { - const int id; const float value; const float dominance; - inline static int counter = 0; // track nb alleles to set unique ID for each allele public: - Allele(float alleleValue, float alleleDominance) : value(alleleValue), dominance(alleleDominance), id(counter) { ++counter; } + Allele(float alleleValue, float alleleDominance) : value(alleleValue), dominance(alleleDominance) { } ~Allele() {} float getAlleleValue() const { return value; }; float getDominanceCoef() const { return dominance; }; - int getId() const { return id; } }; #endif \ No newline at end of file diff --git a/DispersalTrait.cpp b/DispersalTrait.cpp index 5d27cb9..7bd30ad 100644 --- a/DispersalTrait.cpp +++ b/DispersalTrait.cpp @@ -419,31 +419,6 @@ void DispersalTrait::trimPhenotype(float& val) { } } -// ---------------------------------------------------------------------------------------- -// Check if specific locus is heterozygote -// ---------------------------------------------------------------------------------------- -bool DispersalTrait::isHeterozygoteAtLocus(int locus) const { - // assumes diploidy - auto it = genes.find(locus); - if (it == genes.end()) //not found - throw runtime_error("Dispersal gene queried for heterozygosity does not exist."); - else - return(it->second[0].get()->getId() != it->second[1].get()->getId()); -} - -// ---------------------------------------------------------------------------------------- -// Count heterozygote loci in genome -// ---------------------------------------------------------------------------------------- -int DispersalTrait::countHeterozygoteLoci() const { - // assumes diploidy - int count = 0; - for (auto const& [locus, allelePair] : genes) { - if (allelePair.size() == 2) - count += (allelePair[0].get()->getId() != allelePair[1].get()->getId()); - } - return count; -} - // ---------------------------------------------------------------------------------------- // Get allele value at locus // ---------------------------------------------------------------------------------------- @@ -462,17 +437,6 @@ float DispersalTrait::getDomCoefAtLocus(short whichChromosome, int position) con return it->second[whichChromosome]->getDominanceCoef(); } -#ifndef NDEBUG // Testing only - -// Get allele ID at locus -int DispersalTrait::getAlleleIDAtLocus(short whichChromosome, int position) const { - auto it = genes.find(position); - if (it == genes.end()) - throw runtime_error("The Dispersal locus queried for its allele value does not exist."); - return it->second[whichChromosome].get()->getId(); -} -#endif - #ifndef NDEBUG // Create a default set of alleles for testing diff --git a/DispersalTrait.h b/DispersalTrait.h index 97bde41..7060843 100644 --- a/DispersalTrait.h +++ b/DispersalTrait.h @@ -43,8 +43,6 @@ class DispersalTrait : public QuantitativeTrait { float getAlleleValueAtLocus(short chromosome, int i) const override; float getDomCoefAtLocus(short chromosome, int position) const override; - int countHeterozygoteLoci() const; - bool isHeterozygoteAtLocus(int locus) const override; #ifndef NDEBUG // for testing only void overwriteGenes(map>> genSeq) { @@ -58,7 +56,6 @@ class DispersalTrait : public QuantitativeTrait { int startChr) { (this->*_inherit_func_ptr)(fromMother, parentGenes, recomPositions, startChr); } - int getAlleleIDAtLocus(short whichChromosome, int position) const; #endif private: diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index c3b4fbf..522941c 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -387,35 +387,6 @@ float GeneticFitnessTrait::express() { return phenotype; } -// ---------------------------------------------------------------------------------------- -// Check if specific locus is heterozygote -// ---------------------------------------------------------------------------------------- -bool GeneticFitnessTrait::isHeterozygoteAtLocus(int locus) const { - // assumes diploidy - auto it = genes.find(locus); - if (it == genes.end()) - throw runtime_error("Genetic load gene queried for heterozygosity does not exist."); - else { - shared_ptr alleleRight = it->second[0] == 0 ? wildType : it->second[0]; - shared_ptr alleleLeft = it->second[1] == 0 ? wildType : it->second[1]; - return alleleRight != alleleLeft; - } -} - -// ---------------------------------------------------------------------------------------- -// Count heterozygote loci in genome -// ---------------------------------------------------------------------------------------- -int GeneticFitnessTrait::countHeterozygoteLoci() const { - // assumes diploidy - int count = 0; - for (auto const& [locus, allelePair] : genes) { - shared_ptr alleleLeft = allelePair[0] == 0 ? wildType : allelePair[0]; - shared_ptr alleleRight = allelePair[1] == 0 ? wildType : allelePair[1]; - count += alleleLeft != alleleRight; - } - return count; -} - // ---------------------------------------------------------------------------------------- // Get allele value at locus // ---------------------------------------------------------------------------------------- @@ -432,15 +403,4 @@ float GeneticFitnessTrait::getDomCoefAtLocus(short whichChromosome, int position if (it == genes.end()) throw runtime_error("The genetic load locus queried for its dominance coefficient does not exist."); return it->second[whichChromosome] == 0 ? wildType->getDominanceCoef() : it->second[whichChromosome]->getDominanceCoef(); -} - -#ifndef NDEBUG // Testing only -// Get allele ID at locus -int GeneticFitnessTrait::getAlleleIDAtLocus(short whichChromosome, int position) const { - auto it = genes.find(position); - if (it == genes.end()) - throw runtime_error("The Dispersal locus queried for its allele ID does not exist."); - return it->second[whichChromosome].get()->getId(); -} - -#endif // NDEBUG \ No newline at end of file +} \ No newline at end of file diff --git a/GeneticFitnessTrait.h b/GeneticFitnessTrait.h index 3db23cf..ff072ed 100644 --- a/GeneticFitnessTrait.h +++ b/GeneticFitnessTrait.h @@ -47,11 +47,6 @@ class GeneticFitnessTrait : public QuantitativeTrait { virtual float getAlleleValueAtLocus(short chromosome, int position) const override; virtual float getDomCoefAtLocus(short chromosome, int position) const override; - virtual int countHeterozygoteLoci() const; - virtual bool isHeterozygoteAtLocus(int locus) const override; -#ifndef NDEBUG // for testing only - int getAlleleIDAtLocus(short whichChromosome, int position) const; -#endif private: diff --git a/NeutralTrait.cpp b/NeutralTrait.cpp index fb77350..8d40481 100644 --- a/NeutralTrait.cpp +++ b/NeutralTrait.cpp @@ -291,12 +291,6 @@ float NeutralTrait::getAlleleValueAtLocus(short whichChromosome, int position) c } #ifndef NDEBUG // Testing only -// Get allele ID at locus -int NeutralTrait::getAlleleIDAtLocus(short whichChromosome, int position) const { - // for neutral genes this is the same as the allele value - // need this declaration for quanti trait that use an actual ID - return getAlleleValueAtLocus(whichChromosome, position); -} // Create a default set of neutral alleles for testing // diff --git a/NeutralTrait.h b/NeutralTrait.h index 160abb0..7cccf46 100644 --- a/NeutralTrait.h +++ b/NeutralTrait.h @@ -51,11 +51,8 @@ class NeutralTrait : public QuantitativeTrait { return 0.0; } - virtual int countHeterozygoteLoci() const; - virtual bool isHeterozygoteAtLocus(int locus) const override; -#ifndef NDEBUG // for testing only - int getAlleleIDAtLocus(short whichChromosome, int position) const; -#endif + int countHeterozygoteLoci() const; + bool isHeterozygoteAtLocus(int locus) const; private: diff --git a/Population.cpp b/Population.cpp index d39912d..d6a5142 100644 --- a/Population.cpp +++ b/Population.cpp @@ -400,7 +400,7 @@ int Population::countHeterozygoteLoci() { int nbHetero = 0; if (pSpecies->isDiploid()) { for (Individual* ind : sampledInds) { - const auto trait = ind->getTrait(NEUTRAL); + const NeutralTrait* trait = (NeutralTrait*)(ind->getTrait(NEUTRAL)); nbHetero += trait->countHeterozygoteLoci(); } } @@ -416,7 +416,7 @@ vector Population::countNbHeterozygotesEachLocus() { if (pSpecies->isDiploid()) { for (Individual* ind : sampledInds) { - const auto trait = ind->getTrait(NEUTRAL); + const NeutralTrait* trait = (NeutralTrait*)ind->getTrait(NEUTRAL); int counter = 0; for (auto position : positions) { hetero[counter] += trait->isHeterozygoteAtLocus(position); diff --git a/QuantitativeTrait.h b/QuantitativeTrait.h index 1ab22c2..53ae033 100644 --- a/QuantitativeTrait.h +++ b/QuantitativeTrait.h @@ -22,13 +22,8 @@ class QuantitativeTrait { virtual bool isInherited() const = 0; virtual float getAlleleValueAtLocus(short chromosome, int i) const = 0; virtual float getDomCoefAtLocus(short whichChromosome, int position) const = 0; - virtual int countHeterozygoteLoci() const = 0; - virtual bool isHeterozygoteAtLocus(int loci) const = 0; virtual float express() = 0; virtual ~QuantitativeTrait() { } -#ifndef NDEBUG // for testing only - virtual int getAlleleIDAtLocus(short whichChromosome, int position) const = 0; -#endif }; extern RSrandom* pRandom; diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 34417ec..36fb700 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -662,8 +662,8 @@ void testGenetics() { } bool haveSameEmigD0Allele(const Individual& indA, const Individual& indB, const int& position, short whichHaplo = 0) { - return indA.getTrait(E_D0)->getAlleleIDAtLocus(whichHaplo, position) - == indB.getTrait(E_D0)->getAlleleIDAtLocus(whichHaplo, position); + return indA.getTrait(E_D0)->getAlleleValueAtLocus(whichHaplo, position) + == indB.getTrait(E_D0)->getAlleleValueAtLocus(whichHaplo, position); } void testIndividual() { @@ -678,7 +678,7 @@ void testIndividual() { // Genetic linkage + Chromosome breaks // Considering diallelic genes A, B, C, D with: - // A, B, C sit on chr.1, D sits on chr.2 + // A, B, C are on chr.1, D is on chr.2 // A, B are adjacent, C sits on the other end of chr.1 // C, D have adjacent positions in genome (but are on separate chr.) // AB------------C//D From 73a674b877707e7f8a5bc29dd9c3d61f7691453f Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 18 Oct 2024 16:13:27 +0100 Subject: [PATCH 281/332] allow negative values for settlement and emigration alphas --- SpeciesTrait.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 8818cd3..61db3a5 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -110,13 +110,9 @@ bool SpeciesTrait::isValidTraitVal(const float& val) const { break; } case E_ALPHA_F: case E_ALPHA_M: case E_ALPHA: - { - return val > 0.0; - break; - } case E_BETA_F: case E_BETA_M: case E_BETA: { - return true; // inflexion point can be any value + return true; // slope and inflexion point can be any value break; } /// Settlement @@ -126,13 +122,9 @@ bool SpeciesTrait::isValidTraitVal(const float& val) const { break; } case S_ALPHA_F: case S_ALPHA_M: case S_ALPHA: - { - return val > 0.0; - break; - } case S_BETA_F: case S_BETA_M: case S_BETA: { - return true; + return true; // slope and inflection point can be any value break; } /// Transfer - Kernels From 03681a8993f0b59e8ebc1eba8842ed1bd3c44ca7 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 18 Oct 2024 17:23:49 +0100 Subject: [PATCH 282/332] small cleanup --- Population.cpp | 3 --- RSrandom.cpp | 8 ++++++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Population.cpp b/Population.cpp index d6a5142..d2c24dd 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1438,9 +1438,6 @@ void Population::survival0(float localK, short option0, short option1) if ((ind.stage == 0 && option0 < 2) || (ind.stage > 0 && option0 > 0)) { // condition for processing the stage is met... if (ind.status < 6) { // not already doomed - if (ind.sex < sex_t::FEM || ind.sex > sex_t::MAL) - // ?? MSVC believes it's important to bound check ind.sex - throw runtime_error("Individual sex is out of bounds"); double probsurv = surv[ind.stage][ind.sex]; // does the individual survive? if (pRandom->Bernoulli(probsurv)) { // survives diff --git a/RSrandom.cpp b/RSrandom.cpp index 81abf2a..ed12c98 100644 --- a/RSrandom.cpp +++ b/RSrandom.cpp @@ -120,8 +120,12 @@ float RSrandom::FRandom(float min, float max) { } int RSrandom::Bernoulli(double p) { - if (p < 0) throw runtime_error("Bernoulli's p cannot be negative.\n"); - if (p > 1) throw runtime_error("Bernoulli's p cannot be above 1.\n"); + if (p < 0) { + throw runtime_error("Bernoulli's p cannot be negative.\n"); + } + if (p > 1) { + throw runtime_error("Bernoulli's p cannot be above 1.\n"); + } return Random() < p; } From 0c450bcfddfd1ef55b7011c1ffc72656e093b8b9 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 23 Oct 2024 17:07:40 +0100 Subject: [PATCH 283/332] expression should be half both allele if all dom coeffs are 0 --- GeneticFitnessTrait.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index 522941c..b3e1e1b 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -375,14 +375,14 @@ float GeneticFitnessTrait::express() { shared_ptr pAlleleB = pAllelePair[1] == 0 ? wildType : pAllelePair[1]; sB = pAlleleB->getAlleleValue(); hB = pAlleleB->getDominanceCoef(); + + sumDomCoeffs = hA + hB; + hLocus = sumDomCoeffs == 0.0 ? 0.5 : hA / sumDomCoeffs; + phenotype *= 1 - hLocus * sA - (1 - hLocus) * sB; } else { - sB = 0.0; - hB = 0.0; + phenotype *= 1 - sA; } - sumDomCoeffs = hA + hB; - hLocus = sumDomCoeffs == 0.0 ? 0.0 : hA / sumDomCoeffs; - phenotype *= 1 - hLocus * sA - (1 - hLocus) * sB; } return phenotype; } From 70ec1f60c40b027649f32f7eab7f9476587bb8ec Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Thu, 24 Oct 2024 10:27:05 +0200 Subject: [PATCH 284/332] fixed compiling bug in Management.h --- Management.h | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Management.h b/Management.h index 2763f95..efa0723 100644 --- a/Management.h +++ b/Management.h @@ -38,14 +38,9 @@ #ifndef ManagementH #define ManagementH -//#if LINUX_CLUSTER -//#include -//#else #include -//#endif #include #include -//#include #include #include #include @@ -66,12 +61,8 @@ using namespace std; #if RS_RCPP typedef intptr_t intptr; #else -#if RSWIN64 typedef unsigned long long intptr; -#else -typedef unsigned int intptr; -#endif -#endif +#endif // RS_RCPP From 750911188fd90222dc841153ed7048151d20d2f9 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Thu, 24 Oct 2024 10:53:01 +0200 Subject: [PATCH 285/332] fixed bug due to merging in Model.cpp --- Model.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Model.cpp b/Model.cpp index 8216f2a..47bc815 100644 --- a/Model.cpp +++ b/Model.cpp @@ -786,6 +786,8 @@ void OutParameters(Landscape* pLandscape) outPar << "BATCH MODE \t"; if (sim.batchMode) outPar << "yes" << endl; else outPar << "no" << endl; +#if RS_RCPP + outPar << "SEED \t" << RS_random_seed << endl; #else outPar << "SEED \t" << pRandom->getSeed() << endl; #endif From 3b81ba1a69d740b121df39f903a26e56ffa55e64 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 24 Oct 2024 11:59:29 +0100 Subject: [PATCH 286/332] fix scaled sd parameter not being passed from parent to offspring --- GeneticFitnessTrait.cpp | 14 +++++++++----- GeneticFitnessTrait.h | 2 +- SpeciesTrait.h | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index b3e1e1b..81847de 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -125,8 +125,13 @@ GeneticFitnessTrait::GeneticFitnessTrait(SpeciesTrait* P) // Copies immutable features from a parent trait // Only called via clone() // ---------------------------------------------------------------------------------------- -GeneticFitnessTrait::GeneticFitnessTrait(const GeneticFitnessTrait& T) : pSpeciesTrait(T.pSpeciesTrait), _inherit_func_ptr(T._inherit_func_ptr) -{} +GeneticFitnessTrait::GeneticFitnessTrait(const GeneticFitnessTrait& T) : + pSpeciesTrait(T.pSpeciesTrait), + _inherit_func_ptr(T._inherit_func_ptr), + scaledDomMeanSelCoeff(T.scaledDomMeanSelCoeff) +{ + // nothing +} void GeneticFitnessTrait::initialise() { // All positions start at wild type, mutations accumulate through simulation @@ -215,11 +220,10 @@ float GeneticFitnessTrait::drawDominance(float selCoef) { } case SCALED: { - const float min = 0; const float h_d = dominanceParameters.find(MEAN)->second; const float k = -log(2 * h_d) / scaledDomMeanSelCoeff; - const float max = static_cast(exp(-k * selCoef)); - h = static_cast(pRandom->FRandom(min, max)); + const float max = exp(-k * selCoef); + h = pRandom->FRandom(0, max); break; } diff --git a/GeneticFitnessTrait.h b/GeneticFitnessTrait.h index ff072ed..001e1c2 100644 --- a/GeneticFitnessTrait.h +++ b/GeneticFitnessTrait.h @@ -60,7 +60,7 @@ class GeneticFitnessTrait : public QuantitativeTrait { void initialise(); // Mutation - float scaledDomMeanSelCoeff; // s_d, only for scaled dominance distribution + float scaledDomMeanSelCoeff = 0; // s_d, only for scaled dominance distribution float drawDominance(float); float drawSelectionCoef(); diff --git a/SpeciesTrait.h b/SpeciesTrait.h index 43b7943..5a323e9 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -33,7 +33,7 @@ class SpeciesTrait { ); bool isValidTraitVal(const float& val) const; - TraitType getTraitType() const { return traitType; } + TraitType getTraitType() const { return traitType; } bool isOutput() const { return traitIsOutput; } // Getters From 02adc8286f61607f9f1e8785d793c661b893c51d Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 4 Nov 2024 14:10:30 +0100 Subject: [PATCH 287/332] bit of cleaning of survival --- Model.cpp | 10 +++------- Population.cpp | 7 ++++--- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/Model.cpp b/Model.cpp index dcac24b..970267a 100644 --- a/Model.cpp +++ b/Model.cpp @@ -483,12 +483,9 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->outNeutralGenetics(pSpecies, rep, yr, gen, sim.outputWeirCockerham, sim.outputWeirHill); } } - if (dem.stageStruct) { - pComm->survival(1, 0, 1); - } - else { // non-structured population - pComm->survival(1, 0, 1); - } + + // Resolve survival and devlpt + pComm->survival(1, 0, 1); } // end of the generation loop @@ -519,7 +516,6 @@ int RunModel(Landscape* pLandscape, int seqsim) cout << "All populations went extinct." << endl; yr++; break; - } } diff --git a/Population.cpp b/Population.cpp index d2c24dd..00d31e2 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1336,14 +1336,15 @@ void Population::survival0(float localK, short option0, short option1) stageParams sstruct = pSpecies->getStageParams(); // get current population size - int ninds = (int)inds.size(); + int ninds = inds.size(); if (ninds == 0) return; + // set up local copies of species development and survival tables - int nsexes; - if (dem.repType == 0) nsexes = 1; else nsexes = 2; + int nsexes = dem.repType == 0 ? 1 : 2; float dev[gMaxNbStages][gMaxNbSexes]; float surv[gMaxNbStages][gMaxNbSexes]; short minAge[gMaxNbStages][gMaxNbSexes]; + for (int stg = 0; stg < sstruct.nStages; stg++) { for (int sex = 0; sex < nsexes; sex++) { if (dem.stageStruct) { From e5a314bdc3e6443e0b6b344709d13a4c721d93cc Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Thu, 14 Nov 2024 14:46:08 +0100 Subject: [PATCH 288/332] For now only commented out code for file reads that are not necessary anymore (still need to be tested for unix) RS_random_seed not defined but needed for R package --- Landscape.cpp | 90 +++++++++++++++++++++++++-------------------------- RSrandom.cpp | 6 ++++ 2 files changed, 51 insertions(+), 45 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index e7f358b..8fa39f8 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -171,15 +171,15 @@ int InitDist::readDistribution(string distfile) { #endif // open distribution file -#if RS_RCPP - dfile.open(distfile, std::ios::binary); - if (spdistraster.utf) { - // apply BOM-sensitive UTF-16 facet - dfile.imbue(std::locale(dfile.getloc(), new std::codecvt_utf16)); - } -#else +// #if RS_RCPP +// dfile.open(distfile, std::ios::binary); +// if (spdistraster.utf) { +// // apply BOM-sensitive UTF-16 facet +// dfile.imbue(std::locale(dfile.getloc(), new std::codecvt_utf16)); +// } +// #else dfile.open(distfile.c_str()); -#endif +// #endif if (!dfile.is_open()) return 21; // read landscape data from header records of distribution file @@ -334,8 +334,8 @@ void Landscape::resetLand(void) { void Landscape::setLandParams(landParams ppp, bool batchMode) { - generated = ppp.generated; - patchModel = ppp.patchModel; + generated = ppp.generated; + patchModel = ppp.patchModel; spDist = ppp.spDist; dynamic = ppp.dynamic; landNum = ppp.landNum; @@ -870,7 +870,7 @@ set Landscape::samplePatches(const string& samplingOption, int nbToSample, || p->speciesIsPresent(pSpecies)) // otherwise only patches with at least 1 ind eligiblePatches.push_back(p->getPatchNum()); } - + if (samplingOption == "all") { sampledPatches = eligiblePatches; } @@ -1558,10 +1558,10 @@ void Landscape::recordPatchChanges(int landIx) { int Landscape::numPatchChanges(void) { return (int)patchchanges.size(); } patchChange Landscape::getPatchChange(int i) { - patchChange c; - c.chgnum = 99999999; + patchChange c; + c.chgnum = 99999999; c.x = c.y = c.oldpatch = c.newpatch = -1; - if (i >= 0 && i < (int)patchchanges.size()) + if (i >= 0 && i < (int)patchchanges.size()) c = patchchanges[i]; return c; } @@ -1792,27 +1792,27 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string initParams init = paramsInit->getInit(); // open habitat file and optionally also patch file -#if RS_RCPP - hfile.open(habfile, std::ios::binary); - if (landraster.utf) { - // apply BOM-sensitive UTF-16 facet - hfile.imbue(std::locale(hfile.getloc(), new std::codecvt_utf16)); - } -#else +// #if RS_RCPP +// hfile.open(habfile, std::ios::binary); +// if (landraster.utf) { +// // apply BOM-sensitive UTF-16 facet +// hfile.imbue(std::locale(hfile.getloc(), new std::codecvt_utf16)); +// } +// #else hfile.open(habfile.c_str()); -#endif +// #endif if (!hfile.is_open()) return 11; if (fileNum == 0) { if (patchModel) { -#if RS_RCPP - pfile.open(pchfile, std::ios::binary); - if (patchraster.utf) { - // apply BOM-sensitive UTF-16 facet - pfile.imbue(std::locale(pfile.getloc(), new std::codecvt_utf16)); - } -#else +// #if RS_RCPP +// pfile.open(pchfile, std::ios::binary); +// if (patchraster.utf) { +// // apply BOM-sensitive UTF-16 facet +// pfile.imbue(std::locale(pfile.getloc(), new std::codecvt_utf16)); +// } +// #else pfile.open(pchfile.c_str()); -#endif +// #endif if (!pfile.is_open()) { hfile.close(); hfile.clear(); return 12; @@ -1841,23 +1841,23 @@ resol = (int) tmpresol; } #endif - dimX = ncols; - dimY = nrows; - minX = maxY = 0; + dimX = ncols; + dimY = nrows; + minX = maxY = 0; maxX = dimX - 1; maxY = dimY - 1; if (fileNum == 0) { // set initialisation limits to landscape limits init.minSeedX = init.minSeedY = 0; - init.maxSeedX = maxX; + init.maxSeedX = maxX; init.maxSeedY = maxY; paramsInit->setInit(init); } if (fileNum == 0) { if (patchModel) { - for (int i = 0; i < 5; i++) + for (int i = 0; i < 5; i++) pfile >> header >> pfloat; pfile >> header >> pchnodata; } @@ -2294,15 +2294,15 @@ int Landscape::readCosts(string fname) int maxcost = 0; // open cost file -#if RS_RCPP - costs.open(fname, std::ios::binary); - if (costsraster.utf) { - // apply BOM-sensitive UTF-16 facet - costs.imbue(std::locale(costs.getloc(), new std::codecvt_utf16)); - } -#else +// #if RS_RCPP +// costs.open(fname, std::ios::binary); +// if (costsraster.utf) { +// // apply BOM-sensitive UTF-16 facet +// costs.imbue(std::locale(costs.getloc(), new std::codecvt_utf16)); +// } +// #else costs.open(fname.c_str()); -#endif +// #endif // read headers and check that they correspond to the landscape ones costs >> header; #if RS_RCPP @@ -2671,13 +2671,13 @@ landParams createDefaultLandParams(const int& dim) { ls_params.maxX = ls_params.maxY = ls_params.dimX - 1; ls_params.resol = ls_params.spResol = 1; ls_params.rasterType = 0; // habitat types - + ls_params.patchModel = false; ls_params.spDist = false; ls_params.generated = false; ls_params.dynamic = false; ls_params.landNum = 0; - ls_params.nHab = ls_params.nHabMax = 0; // irrelevant for habitat codes + ls_params.nHab = ls_params.nHabMax = 0; // irrelevant for habitat codes return ls_params; } diff --git a/RSrandom.cpp b/RSrandom.cpp index ed12c98..43475e1 100644 --- a/RSrandom.cpp +++ b/RSrandom.cpp @@ -25,6 +25,12 @@ extern paramSim* paramsSim; #endif +#if RS_RCPP +std::uint32_t RS_random_seed = 0; +#else +int RS_random_seed = 0; +#endif + // C'tor #if RS_RCPP // if parameter seed is negative, a random seed will be generated, else it is used as seed From 6d08f6599a3a64fec8ceba50e98c7e2ff6254d50 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Fri, 15 Nov 2024 08:20:58 +0100 Subject: [PATCH 289/332] changed gNameCostfile to name_costfile --- Model.cpp | 2 +- Model.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Model.cpp b/Model.cpp index e7ee8f8..9038dbe 100644 --- a/Model.cpp +++ b/Model.cpp @@ -838,7 +838,7 @@ void OutParameters(Landscape* pLandscape) outPar << "PATCH FILE: " << name_patch << endl; } if (trfr.costMap) { - outPar << "COSTS FILE: " << gNameCostFile << endl; + outPar << "COSTS FILE: " << name_costfile << endl; } #else if (sim.batchMode) outPar << " (see batch file) " << landFile << endl; diff --git a/Model.h b/Model.h index 58b419a..d57f3c5 100644 --- a/Model.h +++ b/Model.h @@ -107,7 +107,7 @@ extern RSrandom *pRandom; #if RS_RCPP extern std::uint32_t RS_random_seed; -extern string name_landscape, name_patch, gNameCostFile, name_sp_dist; +extern string name_landscape, name_patch, name_costfile, name_sp_dist; #endif //--------------------------------------------------------------------------- #endif From 139387b35022a3aed25c02d0d605be8e3dee507f Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 19 Nov 2024 17:08:41 +0000 Subject: [PATCH 290/332] initialise genetic load with non-zero sel + dom coeffs #75 --- GeneticFitnessTrait.cpp | 202 +++++++++++++++++++++++++++++++--------- GeneticFitnessTrait.h | 13 ++- SpeciesTrait.cpp | 39 ++++++-- SpeciesTrait.h | 15 ++- 4 files changed, 211 insertions(+), 58 deletions(-) diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index 81847de..82cfb17 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -11,13 +11,106 @@ GeneticFitnessTrait::GeneticFitnessTrait(SpeciesTrait* P) pSpeciesTrait = P; ExpressionType expressionType = pSpeciesTrait->getExpressionType(); - initialise(); - _inherit_func_ptr = (pSpeciesTrait->getPloidy() == 1) ? &GeneticFitnessTrait::inheritHaploid : &GeneticFitnessTrait::inheritDiploid; //this could be changed if we wanted some alternative form of inheritance + // Set initialisation parameters + DistributionType initialDistribution = pSpeciesTrait->getInitialDistribution(); + map initialParameters = pSpeciesTrait->getInitialParameters(); + switch (initialDistribution) { + case UNIFORM: + { + if (initialParameters.count(MAX) != 1) + throw logic_error("Error: initial uniform distribution parameter must contain max value (e.g. max= ) \n"); + if (initialParameters.count(MIN) != 1) + throw logic_error("Error: initial uniform distribution parameter must contain min value (e.g. min= ) \n"); + break; + } + case NORMAL: + { + if (initialParameters.count(MEAN) != 1) + throw logic_error("Error: initial normal distribution parameter must contain mean value (e.g. mean= ) \n"); + if (initialParameters.count(SD) != 1) + throw logic_error("Error: initial normal distribution parameter must contain sdev value (e.g. sdev= ) \n"); + break; + } + case GAMMA: + { + if (initialParameters.count(SHAPE) != 1) + throw logic_error("Error:: genetic load dominance distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); + if (initialParameters.count(SCALE) != 1) + throw logic_error("Error:: genetic load dominance distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); + break; + } + case NEGEXP: + { + if (initialParameters.count(MEAN) != 1) + throw logic_error("Error:: genetic load dominance distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); + break; + } + case NONE: // initialise with default (i.e. zero) values + break; + default: + { + throw logic_error("wrong parameter value for parameter \"initialisation of dispersal traits\", must be uniform/normal \n"); + break; + } + } + + DistributionType initDomDistribution = pSpeciesTrait->getInitialDistribution(); + map initDomParameters = pSpeciesTrait->getInitialParameters(); + switch (initDomDistribution) { + case UNIFORM: + { + if (initDomParameters.count(MAX) != 1) + throw logic_error("Error:: genetic load dominance uniform distribution parameter must contain one max value (e.g. max= ) \n"); + if (initDomParameters.count(MIN) != 1) + throw logic_error("Error:: genetic load dominance uniform distribution parameter must contain one min value (e.g. min= ) \n"); + break; + } + case NORMAL: + { + if (initDomParameters.count(MEAN) != 1) + throw logic_error("Error:: genetic load dominance distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); + if (initDomParameters.count(SD) != 1) + throw logic_error("Error:: genetic load dominance distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); + break; + } + case GAMMA: + { + if (initDomParameters.count(SHAPE) != 1) + throw logic_error("Error:: genetic load dominance distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); + if (initDomParameters.count(SCALE) != 1) + throw logic_error("Error:: genetic load dominance distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); + break; + } + case NEGEXP: + { + if (initDomParameters.count(MEAN) != 1) + throw logic_error("Error:: genetic load dominance distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); + break; + } + case SCALED: + { + if (initDomParameters.count(MEAN) != 1) + throw logic_error("Error:: genetic load dominance distribution set to scaled, so parameters must contain mean dominance value (e.g. mean= ) \n"); + break; + // Set for drawing initial values + setScaledCoeff(initialDistribution, initialParameters); + } + case NONE: // default values, zero-dominance coefficients + break; + default: + { + throw logic_error("Error:: wrong parameter value for genetic load dominance model, must be uniform/normal/gamma/negExp/scaled \n"); + break; + } + } + + // Draw initial values + initialise(); + DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); map mutationParameters = pSpeciesTrait->getMutationParameters(); - switch (mutationDistribution) { case UNIFORM: { @@ -92,24 +185,8 @@ GeneticFitnessTrait::GeneticFitnessTrait(SpeciesTrait* P) if (dominanceParameters.count(MEAN) != 1) throw logic_error("Error:: genetic load dominance distribution set to scaled, so parameters must contain mean dominance value (e.g. mean= ) \n"); - // Calculate mean selection coeff s_d for calculation of k - switch (mutationDistribution) - { - case UNIFORM: - scaledDomMeanSelCoeff = (mutationParameters.find(MIN)->second + mutationParameters.find(MAX)->second) / 2; - break; - case NORMAL: - scaledDomMeanSelCoeff = mutationParameters.find(MEAN)->second; - break; - case GAMMA: - scaledDomMeanSelCoeff = mutationParameters.find(SHAPE)->second * mutationParameters.find(SCALE)->second; - break; - case NEGEXP: - scaledDomMeanSelCoeff = 1 / mutationParameters.find(MEAN)->second; - break; - default: - break; - } + // Set for drawing mutations (overwrite initial value) + setScaledCoeff(mutationDistribution, mutationParameters); break; } default: @@ -120,6 +197,29 @@ GeneticFitnessTrait::GeneticFitnessTrait(SpeciesTrait* P) } } +// Calculate mean selection coeff s_d for calculation of k +void GeneticFitnessTrait::setScaledCoeff(const DistributionType& selCoeffDist, const map& selCoeffParams) +{ + switch (selCoeffDist) + { + case UNIFORM: + scaledDomMeanSelCoeff = (selCoeffParams.find(MIN)->second + selCoeffParams.find(MAX)->second) / 2; + break; + case NORMAL: + scaledDomMeanSelCoeff = selCoeffParams.find(MEAN)->second; + break; + case GAMMA: + scaledDomMeanSelCoeff = selCoeffParams.find(SHAPE)->second * selCoeffParams.find(SCALE)->second; + break; + case NEGEXP: + scaledDomMeanSelCoeff = 1 / selCoeffParams.find(MEAN)->second; + break; + case NONE: + throw logic_error("Scaled dominance distribution cannot be used with default allele distribution."); + default: break; + } +} + // ---------------------------------------------------------------------------------------- // Inheritance constructor // Copies immutable features from a parent trait @@ -134,12 +234,25 @@ GeneticFitnessTrait::GeneticFitnessTrait(const GeneticFitnessTrait& T) : } void GeneticFitnessTrait::initialise() { - // All positions start at wild type, mutations accumulate through simulation - const set genePositions = pSpeciesTrait->getGenePositions(); + float initSelCoeff; + float initDomCoeff; short ploidy = pSpeciesTrait->getPloidy(); - const vector> wildTypeGene(ploidy, wildType); + auto initDist = pSpeciesTrait->getInitialDistribution(); + auto initParams = pSpeciesTrait->getInitialParameters(); + auto initDomDist = pSpeciesTrait->getInitDomDistribution(); + auto initDomParams = pSpeciesTrait->getInitDomParameters(); + + const set genePositions = pSpeciesTrait->getGenePositions(); for (auto position : genePositions) { - genes.insert(make_pair(position, wildTypeGene)); + vector> initialGene(ploidy); + for (int p = 0; p < ploidy; p++) { + initSelCoeff = initDist == NONE ? 0.0 + : drawSelectionCoef(initDist, initParams); + initDomCoeff = initDomDist == NONE ? 0.0 + : drawDominance(initSelCoeff, initDomDist, initDomParams); + initialGene[p] = make_shared(initSelCoeff, initDomCoeff); + } + genes.insert(make_pair(position, initialGene)); } } @@ -171,8 +284,15 @@ void GeneticFitnessTrait::mutate() auto it = genes.find(m); if (it == genes.end()) throw runtime_error("Locus sampled for mutation doesn't exist."); - newSelectionCoef = drawSelectionCoef(); - newDominanceCoef = drawDominance(newSelectionCoef); + newSelectionCoef = drawSelectionCoef( + pSpeciesTrait->getMutationDistribution(), + pSpeciesTrait->getMutationParameters() + ); + newDominanceCoef = drawDominance( + newSelectionCoef, + pSpeciesTrait->getDominanceDistribution(), + pSpeciesTrait->getDominanceParameters() + ); it->second[p] = make_shared(newSelectionCoef, newDominanceCoef); } } @@ -182,24 +302,21 @@ void GeneticFitnessTrait::mutate() // ---------------------------------------------------------------------------------------- // get dominance value for new mutation // ---------------------------------------------------------------------------------------- -float GeneticFitnessTrait::drawDominance(float selCoef) { - - DistributionType dominanceDistribution = pSpeciesTrait->getDominanceDistribution(); - map dominanceParameters = pSpeciesTrait->getDominanceParameters(); +float GeneticFitnessTrait::drawDominance(float selCoef, const DistributionType& domDist, const map& domParams) { float h; - switch (dominanceDistribution) { + switch (domDist) { case UNIFORM: { - float maxD = dominanceParameters.find(MAX)->second; - float minD = dominanceParameters.find(MIN)->second; + float maxD = domParams.find(MAX)->second; + float minD = domParams.find(MIN)->second; h = pRandom->FRandom(minD, maxD); break; } case NORMAL: { - const float mean = dominanceParameters.find(MEAN)->second; - const float sd = dominanceParameters.find(SD)->second; + const float mean = domParams.find(MEAN)->second; + const float sd = domParams.find(SD)->second; do { h = static_cast(pRandom->Normal(mean, sd)); } while (h <= 0.0); @@ -207,20 +324,20 @@ float GeneticFitnessTrait::drawDominance(float selCoef) { } case GAMMA: { - const float shape = dominanceParameters.find(SHAPE)->second; - const float scale = dominanceParameters.find(SCALE)->second; + const float shape = domParams.find(SHAPE)->second; + const float scale = domParams.find(SCALE)->second; h = static_cast(pRandom->Gamma(shape, scale)); break; } case NEGEXP: { - const float mean = dominanceParameters.find(MEAN)->second; + const float mean = domParams.find(MEAN)->second; h = static_cast(pRandom->NegExp(mean)); break; } case SCALED: { - const float h_d = dominanceParameters.find(MEAN)->second; + const float h_d = domParams.find(MEAN)->second; const float k = -log(2 * h_d) / scaledDomMeanSelCoeff; const float max = exp(-k * selCoef); h = pRandom->FRandom(0, max); @@ -243,10 +360,7 @@ float GeneticFitnessTrait::drawDominance(float selCoef) { // if the mutation distribution enable it, take a negative value // down to -1 representing the effect of beneficial mutations // ---------------------------------------------------------------------------------------- -float GeneticFitnessTrait::drawSelectionCoef() { - - DistributionType mutationDistribution = pSpeciesTrait->getMutationDistribution(); - map mutationParameters = pSpeciesTrait->getMutationParameters(); +float GeneticFitnessTrait::drawSelectionCoef(const DistributionType& mutationDistribution, const map& mutationParameters) { float s = 0.0; // default selection coefficient is 0 diff --git a/GeneticFitnessTrait.h b/GeneticFitnessTrait.h index 001e1c2..db9e7ab 100644 --- a/GeneticFitnessTrait.h +++ b/GeneticFitnessTrait.h @@ -59,10 +59,19 @@ class GeneticFitnessTrait : public QuantitativeTrait { // Initialisation void initialise(); + void setScaledCoeff(const DistributionType& selCoeffDist, const map& selCoeffParams); + // Mutation float scaledDomMeanSelCoeff = 0; // s_d, only for scaled dominance distribution - float drawDominance(float); - float drawSelectionCoef(); + float drawDominance( + float selCoef, + const DistributionType& domDist, + const map& domParams + ); + float drawSelectionCoef( + const DistributionType& mutationDistribution, + const map& mutationParameters + ); // Immutable features, set at initialisation // and passed down to every subsequent trait copy diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 61db3a5..94fdd0f 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -3,16 +3,20 @@ // Species trait constructor SpeciesTrait::SpeciesTrait( - const TraitType& trType, const sex_t& sx, - const set& pos, + const TraitType& trType, + const sex_t& sx, + const set& pos, const ExpressionType& expr, - const DistributionType& initDist, + const DistributionType& initDist, const map initParams, - const DistributionType& dominanceDist, - const map dominanceParams, - bool isInherited, const float& mutRate, - const DistributionType& mutationDist, + const DistributionType& initDomDist, + const map initDomParams, + bool isInherited, + const float& mutRate, + const DistributionType& mutationDist, const map mutationParams, + const DistributionType& dominanceDist, + const map dominanceParams, const int nPloidy, const bool isOutput) : traitType{ trType }, @@ -21,6 +25,8 @@ SpeciesTrait::SpeciesTrait( expressionType{ expr }, initialDistribution{ initDist }, initialParameters{ initParams }, + initialDomDistribution{ initDomDist }, + initialDomParameters{ initDomParams }, dominanceDistribution{ dominanceDist }, dominanceParameters{ dominanceParams }, inherited{ isInherited }, @@ -31,7 +37,7 @@ SpeciesTrait::SpeciesTrait( traitIsOutput{ isOutput } { // Check distribution parameters - // Initial distribution + // Initial allele distribution for (auto [paramType, paramVal] : initParams) { switch (paramType) { @@ -48,6 +54,23 @@ SpeciesTrait::SpeciesTrait( } } + // Initial dominance distribution + for (auto [paramType, paramVal] : initDomParams) { + switch (paramType) + { + case MIN: case MAX: case MEAN: + if (paramVal < 0.0) + throw logic_error("Invalid parameter value: initial dominance parameter " + to_string(paramType) + " must not be negative."); + break; + case SD: case SHAPE: case SCALE: + if (paramVal <= 0.0) + throw logic_error("Invalid parameter value: initial dominance parameter " + to_string(paramType) + " must be strictly positive"); + break; + default: + break; + } + } + // Mutation distribution for (auto [paramType, paramVal] : mutationParams) { switch (paramType) diff --git a/SpeciesTrait.h b/SpeciesTrait.h index 5a323e9..c866dd4 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -22,12 +22,14 @@ class SpeciesTrait { const ExpressionType& expr, const DistributionType& initDist, const map initParams, - const DistributionType& dominanceDist, - const map dominanceParams, + const DistributionType& initDomDist, + const map initDomParams, bool isInherited, const float& mutationRate, const DistributionType& mutationDist, const map mutationParams, + const DistributionType& dominanceDist, + const map dominanceParams, const int ploidy, const bool isOutput ); @@ -44,12 +46,15 @@ class SpeciesTrait { int getPositionsSize() const { return static_cast(genePositions.size()); } bool isInherited() const { return inherited; } + DistributionType getInitialDistribution() const { return initialDistribution; }; + map getInitialParameters() const { return initialParameters; }; + DistributionType getInitDomDistribution() const { return initialDomDistribution; }; + map getInitDomParameters() const { return initialDomParameters; }; DistributionType getMutationDistribution() const { return mutationDistribution; }; map getMutationParameters() const { return mutationParameters; }; DistributionType getDominanceDistribution() const { return dominanceDistribution; }; map getDominanceParameters() const { return dominanceParameters; }; - DistributionType getInitialDistribution() const { return initialDistribution; }; - map getInitialParameters() const { return initialParameters; }; + ExpressionType getExpressionType() const { return expressionType; }; int getNbNeutralAlleles() const { @@ -78,6 +83,8 @@ class SpeciesTrait { ExpressionType expressionType; DistributionType initialDistribution; map initialParameters; + DistributionType initialDomDistribution; + map initialDomParameters; DistributionType dominanceDistribution; map dominanceParameters; bool inherited; From edf9cf81c1850c1305fc979e66b8610a379fe4c3 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 20 Nov 2024 10:42:30 +0000 Subject: [PATCH 291/332] oops bugs in #75 --- GeneticFitnessTrait.cpp | 6 +++--- SpeciesTrait.cpp | 14 ++++++++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index 82cfb17..c20c164 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -56,8 +56,8 @@ GeneticFitnessTrait::GeneticFitnessTrait(SpeciesTrait* P) } } - DistributionType initDomDistribution = pSpeciesTrait->getInitialDistribution(); - map initDomParameters = pSpeciesTrait->getInitialParameters(); + DistributionType initDomDistribution = pSpeciesTrait->getInitDomDistribution(); + map initDomParameters = pSpeciesTrait->getInitDomParameters(); switch (initDomDistribution) { case UNIFORM: { @@ -93,9 +93,9 @@ GeneticFitnessTrait::GeneticFitnessTrait(SpeciesTrait* P) { if (initDomParameters.count(MEAN) != 1) throw logic_error("Error:: genetic load dominance distribution set to scaled, so parameters must contain mean dominance value (e.g. mean= ) \n"); - break; // Set for drawing initial values setScaledCoeff(initialDistribution, initialParameters); + break; } case NONE: // default values, zero-dominance coefficients break; diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 94fdd0f..09afa6f 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -228,6 +228,8 @@ SpeciesTrait* createTestEmigSpTrait(const set& genePositions, const bool& i 0.0, // mutation rate DistributionType::UNIFORM, distParams, + DistributionType::NONE, // no dominance + distParams, isDiploid ? 2 : 1, false ); @@ -245,14 +247,16 @@ SpeciesTrait* createTestGenLoadTrait(const set& genePositions, const bool& sex_t::NA, genePositions, ExpressionType::MULTIPLICATIVE, - DistributionType::UNIFORM, + DistributionType::NONE, distParams, - DistributionType::UNIFORM, + DistributionType::NONE, // initialise dominance to zero distParams, true, // isInherited 0.0, // mutation rate DistributionType::UNIFORM, distParams, + DistributionType::UNIFORM, + distParams, isDiploid ? 2 : 1, false ); @@ -272,13 +276,15 @@ SpeciesTrait* createTestNeutralSpTrait(const float& maxAlleleVal, const set ExpressionType::NOTEXPR, // Sample initial values from uniform(0, max) DistributionType::UNIFORM, distParams, - // No dominance - DistributionType::NONE, map{}, + DistributionType::NONE, // No dominance + map{}, true, // isInherited 0.0, // mutation rate // Mutation sampled from a uniform(0, max) DistributionType::KAM, distParams, + DistributionType::NONE, // No dominance + map{}, isDiploid ? 2 : 1, false ); From e2834e771621f6fc86b3c9ceb22f150ad40e01aa Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 20 Nov 2024 14:31:13 +0000 Subject: [PATCH 292/332] update tests to non-zero initial dominance coeffs --- unit_tests/testIndividual.cpp | 25 +++++++++++++++++++++---- unit_tests/testPopulation.cpp | 2 ++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 36fb700..8dbf8d3 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -539,12 +539,12 @@ void testGenetics() { sex_t::NA, createTestGenePositions(genomeSz), ExpressionType::ADDITIVE, - DistributionType::UNIFORM, - distParams, + DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, not used isInherited, 0.0, // no mutations DistributionType::UNIFORM, distParams, // ignored + DistributionType::NONE, distParams, // no dominance, not used isDiploid ? 2 : 1, false ); @@ -601,10 +601,11 @@ void testGenetics() { createTestGenePositions(genomeSz), ExpressionType::MULTIPLICATIVE, DistributionType::NONE, placeholderParams, // not used for genetic load - DistributionType::NORMAL, dominanceParams, + DistributionType::NONE, dominanceParams, true, 1.0, // every site mutates DistributionType::GAMMA, mutationParams, + DistributionType::NORMAL, dominanceParams, isDiploid ? 2 : 1, false ); @@ -642,10 +643,11 @@ void testGenetics() { createTestGenePositions(genomeSz), ExpressionType::MULTIPLICATIVE, DistributionType::NONE, placeholderParams, // not used for genetic load - DistributionType::NORMAL, placeholderParams, // doesn't matter for this test + DistributionType::NONE, placeholderParams, // doesn't matter for this test true, 1.0, // every site mutates DistributionType::NORMAL, mutationParams, + DistributionType::NORMAL, placeholderParams, // doesn't matter for this test isDiploid ? 2 : 1, false ); @@ -794,6 +796,7 @@ void testIndividual() { true, // isInherited maleMutationRate, // does not mutate DistributionType::UNIFORM, mutationParams, // not used + DistributionType::NONE, initParams, // no dominance, params are ignored isDiploid ? 2 : 1, false ); @@ -810,6 +813,7 @@ void testIndividual() { true, // isInherited femaleMutationRate, // does mutate DistributionType::UNIFORM, mutationParams, // not used + DistributionType::NONE, initParams, isDiploid ? 2 : 1, false ); @@ -874,6 +878,7 @@ void testIndividual() { true, // isInherited 0.0, // no mutation DistributionType::UNIFORM, mutationParams, // not used + DistributionType::NONE, initParams, // no dominance, params are ignored 2, // diploid false ); @@ -939,6 +944,7 @@ void testIndividual() { true, // isInherited 1.0, // will mutate DistributionType::UNIFORM, mutationParams, // lethal mutation + DistributionType::NONE, initParams, 2, // diploid false ); @@ -989,6 +995,7 @@ void testIndividual() { true, // isInherited 0.0, // no mutation DistributionType::UNIFORM, distParams, // lethal mutation + DistributionType::NONE, distParams, 2, // diploid false ); @@ -1069,6 +1076,7 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used + DistributionType::NONE, distParams, // no dominance, params are ignored isDiploid ? 2 : 1, false ); @@ -1082,6 +1090,7 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used + DistributionType::NONE, distParams, isDiploid ? 2 : 1, false ); @@ -1095,6 +1104,7 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used + DistributionType::NONE, distParams, // no dominance, params are ignored isDiploid ? 2 : 1, false ); @@ -1108,6 +1118,7 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used + DistributionType::NONE, distParams, // no dominance, params are ignored isDiploid ? 2 : 1, false ); @@ -1183,6 +1194,7 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used + DistributionType::NONE, distParams, // no dominance, params are ignored isDiploid ? 2 : 1, false ); @@ -1196,6 +1208,7 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used + DistributionType::NONE, distParams, // no dominance, params are ignored isDiploid ? 2 : 1, false ); @@ -1265,6 +1278,7 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used + DistributionType::NONE, distParams, // no dominance, params are ignored isDiploid ? 2 : 1, false ); @@ -1278,6 +1292,7 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used + DistributionType::NONE, distParams, // no dominance, params are ignored isDiploid ? 2 : 1, false ); @@ -1291,6 +1306,7 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used + DistributionType::NONE, distParams, // no dominance, params are ignored isDiploid ? 2 : 1, false ); @@ -1304,6 +1320,7 @@ void testIndividual() { true, // isInherited mutationRate, // does not mutate DistributionType::UNIFORM, distParams, // not used + DistributionType::NONE, distParams, // no dominance, params are ignored isDiploid ? 2 : 1, false ); diff --git a/unit_tests/testPopulation.cpp b/unit_tests/testPopulation.cpp index 63054ad..3cfe9df 100644 --- a/unit_tests/testPopulation.cpp +++ b/unit_tests/testPopulation.cpp @@ -52,6 +52,7 @@ void testPopulation() true, // isInherited mutationRate, // mutation rate DistributionType::UNIFORM, mutParams, + DistributionType::UNIFORM, domParams, isDiploid ? 2 : 1, false ); @@ -120,6 +121,7 @@ void testPopulation() true, // isInherited mutationRate, // mutation rate DistributionType::UNIFORM, mutParams, + DistributionType::NONE, map{}, // no dominance isDiploid ? 2 : 1, false ); From 52becbaf9b91788690bfbd8ea20e887fdb812a68 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 30 Jan 2025 10:57:08 +0000 Subject: [PATCH 293/332] improve readability of readDynLand --- Landscape.cpp | 42 +++++++++++++++++++++--------------------- Landscape.h | 3 ++- Model.cpp | 20 ++++++++++---------- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index 5ec8ded..c87fb47 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -1106,8 +1106,8 @@ void Landscape::addLandChange(landChange c) { int Landscape::numLandChanges(void) { return (int)landchanges.size(); } landChange Landscape::getLandChange(short ix) { - landChange c; c.chgnum = c.chgyear = 0; - c.habfile = c.pchfile = c.costfile = "none"; + landChange c; c.chgNb = c.chgYear = 0; + c.pathHabFile = c.pathPatchFile = c.pathCostFile = "none"; int nchanges = (int)landchanges.size(); if (ix < nchanges) c = landchanges[ix]; return c; @@ -1148,17 +1148,17 @@ int Landscape::readLandChange(int filenum, bool costs) #if !RS_RCPP || R_CMD // open habitat file and optionally also patch and costs files - hfile.open(landchanges[filenum].habfile.c_str()); + hfile.open(landchanges[filenum].pathHabFile.c_str()); if (!hfile.is_open()) return 30; if (patchModel) { - pfile.open(landchanges[filenum].pchfile.c_str()); + pfile.open(landchanges[filenum].pathPatchFile.c_str()); if (!pfile.is_open()) { hfile.close(); hfile.clear(); return 31; } } if (costs) { - cfile.open(landchanges[filenum].costfile.c_str()); + cfile.open(landchanges[filenum].pathCostFile.c_str()); if (!cfile.is_open()) { hfile.close(); hfile.clear(); if (pfile.is_open()) { @@ -1784,7 +1784,7 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string // open habitat file and optionally also patch file #if RS_RCPP - hfile.open(habfile, std::ios::binary); + hfile.open(pathHabFile, std::ios::binary); if (landraster.utf) { // apply BOM-sensitive UTF-16 facet hfile.imbue(std::locale(hfile.getloc(), new std::codecvt_utf16)); @@ -1796,7 +1796,7 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string if (fileNum == 0) { if (patchModel) { #if RS_RCPP - pfile.open(pchfile, std::ios::binary); + pfile.open(pathPatchFile, std::ios::binary); if (patchraster.utf) { // apply BOM-sensitive UTF-16 facet pfile.imbue(std::locale(pfile.getloc(), new std::codecvt_utf16)); @@ -1819,7 +1819,7 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string #if RS_RCPP if (!hfile.good()) { // corrupt file stream - StreamErrorR(habfile); + StreamErrorR(pathHabFile); hfile.close(); hfile.clear(); if (patchModel) { @@ -1853,7 +1853,7 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string #if RS_RCPP if (!pfile.good()) { // corrupt file stream - StreamErrorR(pchfile); + StreamErrorR(pathPatchFile); hfile.close(); hfile.clear(); pfile.close(); @@ -1900,7 +1900,7 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string #if RS_RCPP && !R_CMD Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - StreamErrorR(pchfile); + StreamErrorR(pathPatchFile); hfile.close(); hfile.clear(); pfile.close(); @@ -1914,7 +1914,7 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string #if RS_RCPP && !R_CMD Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - StreamErrorR(habfile); + StreamErrorR(pathHabFile); hfile.close(); hfile.clear(); if (patchModel) { @@ -1980,11 +1980,11 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string } #if RS_RCPP hfile >> hfloat; -if (!hfile.eof()) EOFerrorR(habfile); +if (!hfile.eof()) EOFerrorR(pathHabFile); if (patchModel) { pfile >> pfloat; - if (!pfile.eof()) EOFerrorR(pchfile); + if (!pfile.eof()) EOFerrorR(pathPatchFile); } #endif break; @@ -2015,7 +2015,7 @@ if (patchModel) #if RS_RCPP && !R_CMD Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - StreamErrorR(pchfile); + StreamErrorR(pathPatchFile); hfile.close(); hfile.clear(); pfile.close(); @@ -2096,7 +2096,7 @@ else { // couldn't read from hfile #if RS_RCPP && !R_CMD Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - StreamErrorR(habfile); + StreamErrorR(pathHabFile); hfile.close(); hfile.clear(); if (patchModel) { @@ -2112,11 +2112,11 @@ else { // couldn't read from hfile habIndexed = true; // habitats are already numbered 1...n in correct order #if RS_RCPP hfile >> hfloat; - if (!hfile.eof()) EOFerrorR(habfile); + if (!hfile.eof()) EOFerrorR(pathHabFile); if (patchModel) { pfile >> pfloat; - if (!pfile.eof()) EOFerrorR(pchfile); + if (!pfile.eof()) EOFerrorR(pathPatchFile); } #endif break; @@ -2139,7 +2139,7 @@ else { // couldn't read from hfile #if RS_RCPP && !R_CMD Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - StreamErrorR(habfile); + StreamErrorR(pathHabFile); hfile.close(); hfile.clear(); if (patchModel) { @@ -2164,7 +2164,7 @@ else { // couldn't read from hfile #if RS_RCPP && !R_CMD Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - StreamErrorR(pchfile); + StreamErrorR(pathPatchFile); hfile.close(); hfile.clear(); pfile.close(); @@ -2224,11 +2224,11 @@ else { // couldn't read from hfile } #if RS_RCPP hfile >> hfloat; - if (!hfile.eof()) EOFerrorR(habfile); + if (!hfile.eof()) EOFerrorR(pathHabFile); if (patchModel) { pfile >> pfloat; - if (!pfile.eof()) EOFerrorR(pchfile); + if (!pfile.eof()) EOFerrorR(pathPatchFile); } #endif break; diff --git a/Landscape.h b/Landscape.h index ac7e258..e2f2cf9 100644 --- a/Landscape.h +++ b/Landscape.h @@ -179,7 +179,8 @@ struct patchData { Patch* pPatch; int patchNum, nCells; int x, y; }; struct landChange { - int chgnum, chgyear; string habfile, pchfile, costfile; + int chgNb, chgYear; + string pathHabFile, pathPatchFile, pathCostFile; }; struct patchChange { int chgnum, x, y, oldpatch, newpatch; diff --git a/Model.cpp b/Model.cpp index 970267a..9e48037 100644 --- a/Model.cpp +++ b/Model.cpp @@ -218,7 +218,7 @@ int RunModel(Landscape* pLandscape, int seqsim) pLandscape->createConnectMatrix(); // variables to control dynamic landscape - landChange landChg; landChg.chgnum = 0; landChg.chgyear = 999999; + landChange landChg; landChg.chgNb = 0; landChg.chgYear = 999999; if (!ppLand.generated && ppLand.dynamic) { landChg = pLandscape->getLandChange(0); // get first change year } @@ -315,8 +315,8 @@ int RunModel(Landscape* pLandscape, int seqsim) updateCC = true; } if (ppLand.dynamic) { - if (yr == landChg.chgyear) { // apply landscape change - landIx = landChg.chgnum; + if (yr == landChg.chgYear) { // apply landscape change + landIx = landChg.chgNb; updateland = updateCC = true; if (ppLand.patchModel) { // apply any patch changes Patch* pPatch; @@ -343,7 +343,7 @@ int RunModel(Landscape* pLandscape, int seqsim) ixpchchg--; pLandscape->resetPatches(); // reset patch limits } - if (landChg.costfile != "NULL") { // apply any SMS cost changes + if (landChg.pathCostFile != "NULL") { // apply any SMS cost changes Cell* pCell; costchange = pLandscape->getCostChange(ixcostchg++); while (costchange.chgnum <= landIx && ixcostchg <= ncostchanges) { @@ -360,7 +360,7 @@ int RunModel(Landscape* pLandscape, int seqsim) landChg = pLandscape->getLandChange(landIx); } else { - landChg.chgyear = 9999999; + landChg.chgYear = 9999999; } } } @@ -841,13 +841,13 @@ void OutParameters(Landscape* pLandscape) int nchanges = pLandscape->numLandChanges(); for (int i = 0; i < nchanges; i++) { chg = pLandscape->getLandChange(i); - outPar << "Change no. " << chg.chgnum << " in year " << chg.chgyear << endl; - outPar << "Landscape: " << chg.habfile << endl; + outPar << "Change no. " << chg.chgNb << " in year " << chg.chgYear << endl; + outPar << "Landscape: " << chg.pathHabFile << endl; if (ppLand.patchModel) { - outPar << "Patches : " << chg.pchfile << endl; + outPar << "Patches : " << chg.pathPatchFile << endl; } - if (chg.costfile != "none" && chg.costfile != "NULL") { - outPar << "Costs : " << chg.costfile << endl; + if (chg.pathCostFile != "none" && chg.pathCostFile != "NULL") { + outPar << "Costs : " << chg.pathCostFile << endl; } } } From 187d9bdd0bbd10a3ae1acab32ac6c24c81059ef3 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 4 Feb 2025 16:20:35 +0000 Subject: [PATCH 294/332] drop unused map and views features --- Community.cpp | 8 ++--- Community.h | 4 +-- Landscape.cpp | 8 ++--- Model.cpp | 30 ++++------------ Parameters.cpp | 32 ++--------------- Parameters.h | 95 +++++++++++++++++++++++++------------------------- 6 files changed, 62 insertions(+), 115 deletions(-) diff --git a/Community.cpp b/Community.cpp index 7298f4e..3455a6f 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1072,7 +1072,7 @@ void Community::outOccupancy(void) { } } -void Community::outOccSuit(bool view) { +void Community::outOccSuit() { double sum, ss, mean, sd, se; simParams sim = paramsSim->getSim(); @@ -1107,7 +1107,6 @@ order of y void Community::outTraits(Species* pSpecies, int rep, int yr, int gen) { simParams sim = paramsSim->getSim(); - simView v = paramsSim->getViews(); landParams land = pLandscape->getLandParams(); traitsums* ts = 0; traitsums sctraits; @@ -1132,9 +1131,8 @@ void Community::outTraits(Species* pSpecies, int rep, int yr, int gen) } } } - if (v.viewTraits - || ((sim.outTraitsCells && yr >= sim.outStartTraitCell && yr % sim.outIntTraitCell == 0) || - (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0))) + if ((sim.outTraitsCells && yr >= sim.outStartTraitCell && yr % sim.outIntTraitCell == 0) || + (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0)) { // generate output for each sub-community (patch) in the community int nsubcomms = (int)subComms.size(); diff --git a/Community.h b/Community.h index 2de09d9..c93e4ae 100644 --- a/Community.h +++ b/Community.h @@ -158,9 +158,7 @@ class Community { int // option: -999 to close the file ); void outOccupancy(void); - void outOccSuit( - bool // TRUE if occupancy graph is to be viewed on screen - ); + void outOccSuit(); bool outTraitsHeaders( // Open traits file and write header record Species*, // pointer to Species int // Landscape number (-999 to close the file) diff --git a/Landscape.cpp b/Landscape.cpp index c87fb47..01e51c2 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -2276,9 +2276,6 @@ int Landscape::readCosts(string fname) string header; #endif Cell* pCell; -#if !RS_RCPP - simView v = paramsSim->getViews(); -#endif int maxcost = 0; @@ -2598,14 +2595,12 @@ void Landscape::outVisits(int rep, int landNr) { + "Sim" + to_string(sim.simulation) + "_land" + to_string(landNr) + "_rep" + to_string(rep) #endif - // + "_yr" + to_string(yr) + "_Visits.txt"; } else { name = paramsSim->getDir(3) + "Sim" + to_string(sim.simulation) + "_land" + to_string(landNr) + "_rep" + to_string(rep) - // + "_yr" + to_string(yr) + "_Visits.txt"; } outvisits.open(name.c_str()); @@ -2629,7 +2624,8 @@ void Landscape::outVisits(int rep, int landNr) { outvisits << endl; } - outvisits.close(); outvisits.clear(); + outvisits.close(); + outvisits.clear(); } //--------------------------------------------------------------------------- diff --git a/Model.cpp b/Model.cpp index 9e48037..87bd137 100644 --- a/Model.cpp +++ b/Model.cpp @@ -45,7 +45,6 @@ int RunModel(Landscape* pLandscape, int seqsim) transferRules trfr = pSpecies->getTransferRules(); initParams init = paramsInit->getInit(); simParams sim = paramsSim->getSim(); - simView v = paramsSim->getViews(); if (!ppLand.generated) { if (!ppLand.patchModel) { // cell-based landscape @@ -402,8 +401,7 @@ int RunModel(Landscape* pLandscape, int seqsim) for (int gen = 0; gen < dem.repSeasons; gen++) // generation loop { // Output and pop. visualisation before reproduction - if (v.viewPop || v.viewTraits || sim.outOccup - || sim.outTraitsCells || sim.outTraitsRows || sim.saveMaps) + if (sim.outOccup || sim.outTraitsCells || sim.outTraitsRows) PreReproductionOutput(pLandscape, pComm, rep, yr, gen); // for non-structured population, also produce range and population output now if (!dem.stageStruct && (sim.outRange || sim.outPop)) @@ -523,8 +521,7 @@ int RunModel(Landscape* pLandscape, int seqsim) // Final output // produce final summary output - if (v.viewPop || v.viewTraits || sim.outOccup - || sim.outTraitsCells || sim.outTraitsRows || sim.saveMaps) + if (sim.outOccup || sim.outTraitsCells || sim.outTraitsRows) PreReproductionOutput(pLandscape, pComm, rep, yr, 0); if (sim.outRange || sim.outPop) RangePopOutput(pComm, rep, yr, 0); @@ -620,7 +617,7 @@ int RunModel(Landscape* pLandscape, int seqsim) // Occupancy outputs if (sim.outOccup && sim.reps > 1) { pComm->outOccupancy(); - pComm->outOccSuit(v.viewGraph); + pComm->outOccSuit(); pComm->deleteOccupancy((sim.years / sim.outIntOcc) + 1); pComm->outOccupancyHeaders(-999); } @@ -703,12 +700,10 @@ bool CheckDirectory(const string& pathToProjDir) void PreReproductionOutput(Landscape* pLand, Community* pComm, int rep, int yr, int gen) { simParams sim = paramsSim->getSim(); - simView v = paramsSim->getViews(); // trait outputs and visualisation - if (v.viewTraits - || ((sim.outTraitsCells && yr >= sim.outStartTraitCell && yr % sim.outIntTraitCell == 0) || - (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0))) + if ((sim.outTraitsCells && yr >= sim.outStartTraitCell && yr % sim.outIntTraitCell == 0) + || (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0)) { pComm->outTraits(pSpecies, rep, yr, gen); } @@ -1708,20 +1703,7 @@ void OutParameters(Landscape* pLandscape) outPar << endl; } #endif - outPar << "SAVE MAPS: "; - if (sim.saveMaps) { - outPar << "yes - every " << sim.mapInt << " year"; - if (sim.mapInt > 1) outPar << "s"; - outPar << endl; - } - else outPar << "no" << endl; - outPar << "SAVE TRAITS MAPS: "; - if (sim.saveTraitMaps) { - outPar << "yes - every " << sim.traitInt << " year"; - if (sim.traitInt > 1) outPar << "s"; - outPar << endl; - } - else outPar << "no" << endl; + if (trfr.usesMovtProc && trfr.moveType == 1) { outPar << "SMS HEAT MAPS: "; if (sim.saveVisits) outPar << "yes" << endl; diff --git a/Parameters.cpp b/Parameters.cpp index cc1de60..68d440d 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -220,20 +220,16 @@ paramSim::paramSim(const string& pathToProjDir) : outStartTraitCell = outStartTraitRow = outStartConn = 0; outIntOcc = outIntPop = outIntInd = outputGeneticInterval = 10; outIntTraitCell = outIntTraitRow = outIntConn = 10; - mapInt = traitInt = 10; - slowFactor = 1; + traitInt = 10; batchMode = absorbing = false; outRange = outOccup = outPop = outInds = false; outTraitsCells = outTraitsRows = outConnect = false; outputGenes = outputWeirCockerham = outputWeirHill = false; - saveMaps = false; saveTraitMaps = false; saveVisits = false; #if RS_RCPP outStartPaths = 0; outIntPaths = 0; outPaths = false; ReturnPopRaster = false; CreatePopFile = true; #endif - viewLand = false; viewPatch = false; viewGrad = false; viewCosts = false; - viewPop = false; viewTraits = false; viewPaths = false; viewGraph = false; } paramSim::~paramSim(void) { } @@ -243,7 +239,6 @@ void paramSim::setSim(simParams s) { if (s.simulation >= 0) simulation = s.simulation; if (s.reps >= 1) reps = s.reps; if (s.years >= 1) years = s.years; - if (s.mapInt >= 1) mapInt = s.mapInt; if (s.traitInt >= 1) traitInt = s.traitInt; batchMode = s.batchMode; absorbing = s.absorbing; outRange = s.outRange; outOccup = s.outOccup; @@ -262,7 +257,6 @@ void paramSim::setSim(simParams s) { if (s.outIntTraitCell >= 1) outIntTraitCell = s.outIntTraitCell; if (s.outIntTraitRow >= 1) outIntTraitRow = s.outIntTraitRow; if (s.outIntConn >= 1) outIntConn = s.outIntConn; - saveMaps = s.saveMaps; saveTraitMaps = s.saveTraitMaps; saveVisits = s.saveVisits; #if RS_RCPP outStartPaths = s.outStartPaths; @@ -283,7 +277,7 @@ void paramSim::setGeneticSim(string patchSamplingOption, bool outputGeneticValue this->outputGeneticInterval = outputGeneticInterval; } -simParams paramSim::getSim(void) { +simParams paramSim::getSim() { simParams s; s.batchNum = batchNum; s.simulation = simulation; s.reps = reps; s.years = years; @@ -300,9 +294,7 @@ simParams paramSim::getSim(void) { s.outIntConn = outIntConn; s.batchMode = batchMode; s.absorbing = absorbing; - s.saveMaps = saveMaps; s.saveTraitMaps = saveTraitMaps; - s.saveVisits = saveVisits; - s.mapInt = mapInt; s.traitInt = traitInt; + s.traitInt = traitInt; #if RS_RCPP s.outStartPaths = outStartPaths; s.outIntPaths = outIntPaths; @@ -322,24 +314,6 @@ simParams paramSim::getSim(void) { int paramSim::getSimNum(void) { return simulation; } -void paramSim::setViews(simView v) { - viewLand = v.viewLand; viewPatch = v.viewPatch; - viewGrad = v.viewGrad; viewCosts = v.viewCosts; - viewPop = v.viewPop; viewTraits = v.viewTraits; - viewPaths = v.viewPaths; viewGraph = v.viewGraph; - if (v.slowFactor > 0) slowFactor = v.slowFactor; -} - -simView paramSim::getViews(void) { - simView v; - v.viewLand = viewLand; v.viewPatch = viewPatch; - v.viewGrad = viewGrad; v.viewCosts = viewCosts; - v.viewPop = viewPop; v.viewTraits = viewTraits; - v.viewPaths = viewPaths; v.viewGraph = viewGraph; - v.slowFactor = slowFactor; - return v; -} - // return directory name depending on option specified string paramSim::getDir(int option) { string s; diff --git a/Parameters.h b/Parameters.h index a30d3a2..d6ad69d 100644 --- a/Parameters.h +++ b/Parameters.h @@ -301,18 +301,32 @@ class paramInit { struct simParams { int batchNum; - int simulation; int reps; int years; - int outStartPop; int outStartInd; - int outStartTraitCell; int outStartTraitRow; int outStartConn; - int outIntRange; int outIntOcc; int outIntPop; int outIntInd; - int outIntTraitCell; int outIntTraitRow; int outIntConn; - int mapInt; int traitInt; - bool batchMode; bool absorbing; - bool outRange; bool outOccup; bool outPop; bool outInds; - bool outTraitsCells; bool outTraitsRows; bool outConnect; - bool saveMaps; - bool drawLoaded; bool saveTraitMaps; + int simulation; + int reps; + int years; + int outStartPop; + int outStartInd; + int outIntInd; + int outStartTraitCell; + int outStartTraitRow; + int outStartConn; + int outIntRange; + int outIntOcc; + int outIntPop; bool saveVisits; + int outIntTraitCell; + int outIntTraitRow; + int outIntConn; + int traitInt; + bool batchMode; + bool absorbing; + bool outRange; + bool outOccup; + bool outPop; + bool outInds; + bool outTraitsCells; + bool outTraitsRows; + bool outConnect; #if RS_RCPP int outStartPaths; int outIntPaths; bool outPaths; bool ReturnPopRaster; bool CreatePopFile; @@ -339,8 +353,6 @@ class paramSim { void setGeneticSim(string patchSamplingOption, bool outputGeneticValues, bool outputWeirCockerham, bool outputWeirHill, int outputStartGenetics, int outputGeneticInterval); simParams getSim(void); int getSimNum(void); - void setViews(simView); - simView getViews(void); string getDir(int); void setBatchNum(const int& batchNb) { batchNum = batchNb; @@ -352,35 +364,32 @@ class paramSim { #endif private: - int batchNum; // batch number - int simulation; // simulation no. - int reps; // no. of replicates - int years; // no. of years - int outStartPop; // output start year for population file - int outStartInd; // output start year for individuals file - int outStartTraitCell; // output start year for traits by cell file + int batchNum; // batch number + int simulation; // simulation no. + int reps; // no. of replicates + int years; // no. of years + int outStartPop; // output start year for population file + int outStartInd; // output start year for individuals file + int outStartTraitCell; // output start year for traits by cell file int outStartTraitRow; // output start year for traits by row file - int outStartConn; // output start year for connectivity matrix - int outIntRange; // output interval for range file - int outIntOcc; // output interval for occupancy file - int outIntPop; // output interval for population file - int outIntInd; // output interval for individuals file + int outStartConn; // output start year for connectivity matrix + int outIntRange; // output interval for range file + int outIntOcc; // output interval for occupancy file + int outIntPop; // output interval for population file + int outIntInd; // output interval for individuals file int outIntTraitCell; // output interval for traits by cell file int outIntTraitRow; // output interval for traits by row file - int outIntConn; // output interval for connectivity matrix - int mapInt; // output interval for maps - int traitInt; // output interval for evolving traits maps - int slowFactor; // to reduce speed of movement paths on screen - bool batchMode; // - bool absorbing; // landscape boundary and no-data regions are absorbing boundaries - bool outRange; // produce output range file? - bool outOccup; // produce output occupancy file? - bool outPop; // produce output population file? - bool outInds; // produce output individuals file? + int outIntConn; // output interval for connectivity matrix + int traitInt; // output interval for evolving traits maps + bool batchMode; + bool absorbing; // landscape boundary and no-data regions are absorbing boundaries + bool outRange; // produce output range file? + bool outOccup; // produce output occupancy file? + bool outPop; // produce output population file? + bool outInds; // produce output individuals file? bool outTraitsCells; // produce output summary traits by cell file? bool outTraitsRows; // produce output summary traits by row (y) file? - bool outConnect; // produce output connectivity file? - bool saveMaps; // save landscape/population maps? + bool outConnect; // produce output connectivity file? bool saveVisits; // save dispersal visits heat maps? #if RS_RCPP int outStartPaths; @@ -389,17 +398,7 @@ class paramSim { bool ReturnPopRaster; bool CreatePopFile; #endif - bool saveTraitMaps; // save summary traits maps? - bool viewLand; // view landscape map on screen? - bool viewPatch; // view map of landscape patches on screen? - bool viewGrad; // view gradient map on screen? - bool viewCosts; // view costs map on screen? - bool viewPop; // view population density on landscape map on screen? - bool viewTraits; // view summary traits map(s) on screen? - bool viewPaths; // view individual movement paths on screen? - bool viewGraph; // view population/occupancy graph on screen? - string dir; // full name of working directory - + string dir; // full name of working directory bool fixReplicateSeed; string patchSamplingOption; bool outputGenes; From 3c94049eb346dc8a0006ec15a998915243d78bfb Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Wed, 12 Feb 2025 09:05:24 +0100 Subject: [PATCH 295/332] integrated spatial_demography branch - added threadsafe macro: landscape input as R objects/matrices - added spatial_demography macro: spatially varying demography only applicable with matrix input - compiled with R package, still need to be tested --- Cell.cpp | 32 ++- Cell.h | 15 +- Landscape.cpp | 563 ++++++++++++++++++++++++++++++++++++++++++++++- Landscape.h | 64 +++++- Management.cpp | 2 +- Model.cpp | 55 ++++- Model.h | 8 +- Parameters.h | 5 +- Patch.cpp | 49 +++++ Patch.h | 6 + Population.cpp | 55 +++-- Population.h | 10 +- Species.cpp | 157 ++++++++----- Species.h | 43 ++++ SubCommunity.cpp | 16 +- 15 files changed, 982 insertions(+), 98 deletions(-) diff --git a/Cell.cpp b/Cell.cpp index c6088cf..915445e 100644 --- a/Cell.cpp +++ b/Cell.cpp @@ -59,6 +59,11 @@ Cell::~Cell() { if (smsData->effcosts != 0) delete smsData->effcosts; delete smsData; } +demoScalings.clear(); + +#if RSDEBUG +//DEBUGLOG << "Cell::~Cell(): deleted" << endl; +#endif } void Cell::setHabIndex(short hx) { @@ -177,13 +182,30 @@ void Cell::resetVisits(void) { visits = 0; } void Cell::incrVisits(void) { visits++; } unsigned long int Cell::getVisits(void) { return visits; } + +void Cell::addchgDemoScaling(std::vector ds) { + std::for_each(ds.begin(), ds.end(), [](float& perc){ if(perc < 0.0 || perc > 100.0) perc=100; }); + demoScalings.push_back(ds); + return; +} + +std::vector Cell::getDemoScaling(short chgyear) { + if (chgyear < 0 || chgyear >= (int)demoScalings.size()) { + std::vector ret(1, -1); + return ret; + } + else return demoScalings[chgyear]; +} + + + //--------------------------------------------------------------------------- // Initial species distribution cell functions DistCell::DistCell(int xx,int yy) { - x = xx; - y = yy; + x = xx; + y = yy; initialise = false; } @@ -203,9 +225,9 @@ bool DistCell::toInitialise(locn loc) { bool DistCell::selected(void) { return initialise; } locn DistCell::getLocn(void) { - locn loc; - loc.x = x; - loc.y = y; + locn loc; + loc.x = x; + loc.y = y; return loc; } diff --git a/Cell.h b/Cell.h index 0d9757e..a37ddc8 100644 --- a/Cell.h +++ b/Cell.h @@ -31,9 +31,9 @@ DistCell - Initial species distribution cell For full details of RangeShifter, please see: - Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. + Bocedi G., Palmer S.C.F., Pe?er G., Heikkinen R.K., Matsinos Y.G., Watts K. and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial - eco-evolutionary dynamics and species’ responses to environmental changes. + eco-evolutionary dynamics and species? responses to environmental changes. Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 Authors: Greta Bocedi & Steve Palmer, University of Aberdeen @@ -45,6 +45,9 @@ #ifndef CellH #define CellH + +#include + #include using namespace std; @@ -121,6 +124,11 @@ class Cell { void incrVisits(void); unsigned long int getVisits(void); + void addchgDemoScaling(std::vector); + void setDemoScaling(std::vector, short); + std::vector getDemoScaling(short); + + private: int x, y; // cell co-ordinates intptr pPatch; // pointer (cast as integer) to the Patch to which cell belongs @@ -137,6 +145,9 @@ class Cell { // NB initially, habitat codes are loaded, then converted to index nos. // once landscape is fully loaded vector habitats; // habitat proportions (rasterType=1) or quality (rasterType=2) + + std::vector> demoScalings; // demographic scaling layers (only if rasterType==2) + }; //--------------------------------------------------------------------------- diff --git a/Landscape.cpp b/Landscape.cpp index 8fa39f8..5a9d4c0 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -244,7 +244,48 @@ if (!dfile.eof()) EOFerrorR(distfile); return 0; } +// Read species initial distribution file for threadsafe option +#if RS_RCPP +int InitDist::readDistribution(Rcpp::NumericMatrix distfile, landOrigin habfile_origin, int spResol) { + + int d=0; + double dfloat=0; + int ncols,nrows; + + ncols = distfile.ncol(); + nrows = distfile.nrow(); + + minEast = habfile_origin.minEast; + minNorth = habfile_origin.minNorth; + resol = spResol; + maxX = ncols-1; + maxY = nrows-1; + + for (int y = nrows-1; y >= 0; y--) { + for (int x = 0; x < ncols; x++) { + + dfloat = distfile(nrows-1-y,x); + + if ( !R_IsNA(dfloat) ){ // check for NA + d = (int)dfloat; + if ( d == 0 || d == 1) { // only valid values + if (d == 1) { // species present + cells.push_back(new DistCell(x,y)); + } + } + else { // error in file +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found invalid value in species distribution raster." << std::endl; +#endif + return 22; + } + } + } + } + return 0; +} +#endif //--------------------------------------------------------------------------- // Landscape functions @@ -252,6 +293,7 @@ if (!dfile.eof()) EOFerrorR(distfile); Landscape::Landscape(void) { patchModel = false; spDist = false; generated = false; fractal = false; continuous = false; dynamic = false; habIndexed = false; + spatialdemog = false; resol = spResol = 1; landNum = 0; rasterType = 0; nHab = nHabMax = 0; @@ -339,6 +381,7 @@ void Landscape::setLandParams(landParams ppp, bool batchMode) spDist = ppp.spDist; dynamic = ppp.dynamic; landNum = ppp.landNum; + spatialdemog = ppp.spatialdemog; if (ppp.resol > 0) resol = ppp.resol; if (ppp.spResol > 0 && ppp.spResol % ppp.resol == 0) spResol = ppp.spResol; if ((ppp.rasterType >= 0 && ppp.rasterType <= 2) || ppp.rasterType == 9) @@ -374,6 +417,7 @@ landParams Landscape::getLandParams(void) landParams ppp; ppp.generated = generated; ppp.patchModel = patchModel; ppp.spDist = spDist; ppp.dynamic = dynamic; + ppp.spatialdemog = spatialdemog; ppp.landNum = landNum; ppp.resol = resol; ppp.spResol = spResol; ppp.rasterType = rasterType; @@ -914,6 +958,23 @@ void Landscape::updateCarryingCapacity(Species* pSpecies, int yr, short landIx) } +void Landscape::updateDemoScalings(short landIx) { + + patchLimits landlimits; + landlimits.xMin = minX; landlimits.xMax = maxX; + landlimits.yMin = minY; landlimits.yMax = maxY; + + if(spatialdemog && rasterType == 2) {// demographic scaling only implemented for habitat quality maps + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) { + if (patches[i]->getPatchNum() != 0) { // not matrix patch + // calculate local scaling for each patch from its constituent cells + patches[i]->setPatchDemoScaling(landIx, landlimits); + } + } + } +} + Cell* Landscape::findCell(int x, int y) { if (x >= 0 && x < dimX && y >= 0 && y < dimY) return cells[y][x]; else return 0; @@ -1126,8 +1187,191 @@ void Landscape::deleteLandChanges(void) { while (landchanges.size() > 0) landchanges.pop_back(); landchanges.clear(); } +#if RS_RCPP +int Landscape::readLandChange(int filenum, Rcpp::NumericMatrix habfile, Rcpp::NumericMatrix pchfile, Rcpp::NumericMatrix costfile, Rcpp::NumericVector scalinglayers){ -#if RS_RCPP && !R_CMD + if (filenum < 0) return 19; + + int h = 0, p = 0, c = 0, pchseq = 0; + double hfloat = 0,pfloat = 0,cfloat = 0; + bool costs = false; + if(costfile.nrow()>0 && costfile.ncol()>0) costs = true; + + arma::vec cellDemoScalings; // vector to store local demog scalings + Rcpp::IntegerVector DSdim; + int nrDemogScaleLayers = 0; + if(scalinglayers.attr("dim")==R_NilValue) DSdim = Rcpp::IntegerVector::create(1,1,1); + else{ + DSdim = scalinglayers.attr("dim"); + if(DSdim.size()>2) nrDemogScaleLayers = DSdim[2]; //nr of slices on cube + else nrDemogScaleLayers = 1; + } + arma::cube scalingCube(scalinglayers.begin(),DSdim[0],DSdim[1],nrDemogScaleLayers,false); // turn scaling layers into a cube + + simParams sim = paramsSim->getSim(); + + if (patchModel) pchseq = patchCount(); + + switch (rasterType) { + + case 0: // raster with habitat codes - 100% habitat each cell + + for (int y = dimY-1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + + // get numerics from each raster for this cell + hfloat = habfile(dimY-1-y,x); + if (patchModel) pfloat = pchfile(dimY-1-y,x); + if (costs) cfloat = costfile(dimY-1-y,x); + + if (cells[y][x] != 0) { // not a no data cell (in initial landscape) + if ( R_IsNA(hfloat) ){ // invalid no data cell in change map + return 36; + } + else { + h = (int)hfloat; + if (h < 0 || (sim.batchMode && (h < 1 || h > nHabMax))) { // invalid habitat code + return 33; + } + else { + addHabCode(h); + cells[y][x]->setHabIndex(h); + } + } + if (patchModel) { + if ( R_IsNA(pfloat) ){ + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + #endif + return 34; + } + else { + p = (int)pfloat; + if (p < 0 ) { // invalid patch code + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; + #endif + return 34; + } + else { + patchChgMatrix[y][x][2] = p; + if (p > 0 && !existsPatch(p)) { + addPatchNum(p); + newPatch(pchseq++,p); + } + } + } + } + if (costs) { + if ( R_IsNA(cfloat) ){ // invalid cost + return 38; + } + else{ + c = (int)cfloat; + if (c < 1) { // invalid cost + return 38; + } + else { + costsChgMatrix[y][x][2] = c; + } + } + } + } + } + } + break; + + case 2: // habitat quality + + for (int y = dimY-1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + + // get numerics from each raster for this cell + hfloat = habfile(dimY-1-y,x); + if (patchModel) pfloat = pchfile(dimY-1-y,x); + if (costs) cfloat = costfile(dimY-1-y,x); + + if (cells[y][x] != 0) { // not a no data cell (in initial landscape) + if ( R_IsNA(hfloat) ){ // invalid no data cell in change map + return 36; + } + else { + if (hfloat < 0.0 || hfloat > 100.0) { // invalid quality score + return 37; + } + else { + cells[y][x]->setHabitat((float)hfloat); + } + } + if (patchModel) { + if ( R_IsNA(pfloat) ){ + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + #endif + return 34; + } + else { + p = (int)pfloat; + if (p < 0 ) { // invalid patch code + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; + #endif + return 34; + } + else { + patchChgMatrix[y][x][2] = p; + if (p > 0 && !existsPatch(p)) { + addPatchNum(p); + newPatch(pchseq++,p); + } + } + } + } + if (costs) { + if ( R_IsNA(cfloat) ){ // invalid cost + return 38; + } + else{ + c = (int)cfloat; + if (c < 1) { // invalid cost + return 38; + } + else { + costsChgMatrix[y][x][2] = c; + } + } + } + //SPATIALDEMOG + // read demographic scalings + if(nrDemogScaleLayers>0){ + // get tube at (y/x) + cellDemoScalings = scalingCube(arma::span(dimY-1-y), arma::span(x), arma::span::all); + if(cellDemoScalings.n_elem==(unsigned)nDSlayer){ + // set vector percentage values in cell + cells[y][x]->addchgDemoScaling(arma::conv_to< std::vector >::from(cellDemoScalings)); + } + else{// invalid patch code + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Wrong number of demographic scaling layers in cell " << x << " ," << y << " at dyn land change nr " << filenum << std::endl; + #endif + return 39; + } + }// SPATIALDEMOG End + + } + } + } + break; + + default: + break; + } + + return 0; +} +#endif + +#if RS_RCPP && !R_CMD // normal file input int Landscape::readLandChange(int filenum, bool costs, wifstream& hfile, wifstream& pfile, wifstream& cfile, int habnodata, int pchnodata, int costnodata) #else int Landscape::readLandChange(int filenum, bool costs) @@ -1659,7 +1903,22 @@ void Landscape::deleteCostsChgMatrix(void) { // Species distribution functions -int Landscape::newDistribution(Species* pSpecies, string distname) { +//If file input as R objects +int Landscape::newDistribution(Species *pSpecies, Rcpp::NumericMatrix distname, int spResol) { + int readcode; + int ndistns = (int)distns.size(); + distns.push_back(new InitDist(pSpecies)); + landOrigin habfile_origin = this->getOrigin(); + readcode = distns[ndistns]->readDistribution(distname,habfile_origin,spResol); + if (readcode != 0) { // error encountered + // delete the distribution created above + delete distns[ndistns]; + distns.pop_back(); + } + return readcode; +} +// Standard file input +int Landscape::newDistribution(Species *pSpecies, string distname) { int readcode; int ndistns = (int)distns.size(); distns.push_back(new InitDist(pSpecies)); @@ -1672,6 +1931,7 @@ int Landscape::newDistribution(Species* pSpecies, string distname) { return readcode; } + void Landscape::setDistribution(Species* pSpecies, int nInit) { // WILL NEED TO SELECT DISTRIBUTION FOR CORRECT SPECIES ... // ... CURRENTLY IT IS THE ONLY ONE @@ -1763,6 +2023,305 @@ void Landscape::clearInitCells(void) { // Read landscape file(s) // Returns error code or zero if read correctly +// for new landscape input using R objects AND spatial demography: +// RS_THREADSAFE and SPATIALDEMOG +int Landscape::readLandscape(int fileNum, Rcpp::NumericMatrix habfile, Rcpp::NumericMatrix pchfile, Rcpp::NumericMatrix costfile, Rcpp::NumericVector scalinglayers) { + + if (fileNum < 0) return 19; + + int h,seq,p,ncols,nrows,hc,maxcost = 0; + double hfloat,pfloat,cfloat; + Patch *pPatch; + Cell *pCell; + simParams sim = paramsSim->getSim(); + initParams init = paramsInit->getInit(); + + // initialise landscape size + ncols = habfile.ncol(); + nrows = habfile.nrow(); + dimX = ncols; dimY = nrows; + minX = maxY = 0; + maxX = dimX-1; maxY = dimY-1; + if (fileNum == 0) { + // set initialisation limits to landscape limits + init.minSeedX = init.minSeedY = 0; + init.maxSeedX = maxX; init.maxSeedY = maxY; + paramsInit->setInit(init); + setCellArray(); + } + + seq = 0; // initial sequential patch landscape + p = 0; // initial patch number for cell-based landscape + // create patch 0 - the matrix patch (even if there is no matrix) + if (fileNum == 0) newPatch(seq++,p++); + + switch (rasterType) { + + case 0: // raster with habitat codes - 100% habitat each cell + if (fileNum > 0) return 19; // error condition - should not occur + + for (int y = dimY-1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + + // read value from raster cell + hfloat = habfile(dimY-1-y,x); + // check for NA + if ( R_IsNA(hfloat) ) + addNewCellToLand(x,y,-1); // add cell only to landscape + else { + h = (int)hfloat; + // THERE IS AN ANOMALY HERE - CURRENTLY HABITAT 0 IS OK FOR GUI VERSION BUT + // NOT ALLOWED FOR BATCH VERSION (HABITATS MUST BE 1...n) + // SHOULD WE MAKE THE TWO VERSIONS AGREE? ... + if (h < 0 || (sim.batchMode && (h < 1 || h > nHabMax))) { + // invalid habitat code + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found invalid habitat code." << std::endl; + #endif + return 13; + } + else { + addHabCode(h); + if (patchModel) { + pfloat = pchfile(dimY-1-y,x); + if ( R_IsNA(pfloat) ) { // invalid patch code + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + #endif + return 14; + } + p = (int)pfloat; + if (p < 0 ) { // invalid patch code + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; + #endif + return 14; + } + if (p == 0) { // cell is in the matrix + addNewCellToPatch(0,x,y,h); + } + else { + if (existsPatch(p)) { + pPatch = findPatch(p); + addNewCellToPatch(pPatch,x,y,h); + // addNewCellToPatch(findPatch(p),x,y,h); + } + else { + pPatch = newPatch(seq++,p); + addNewCellToPatch(pPatch,x,y,h); + } + } + } + else { // cell-based model + // add cell to landscape (patches created later) + addNewCellToLand(x,y,h); + } + } + } + } + } + break; + + case 1: // multiple % cover + + for (int y = dimY-1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + + hfloat = habfile(dimY-1-y,x); + if (fileNum == 0) { // first habitat cover layer + if ( R_IsNA(hfloat) ) { // check for NA + addNewCellToLand(x,y,-1); // add cell only to landscape + } + else { + if (hfloat < 0.0 || hfloat > 100.0) { // invalid cover score + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found invalid habitat cover score." << std::endl; + #endif + return 17; + } + else { + if (patchModel) { + pfloat = pchfile(dimY-1-y,x); + if ( R_IsNA(pfloat) ) { // invalid patch code + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + #endif + return 14; + } + p = (int)pfloat; + if (p < 0 ) { // invalid patch code + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; + #endif + return 14; + } + if (p == 0) { // cell is in the matrix + addNewCellToPatch(0,x,y,(float)hfloat); + } + else { + if (existsPatch(p)) { + pPatch = findPatch(p); + addNewCellToPatch(pPatch,x,y,(float)hfloat); + // addNewCellToPatch(findPatch(p),x,y,(float)hfloat); + } + else { + pPatch = newPatch(seq++,p); + addNewCellToPatch(pPatch,x,y,(float)hfloat); + } + } + } + else { // cell-based model + // add cell to landscape (patches created later) + addNewCellToLand(x,y,(float)hfloat); + } + } + } + } + else { // additional habitat cover layers + if ( !R_IsNA(hfloat) ) { + if (hfloat < 0.0 || hfloat > 100.0) { // invalid cover score + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found invalid habitat cover score." << std::endl; + #endif + return 17; + } + else { + cells[dimY-1-y][x]->setHabitat((float)hfloat); + } + } // end of h != habnodata + } + } + } + habIndexed = true; // habitats are already numbered 1...n in correct order + + break; + + case 2: // habitat quality + if (fileNum > 0) return 19; // error condition - should not occur + + for (int y = dimY-1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + + hfloat = habfile(dimY-1-y,x); + if ( R_IsNA(hfloat) ) { // check for NA + addNewCellToLand(x,y,-1); // add cell only to landscape + } + else { + if (hfloat < 0.0 || hfloat > 100.0) { // invalid quality score + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found invalid habitat quality score." << std::endl; + #endif + return 17; + } + else { + if (patchModel) { + pfloat = pchfile(dimY-1-y,x); + if ( R_IsNA(pfloat) ) { // invalid patch code + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + #endif + return 14; + } + p = (int)pfloat; + if (p < 0 ) { // invalid patch code + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; + #endif + return 14; + } + if (p == 0) { // cell is in the matrix + addNewCellToPatch(0,x,y,(float)hfloat); + } + else { + if (existsPatch(p)) { + pPatch = findPatch(p); + addNewCellToPatch(pPatch,x,y,(float)hfloat); + // addNewCellToPatch(findPatch(p),x,y,(float)hfloat); + } + else { + addPatchNum(p); + pPatch = newPatch(seq++,p); + addNewCellToPatch(pPatch,x,y,(float)hfloat); + } + } + } + else { // cell-based model + // add cell to landscape (patches created later) + addNewCellToLand(x,y,(float)hfloat); + } + } + } + } + } + break; + + default: + break; + } // end switch(rasterType) + +//#if SPATIALDEMOG + int SMScosts = costfile.nrow()*costfile.ncol(); + + arma::vec cellDemoScalings; // vector to store local demog scalings + Rcpp::IntegerVector DSdim; + int nrDemogScaleLayers = 0; + if(scalinglayers.attr("dim")==R_NilValue) DSdim = Rcpp::IntegerVector::create(1,1,1); + else{ + DSdim = scalinglayers.attr("dim"); + if(DSdim.size()>2) nrDemogScaleLayers = DSdim[2]; //nr of slices on cube + else nrDemogScaleLayers = 1; + } + arma::cube scalingCube(scalinglayers.begin(),DSdim[0],DSdim[1],nrDemogScaleLayers,false); // turn scaling layers into a cube, what happens if it is not a spatial demog? + + if(SMScosts || nrDemogScaleLayers){ // are there SMS costs or demographic scaling layers to read? + + for (int y = dimY-1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + + // find the cell + pCell = findCell(x,y); + if (pCell != 0) { // not no-data cell + + // read cost raster + if(SMScosts) { + cfloat = costfile(dimY-1-y,x); + if ( !R_IsNA(cfloat) ) { + hc = (int)cfloat; + if ( hc < 1 ) { + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Cost map may only contain values of 1 or higher, but found " << hc << "." << endl; + #endif + return 54; + } + // set cost value + pCell->setCost(hc); + if (hc > maxcost) maxcost = hc; + } + } + + // read demographic scalings + if(nrDemogScaleLayers){ + // get tube at (y/x) + cellDemoScalings = scalingCube(arma::span(dimY-1-y), arma::span(x), arma::span::all); + if(cellDemoScalings.n_elem==(unsigned)nDSlayer){ + // set vector percentage values in cell + pCell->addchgDemoScaling(arma::conv_to< std::vector >::from(cellDemoScalings)); + } + else{// invalid patch code + #if RS_RCPP && !R_CMD + Rcpp::Rcout << "Wrong number of demographic scaling layers in cell " << x << " ," << y << " of first layer array." << std::endl; + #endif + return 64; + } + } + } + } + } + } + return 0; +} + + int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string costfile) { // fileNum == 0 for (first) habitat file and optional patch file diff --git a/Landscape.h b/Landscape.h index a5f6313..b8f93ae 100644 --- a/Landscape.h +++ b/Landscape.h @@ -89,8 +89,15 @@ using namespace std; #endif #include #endif +#include //--------------------------------------------------------------------------- +// not sure whether it needs to be added here for the readDistribution() function to work + +struct landOrigin { + double minEast; double minNorth; +}; + // Initial species distribution @@ -98,11 +105,19 @@ class InitDist{ public: InitDist(Species*); ~InitDist(); +#if RS_RCPP int readDistribution( + Rcpp::NumericMatrix, + landOrigin, + int string // name of species distribution file ); +#endif + int readDistribution( + string // name of species distribution file + ); void setDistribution( - int // no. of distribution cells to be initialised (0 for all cells) + int // no. of distribution cells to be initlandOriginialised (0 for all cells) ); void setDistCell( // Set a specified cell (by position in cells vector) int, // index no. of DistCell in cells vector @@ -145,6 +160,7 @@ class InitDist{ struct landParams { bool patchModel; bool spDist; bool generated; bool dynamic; + bool spatialdemog; int landNum; int resol; int spResol; int nHab; int nHabMax; int dimX,dimY,minX,minY,maxX,maxY; short rasterType; @@ -159,9 +175,11 @@ struct genLandParams { struct landPix { int pix; float gpix; }; +/* struct landOrigin { double minEast; double minNorth; }; + */ struct rasterHdr { bool ok; int errors,ncols,nrows,cellsize; @@ -332,7 +350,19 @@ class Landscape{ short // change number ); void deleteLandChanges(void); +//#if RS_THREADSAFE #if RS_RCPP && !R_CMD + int readLandChange( + int, // change number + Rcpp::NumericMatrix,// habitat raster + Rcpp::NumericMatrix,// patch raster + Rcpp::NumericMatrix // cost raster +//#if SPATIALDEMOG + ,Rcpp::NumericVector// array of demographic scaling layers +//#endif + ); +//#else +// #if RS_RCPP && !R_CMD int readLandChange( int, // change file number bool, // change SMS costs? @@ -342,8 +372,10 @@ class Landscape{ int, // habnodata int, // pchnodata int // costnodata +// TODO: add spatial demography with normal file input ); #else + // TODO: add spatial demography for batch version int readLandChange( int, // change file number bool // change SMS costs? @@ -363,6 +395,9 @@ class Landscape{ costChange getCostChange( int // cost change number ); +//#if SPATIALDEMOG + void updateDemoScalings(short); +//#endif // SPATIALDEMOG // functions to handle species distributions @@ -370,6 +405,19 @@ class Landscape{ Species*, // pointer to Species string // name of initial distribution file ); + + // function for new file input +#if RS_RCPP + int newDistribution( + Species*, // pointer to Species + //#if RS_THREADSAFE + Rcpp::NumericMatrix, + int + //#else + string // name of initial distribution file + ); +#endif + void setDistribution( Species*, // pointer to Species int // no. of distribution squares to initialise @@ -445,6 +493,15 @@ class Landscape{ // functions to handle input and output +#if RS_RCPP + int readLandscape( + int, // no. of seasonss + Rcpp::NumericMatrix,// habitat raster + Rcpp::NumericMatrix,// patch raster + Rcpp::NumericMatrix // cost raster + ,Rcpp::NumericVector // array of demographic scaling layers + ); +#endif //for RS_THREADSAFE int readLandscape( int, // fileNum == 0 for (first) habitat file and optional patch file // fileNum > 0 for subsequent habitat files under the %cover option @@ -467,6 +524,9 @@ class Landscape{ bool continuous; // bool dynamic; // landscape changes during simulation bool habIndexed; // habitat codes have been converted to index numbers +//#if SPATIALDEMOG + bool spatialdemog; // are there spatially varying demographic rates? +//#endif // SPATIALDEMOG short rasterType; // 0 = habitat codes 1 = % cover 2 = quality 9 = artificial landscape int landNum; // landscape number int resol; // cell size (m) @@ -514,7 +574,7 @@ class Landscape{ int **connectMatrix; // global environmental stochasticity (epsilon) - float* epsGlobal; // pointer to time-series + float* epsGlobal; // pointer to time-series // patch and costs change matrices (temporary - used when reading dynamic landscape) // indexed by [descending y][x][period] diff --git a/Management.cpp b/Management.cpp index 821b493..bb87620 100644 --- a/Management.cpp +++ b/Management.cpp @@ -226,7 +226,7 @@ void Management::translocate(int yr int nbSampledInds = 0; // We made already sure by now that in s_pPop at least some individuals exist nbSampledInds = s_pPop->sampleIndividuals(nb, min_age, max_age, stage, sex); // checking values was done when reading in the parameters - popStats s_stats = s_pPop->getStats(); + popStats s_stats = s_pPop->getStats(s_patch->getDemoScaling()); Individual* catched_individual; int translocated = 0; // loop over all indsividuals, extract sampled individuals, try to catch individual + translocate them to new patch diff --git a/Model.cpp b/Model.cpp index 9038dbe..7ce171b 100644 --- a/Model.cpp +++ b/Model.cpp @@ -29,7 +29,7 @@ using namespace std::chrono; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #if RS_RCPP && !R_CMD -Rcpp::List RunModel(Landscape* pLandscape, int seqsim) +Rcpp::List RunModel(Landscape* pLandscape, int seqsim, Rcpp::S4 ParMaster) //Rcpp::S4 ParMaster new for all variants #else int RunModel(Landscape* pLandscape, int seqsim) #endif @@ -61,6 +61,12 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm = new Community(pLandscape); // set up community // set up a sub-community associated with each patch (incl. the matrix) pLandscape->updateCarryingCapacity(pSpecies, 0, 0); + + //if SPATIALDEMOG + if (ppLand.rasterType == 2 && ppLand.spatialdemog) + pLandscape->updateDemoScalings(0); // TODO -> is this needed independent of whether it is on or off? + // endif SPATIALDEMOG + patchData ppp; int npatches = pLandscape->patchCount(); for (int i = 0; i < npatches; i++) { @@ -146,6 +152,20 @@ int RunModel(Landscape* pLandscape, int seqsim) } filesOK = true; +#if RS_RCPP + if(init.seedType==2 && init.indsFile=="NULL"){ // initialisation from InitInds list of dataframes + if(rep > 0){ + int error_init = 0; + Rcpp::S4 InitParamsR("InitialisationParams"); + InitParamsR = Rcpp::as(ParMaster.slot("init")); + Rcpp::List InitIndsList = Rcpp::as(InitParamsR.slot("InitIndsList")); + error_init = ReadInitIndsFileR(0, pLandscape, Rcpp::as(InitIndsList[rep])); + if(error_init>0) { + filesOK = false; + } + } + } +#endif if (rep == 0) { // open output files if (sim.outRange) { // open Range file @@ -157,7 +177,11 @@ int RunModel(Landscape* pLandscape, int seqsim) if (!pComm->outOccupancyHeaders(0)) { filesOK = false; } +#if RS_RCPP + if (sim.outPop && sim.CreatePopFile) { +#else if (sim.outPop) { +#endif // open Population file if (!pComm->outPopHeaders(pSpecies, ppLand.landNum)) { filesOK = false; @@ -227,6 +251,11 @@ int RunModel(Landscape* pLandscape, int seqsim) // set up populations in the community pLandscape->updateCarryingCapacity(pSpecies, 0, 0); + + if (ppLand.rasterType == 2 && ppLand.spatialdemog) + pLandscape->updateDemoScalings(0); + +// if (init.seedType != 2) { pComm->initialise(pSpecies, -1); bool updateland = false; int landIx = 0; // landscape change index @@ -370,6 +399,10 @@ int RunModel(Landscape* pLandscape, int seqsim) if (updateCC) { pLandscape->updateCarryingCapacity(pSpecies, yr, landIx); + + if (ppLand.rasterType == 2 && ppLand.spatialdemog) //ppLand.spatialdemog false by default + pLandscape->updateDemoScalings((short)landIx); + } if (sim.outConnect && ppLand.patchModel) @@ -500,10 +533,10 @@ int RunModel(Landscape* pLandscape, int seqsim) } // end of the generation loop totalInds = pComm->totalInds(); - if (totalInds <= 0) { + if (totalInds <= 0) { cout << "All populations went extinct." << endl; - yr++; - break; + yr++; + break; } // Connectivity Matrix @@ -522,9 +555,9 @@ int RunModel(Landscape* pLandscape, int seqsim) pComm->outInds(rep, yr, -1, -1); // list any individuals dying having reached maximum age pComm->survival(1, 0, 1); // delete any such individuals totalInds = pComm->totalInds(); - if (totalInds <= 0) { + if (totalInds <= 0) { cout << "All populations went extinct." << endl; - yr++; + yr++; break; } } @@ -638,7 +671,11 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outRange) { pComm->outRangeHeaders(pSpecies, -999); // close Range file } +#if RS_RCPP + if (sim.outPop && sim.CreatePopFile) { +#else if (sim.outPop) { +#endif pComm->outPopHeaders(pSpecies, -999); // close Population file } if (sim.outTraitsCells) @@ -734,7 +771,11 @@ void RangePopOutput(Community* pComm, int rep, int yr, int gen) if (sim.outRange && (yr % sim.outIntRange == 0 || pComm->totalInds() <= 0)) pComm->outRange(pSpecies, rep, yr, gen); +#if RS_RCPP +if (sim.outPop && sim.CreatePopFile && yr >= sim.outStartPop && yr%sim.outIntPop == 0) +#else if (sim.outPop && yr >= sim.outStartPop && yr % sim.outIntPop == 0) +#endif pComm->outPop(rep, yr, gen); } @@ -780,7 +821,7 @@ void OutParameters(Landscape* pLandscape) outPar << endl << endl; outPar << "BATCH MODE \t"; - if (sim.batchMode) outPar << "yes" << endl; + if (sim.batchMode) outPar << "yes" << endl; else outPar << "no" << endl; #if RS_RCPP outPar << "SEED \t" << RS_random_seed << endl; diff --git a/Model.h b/Model.h index d57f3c5..65c40e3 100644 --- a/Model.h +++ b/Model.h @@ -48,7 +48,10 @@ Authors: Greta Bocedi & Steve Palmer, University of Aberdeen #include #include -#include +#if RS_RCPP +#include +#include "../Rinterface.h" +#endif // RS_RCPP #include "Parameters.h" #include "Landscape.h" @@ -65,7 +68,8 @@ using namespace std::filesystem; #if RS_RCPP && !R_CMD Rcpp::List RunModel( Landscape*, // pointer to Landscape - int // sequential simulation number + int, // sequential simulation number + Rcpp::S4 // parameter master to read initial conditions in each replicate simulation ); #else int RunModel( diff --git a/Parameters.h b/Parameters.h index 5974f8a..20f2b53 100644 --- a/Parameters.h +++ b/Parameters.h @@ -65,6 +65,7 @@ constexpr int gAbsorbingNoDataCost = 100; // cost to use in place of nodata valu // when boundaries are absorbing constexpr int gMaxNbStages = 10; // maximum number of stages permitted constexpr int gMaxNbSexes = 2; // maximum number of sexes permitted +constexpr int gMaxNbLayers = 3*gMaxNbSexes*gMaxNbStages; // maximum number of demographic scaling layers permitted #if RS_RCPP typedef intptr_t intptr; @@ -94,7 +95,7 @@ struct locn { int x; int y; }; /** Trait types **/ enum TraitType { - NEUTRAL, + NEUTRAL, GENETIC_LOAD, GENETIC_LOAD1, GENETIC_LOAD2, GENETIC_LOAD3, GENETIC_LOAD4, GENETIC_LOAD5, E_D0, E_ALPHA, E_BETA, @@ -233,7 +234,7 @@ struct initParams { }; struct initInd { - int year, patchID, x, y; + int year, patchID, x, y; short species, sex, age, stage; }; diff --git a/Patch.cpp b/Patch.cpp index 93b5cf2..0e76ee0 100644 --- a/Patch.cpp +++ b/Patch.cpp @@ -36,12 +36,14 @@ Patch::Patch(int seqnum, int num) for (int sex = 0; sex < gMaxNbSexes; sex++) { nTemp[sex] = 0; } + localDemoScaling.assign(nDSlayer,1.0); changed = false; } Patch::~Patch() { cells.clear(); popns.clear(); + localDemoScaling.clear(); } int Patch::getSeqNum(void) { return patchSeqNum; } @@ -210,6 +212,53 @@ void Patch::setCarryingCapacity(Species* pSpecies, patchLimits landlimits, float Patch::getK(void) { return localK; } +// SPATIALDEMOG +void Patch::setDemoScaling(std::vector ds) { + + std::for_each(ds.begin(), ds.end(), [](float& perc){ if(perc < 0.0 || perc > 1.0) perc=1; }); + + localDemoScaling.assign(ds.begin(), ds.end()); + + return; +} + +std::vector Patch::getDemoScaling(void) { return localDemoScaling; } + +void Patch::setPatchDemoScaling(short landIx, patchLimits landlimits) { + + // if patch wholly outside current landscape boundaries + if (xMin > landlimits.xMax || xMax < landlimits.xMin + || yMin > landlimits.yMax || yMax < landlimits.yMin) { + localDemoScaling.assign(nDSlayer,0.0); // set all local scales to zero + return; + } + + // loop through constituent cells of the patch + int ncells = (int)cells.size(); + std::vector patchDS(nDSlayer, 0.0); + std::vector cellDS(nDSlayer, 0.0); + + for (int i = 0; i < ncells; i++) { + cellDS = cells[i]->getDemoScaling(landIx); // is that ok? + + //add cell value to patch value + for (int ly = 0; ly < nDSlayer; ly++) { + patchDS[ly] += cellDS[ly]; + } + } + + // take mean over cells and divide by 100 to scale to range [0,1] + for (int ly = 0; ly < nDSlayer; ly++) { + patchDS[ly] = patchDS[ly] / ncells / 100.0f; + } + + // set values + setDemoScaling(patchDS); + + return; +} +//SPATIALDEMOG + // Return co-ordinates of a specified cell locn Patch::getCellLocn(int ix) { locn loc; loc.x = -666; loc.y = -666; diff --git a/Patch.h b/Patch.h index 6900658..ad1953a 100644 --- a/Patch.h +++ b/Patch.h @@ -141,6 +141,9 @@ class Patch { bool // TRUE if there is a gradient in carrying capacity across the Landscape ); float getK(void); + void setDemoScaling(std::vector ); + std::vector getDemoScaling(void); + void setPatchDemoScaling(short, patchLimits); // calculate demog. scalings of patch from its cells //TODO arguments bool speciesIsPresent(Species* sp); private: @@ -152,6 +155,7 @@ class Patch { intptr subCommPtr; // pointer (cast as integer) to sub-community associated with the patch // NOTE: FOR MULTI-SPECIES MODEL, PATCH WILL NEED TO STORE K FOR EACH SPECIES float localK; // patch carrying capacity (individuals) + std::vector localDemoScaling; bool changed; // NOTE: THE FOLLOWING ARRAY WILL NEED TO BE MADE SPECIES-SPECIFIC... short nTemp[gMaxNbSexes]; // no. of potential settlers in each sex @@ -166,4 +170,6 @@ class Patch { extern paramStoch* paramsStoch; extern RSrandom* pRandom; +extern short nDSlayer; + #endif diff --git a/Population.cpp b/Population.cpp index b8f9e99..271f415 100644 --- a/Population.cpp +++ b/Population.cpp @@ -455,7 +455,7 @@ double Population::computeHs() { return hs; } -popStats Population::getStats(void) +popStats Population::getStats(std::vector localDemoScaling) { popStats p = popStats(); int ninds; @@ -474,8 +474,18 @@ popStats Population::getStats(void) p.nNonJuvs += ninds; if (ninds > 0) { if (pSpecies->stageStructured()) { - if (dem.repType == 2) fec = pSpecies->getFec(stg, sex); - else fec = pSpecies->getFec(stg, 0); + if (dem.repType == 2) { + if (pSpecies->getFecSpatial() && pSpecies->getFecLayer(stg,sex)>=0){ + fec = pSpecies->getFec(stg,sex)*localDemoScaling[pSpecies->getFecLayer(stg,sex)]; + } + else fec = pSpecies->getFec(stg,sex); + } + else { + if (pSpecies->getFecSpatial() && pSpecies->getFecLayer(stg,0)>=0){ + fec = pSpecies->getFec(stg,0)*localDemoScaling[pSpecies->getFecLayer(stg,0)]; + } + else fec = pSpecies->getFec(stg,0); + } if (fec > 0.0) { breeders[sex] = true; p.nAdults += ninds; } } else breeders[sex] = true; @@ -535,7 +545,7 @@ void Population::extirpate(void) { //--------------------------------------------------------------------------- // Produce juveniles and hold them in the juvs vector -void Population::reproduction(const float localK, const float envval, const int resol) +void Population::reproduction(const float localK, const float envval, const int resol, std::vector localDemoScaling) { // get population size at start of reproduction @@ -567,10 +577,17 @@ void Population::reproduction(const float localK, const float envval, const int if (dem.stageStruct) { if (dem.repType == 1) { // simple sexual model // both sexes use fecundity recorded for females - fec[stg][sex] = pSpecies->getFec(stg, 0); + if (pSpecies->getFecSpatial() && pSpecies->getFecLayer(stg,0)>=0){ + fec[stg][sex] = pSpecies->getFec(stg,0)*localDemoScaling[pSpecies->getFecLayer(stg,0)]; + } + else fec[stg][sex] = pSpecies->getFec(stg,0); + } + else { + if (pSpecies->getFecSpatial() && pSpecies->getFecLayer(stg,sex)>=0){ + fec[stg][sex] = pSpecies->getFec(stg,sex)*localDemoScaling[pSpecies->getFecLayer(stg,sex)]; + } + else fec[stg][sex] = pSpecies->getFec(stg,sex); } - else - fec[stg][sex] = pSpecies->getFec(stg, sex); } else { // non-structured population if (stg == 1) fec[stg][sex] = dem.lambda; // adults @@ -1329,7 +1346,7 @@ bool Population::matePresent(Cell* pCell, short othersex) // FOR MULTIPLE SPECIES, MAY NEED TO SEPARATE OUT THIS IDENTIFICATION STAGE, // SO THAT IT CAN BE PERFORMED FOR ALL SPECIES BEFORE ANY UPDATING OF POPULATIONS -void Population::survival0(float localK, short option0, short option1) +void Population::survival0(float localK, short option0, short option1, std::vector localDemoScaling) { // option0: 0 - stage 0 (juveniles) only // 1 - all stages @@ -1357,13 +1374,25 @@ void Population::survival0(float localK, short option0, short option1) if (dem.stageStruct) { if (dem.repType == 1) { // simple sexual model // both sexes use development and survival recorded for females - dev[stg][sex] = pSpecies->getDev(stg, 0); - surv[stg][sex] = pSpecies->getSurv(stg, 0); + if (pSpecies->getDevSpatial() && pSpecies->getDevLayer(stg,0)>=0){ + dev[stg][sex] = pSpecies->getDev(stg,0)*localDemoScaling[pSpecies->getDevLayer(stg,0)]; + } + else dev[stg][sex] = pSpecies->getDev(stg,0); + if (pSpecies->getSurvSpatial() && pSpecies->getSurvLayer(stg,0)>=0){ + surv[stg][sex] = pSpecies->getSurv(stg,0)*localDemoScaling[pSpecies->getSurvLayer(stg,0)]; + } + else surv[stg][sex] = pSpecies->getSurv(stg,0); minAge[stg][sex] = pSpecies->getMinAge(stg, 0); } else { - dev[stg][sex] = pSpecies->getDev(stg, sex); - surv[stg][sex] = pSpecies->getSurv(stg, sex); + if (pSpecies->getDevSpatial() && pSpecies->getDevLayer(stg,sex)>=0){ + dev[stg][sex] = pSpecies->getDev(stg,sex)*localDemoScaling[pSpecies->getDevLayer(stg,sex)]; + } + else dev[stg][sex] = pSpecies->getDev(stg,sex); + if (pSpecies->getSurvSpatial() && pSpecies->getSurvLayer(stg,sex)>=0){ + surv[stg][sex] = pSpecies->getSurv(stg,sex)*localDemoScaling[pSpecies->getSurvLayer(stg,sex)]; + } + else surv[stg][sex] = pSpecies->getSurv(stg,sex); minAge[stg][sex] = pSpecies->getMinAge(stg, sex); } if (option1 == 0) surv[stg][sex] = 1.0; // development only - all survive @@ -1614,7 +1643,7 @@ void Population::outPopulation(int rep, int yr, int gen, float eps, } outPop << "\t" << pSpecies->getSpNum(); if (dem.stageStruct) { - p = getStats(); + p = getStats(pPatch->getDemoScaling()); outPop << "\t" << p.nNonJuvs; // non-juvenile stage totals from permanent array for (int stg = 1; stg < nStages; stg++) { diff --git a/Population.h b/Population.h index e143708..5285933 100644 --- a/Population.h +++ b/Population.h @@ -119,7 +119,9 @@ class Population { ); ~Population(void); traitsums getIndTraitsSums(Species*); - popStats getStats(void); + popStats getStats( + std::vector + ); Species* getSpecies(void); int getNInds(void); int totalPop(void); @@ -130,7 +132,8 @@ class Population { void reproduction( const float, // local carrying capacity const float, // effect of environmental gradient and/or stochasticty - const int // Landscape resolution + const int, // Landscape resolution + std::vector // local demographic scaling ); // Following reproduction of ALL species, add juveniles to the population void fledge(void); @@ -186,9 +189,10 @@ class Population { short, // option0: 0 - stage 0 (juveniles) only // 1 - all stages // 2 - stage 1 and above (all non-juveniles) - short // option1: 0 - development only (when survival is annual) + short, // option1: 0 - development only (when survival is annual) // 1 - development and survival // 2 - survival only (when survival is annual) + std::vector // local demographic scaling ); void survival1(void); // Apply survival changes to the population void ageIncrement(void); diff --git a/Species.cpp b/Species.cpp index c9b06ea..42aebaa 100644 --- a/Species.cpp +++ b/Species.cpp @@ -34,53 +34,59 @@ Species::Species(const short& repro, const short& nbRepSeasons, const bool& hasS moveType{movementType} { // initialise demographic parameters - propMales = 0.0; - harem = 1.0; - bc = 1.0; - lambda = 1.5; + propMales = 0.0; + harem = 1.0; + bc = 1.0; + lambda = 1.5; probRep = 1.0; - repInterval = 0; - maxAge = 1000; + repInterval = 0; + maxAge = 1000; survival = 1; - fecDens = false; + fecDens = false; fecStageDens = false; - devDens = false; + devDens = false; devStageDens = false; - survDens = false; + survDens = false; survStageDens = false; + fecSpatial = false; + survSpatial = false; + devSpatial = false; disperseOnLoss = false; for (int i = 0; i < gMaxNbStages; i++) { for (int j = 0; j < gMaxNbSexes; j++) { - fec[i][j] = 0.0; - dev[i][j] = 0.0; + fec[i][j] = 0.0; + dev[i][j] = 0.0; surv[i][j] = 0.0; minAge[i][j] = 0; + fecLayer[i][j] = -9; + devLayer[i][j] = -9; + survLayer[i][j] = -9; } } devCoeff = survCoeff = 1.0; - ddwtFec = ddwtDev = ddwtSurv = 0; + ddwtFec = ddwtDev = ddwtSurv = 0; ddwtFecDim = ddwtDevDim = ddwtSurvDim = 0; - habK = 0; + habK = 0; habDimK = 0; - minRK = 1.0; + minRK = 1.0; maxRK = 2.0; // initialise emigration parameters - densDepEmig = false; - stgDepEmig = false; - sexDepEmig = false; + densDepEmig = false; + stgDepEmig = false; + sexDepEmig = false; indVarEmig = false; emigStage = 0; for (int i = 0; i < gMaxNbStages; i++) { for (int j = 0; j < gMaxNbSexes; j++) { - d0[i][j] = 0.0; - alphaEmig[i][j] = 0.0; + d0[i][j] = 0.0; + alphaEmig[i][j] = 0.0; betaEmig[i][j] = 1.0; } } // initialise transfer parameters - stgDepTrfr = false; - sexDepTrfr = false; + stgDepTrfr = false; + sexDepTrfr = false; distMort = false; indVarTrfr = false; twinKern = false; @@ -88,45 +94,45 @@ Species::Species(const short& repro, const short& nbRepSeasons, const bool& hasS costMap = false; for (int i = 0; i < gMaxNbStages; i++) { for (int j = 0; j < gMaxNbSexes; j++) { - meanDist1[i][j] = 100.0f; - meanDist2[i][j] = 1000.0f; + meanDist1[i][j] = 100.0f; + meanDist2[i][j] = 1000.0f; probKern1[i][j] = 0.99f; } } - pr = 1; - prMethod = 1; - memSize = 1; + pr = 1; + prMethod = 1; + memSize = 1; goalType = 0; - dp = 1.0; + dp = 1.0; gb = 1.0; - alphaDB = 1.0; + alphaDB = 1.0; betaDB = 100000; - stepMort = 0.0; - stepLength = 10.0; + stepMort = 0.0; + stepLength = 10.0; rho = 0.9f; habStepMort = 0; habCost = 0; - fixedMort = 0.0; - mortAlpha = 0.0; + fixedMort = 0.0; + mortAlpha = 0.0; mortBeta = 1.0; habDimTrfr = 0; straightenPath = false; fullKernel = false; // initialise settlement parameters - stgDepSett = false; - sexDepSett = false; + stgDepSett = false; + sexDepSett = false; indVarSett = false; for (int i = 0; i < gMaxNbStages; i++) { for (int j = 0; j < gMaxNbSexes; j++) { - densDepSett[i][j] = false; - wait[i][j] = false; - go2nbrLocn[i][j] = false; + densDepSett[i][j] = false; + wait[i][j] = false; + go2nbrLocn[i][j] = false; findMate[i][j] = false; - maxStepsYr[i][j] = 99999999; - minSteps[i][j] = 0; + maxStepsYr[i][j] = 99999999; + minSteps[i][j] = 0; maxSteps[i][j] = 99999999; - s0[i][j] = 1.0; - alphaS[i][j] = 0.0; + s0[i][j] = 1.0; + alphaS[i][j] = 0.0; betaS[i][j] = 1.0; } } @@ -220,11 +226,11 @@ void Species::setStage(const stageParams s) { if (s.maxAge >= 1) maxAge = s.maxAge; if (s.survival >= 0 && s.survival <= 2) survival = s.survival; if (s.probRep > 0.0 && s.probRep <= 1.0) probRep = s.probRep; - fecDens = s.fecDens; + fecDens = s.fecDens; fecStageDens = s.fecStageDens; - devDens = s.devDens; + devDens = s.devDens; devStageDens = s.devStageDens; - survDens = s.survDens; + survDens = s.survDens; survStageDens = s.survStageDens; disperseOnLoss = s.disperseOnLoss; } @@ -285,6 +291,51 @@ float Species::getSurv(short stg, short sex) { else return 0.0; } +void Species::setFecSpatial(bool spat) { + fecSpatial = spat; +} + +void Species::setDevSpatial(bool spat) { + devSpatial = spat; +} + +void Species::setSurvSpatial(bool spat) { + survSpatial = spat; +} + +void Species::setFecLayer(short stg,short sex,short l) { +if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes && l >= 0) + fecLayer[stg][sex] = l; +} + +short Species::getFecLayer(short stg,short sex) { +if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) + return fecLayer[stg][sex]; +else return -9; +} + +void Species::setDevLayer(short stg,short sex,short l) { +if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes && l >= 0) + devLayer[stg][sex] = l; +} + +short Species::getDevLayer(short stg,short sex) { +if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) + return devLayer[stg][sex]; +else return -9; +} + +void Species::setSurvLayer(short stg,short sex,short l) { +if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes && l >= 0) + survLayer[stg][sex] = l; +} + +short Species::getSurvLayer(short stg,short sex) { +if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) + return survLayer[stg][sex]; +else return -9; +} + void Species::setMinAge(short stg, short sex, int age) { // NB min age for stages 0 & 1 must always be zero if (stg > 1 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes && age >= 0) @@ -527,8 +578,8 @@ set Species::getChromosomeEnds() const { // Emigration functions void Species::setEmigRules(const emigRules e) { - densDepEmig = e.densDep; - stgDepEmig = e.stgDep; + densDepEmig = e.densDep; + stgDepEmig = e.stgDep; sexDepEmig = e.sexDep; indVarEmig = e.indVar; if (e.emigStage >= 0) emigStage = e.emigStage; @@ -536,10 +587,10 @@ void Species::setEmigRules(const emigRules e) { emigRules Species::getEmigRules(void) { emigRules e; - e.densDep = densDepEmig; - e.stgDep = stgDepEmig; + e.densDep = densDepEmig; + e.stgDep = stgDepEmig; e.sexDep = sexDepEmig; - e.indVar = indVarEmig; + e.indVar = indVarEmig; e.emigStage = emigStage; return e; } @@ -547,7 +598,7 @@ emigRules Species::getEmigRules(void) { void Species::setSpEmigTraits(const short stg, const short sex, const emigTraits e) { if (stg >= 0 && stg < gMaxNbStages && sex >= 0 && sex < gMaxNbSexes) { if (e.d0 >= 0.0 && e.d0 <= 1.0) d0[stg][sex] = e.d0; - alphaEmig[stg][sex] = e.alpha; + alphaEmig[stg][sex] = e.alpha; betaEmig[stg][sex] = e.beta; } } @@ -579,14 +630,14 @@ float Species::getSpEmigD0(short stg, short sex) { // Transfer functions void Species::setTrfrRules(const transferRules t) { - usesMovtProcess = t.usesMovtProc; - stgDepTrfr = t.stgDep; + usesMovtProcess = t.usesMovtProc; + stgDepTrfr = t.stgDep; sexDepTrfr = t.sexDep; distMort = t.distMort; indVarTrfr = t.indVar; twinKern = t.twinKern; habMort = t.habMort; - moveType = t.moveType; + moveType = t.moveType; costMap = t.costMap; } diff --git a/Species.h b/Species.h index a71c96f..cae31c6 100644 --- a/Species.h +++ b/Species.h @@ -282,6 +282,45 @@ class Species { short // sex ); + void setFecSpatial(bool); + bool getFecSpatial(void){return fecSpatial;}; + void setDevSpatial(bool); + bool getDevSpatial(void){return devSpatial;}; + void setSurvSpatial(bool); + bool getSurvSpatial(void){return survSpatial;}; + void setFecLayer( // set the layer of the spatial demographic scaling used for fecundity + short, // stage + short, // sex + short // layer + ); + + short getFecLayer( // get the layer of the spatial demographic scaling used for fecundity + short, // stage + short // sex + ); + + void setDevLayer( // set the layer of the spatial demographic scaling used for development + short, // stage + short, // sex + short // layer + ); + + short getDevLayer( // get the layer of the spatial demographic scaling used for development + short, // stage + short // sex + ); + + void setSurvLayer( // set the layer of the spatial demographic scaling used for survival + short, // stage + short, // sex + short // layer + ); + + short getSurvLayer( // get the layer of the spatial demographic scaling used for survival + short, // stage + short // sex + ); + float getMaxFec(void); // Get highest fecundity of any stage void setMinAge( // Set minimum age short, // stage @@ -512,6 +551,7 @@ class Species { bool survStageDens; bool disperseOnLoss; // individuals disperse on complete loss of patch // (otherwise they die) + bool fecSpatial, devSpatial, survSpatial; short habDimK; // dimension of carrying capacities matrix float* habK; // habitat-specific carrying capacities (inds/cell) float devCoeff; // density-dependent development coefficient @@ -524,6 +564,9 @@ class Species { float dev[gMaxNbStages][gMaxNbSexes]; // development probabilities float surv[gMaxNbStages][gMaxNbSexes]; // survival probabilities short minAge[gMaxNbStages][gMaxNbSexes]; // minimum age to enter stage + int fecLayer[gMaxNbStages][gMaxNbSexes]; // layer for spatial varying fecundity + int devLayer[gMaxNbStages][gMaxNbSexes]; // layer for spatial varying development + int survLayer[gMaxNbStages][gMaxNbSexes]; // layer for spatial varying survival // NOTE - IN THEORY, NEXT 3 VARIABLES COULD BE COMMON, BUT WE WOULD NEED TO ENSURE THAT // ALL MATRICES ARE DELETED IF THERE IS A CHANGE IN NO. OF STAGES OR REPRODUCTION TYPE // ***** TO BE RECONSIDERED LATER ***** diff --git a/SubCommunity.cpp b/SubCommunity.cpp index bb23b3d..70e94f5 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -166,7 +166,7 @@ popStats SubCommunity::getPopStats(void) { // FOR SINGLE SPECIES IMPLEMENTATION, THERE IS ONLY ONE POPULATION IN THE PATCH int npops = (int)popns.size(); for (int i = 0; i < npops; i++) { // all populations - pop = popns[i]->getStats(); + pop = popns[i]->getStats(pPatch->getDemoScaling()); p.pSpecies = pop.pSpecies; p.spNum = pop.spNum; p.nInds += pop.nInds; @@ -246,6 +246,7 @@ void SubCommunity::reproduction(int resol, float epsGlobal, short rasterType, bo { if (subCommNum == 0) return; // no reproduction in the matrix float localK, envval; + std::vector localDemoScaling; Cell* pCell; envGradParams grad = paramsGrad->getGradient(); envStochParams env = paramsStoch->getStoch(); @@ -255,6 +256,7 @@ void SubCommunity::reproduction(int resol, float epsGlobal, short rasterType, bo if (npops < 1) return; localK = pPatch->getK(); + localDemoScaling = pPatch->getDemoScaling(); if (localK > 0.0) { if (patchModel) { envval = 1.0; // environmental gradient is currently not applied for patch-based model @@ -279,7 +281,7 @@ void SubCommunity::reproduction(int resol, float epsGlobal, short rasterType, bo } } for (int i = 0; i < npops; i++) { // all populations - popns[i]->reproduction(localK, envval, resol); + popns[i]->reproduction(localK, envval, resol, localDemoScaling); popns[i]->fledge(); } } @@ -306,7 +308,7 @@ void SubCommunity::initiateDispersal(SubCommunity* matrix) { int npops = (int)popns.size(); for (int i = 0; i < npops; i++) { // all populations - pop = popns[i]->getStats(); + pop = popns[i]->getStats(pPatch->getDemoScaling()); for (int j = 0; j < pop.nInds; j++) { disp = popns[i]->extractDisperser(j); if (disp.yes) { // disperser - has already been removed from natal population @@ -412,10 +414,12 @@ void SubCommunity::survival(short part, short option0, short option1) { int npops = (int)popns.size(); if (npops < 1) return; + std::vector localDemoScaling; if (part == 0) { + localDemoScaling = pPatch->getDemoScaling(); float localK = pPatch->getK(); for (int i = 0; i < npops; i++) { // all populations - popns[i]->survival0(localK, option0, option1); + popns[i]->survival0(localK, option0, option1, localDemoScaling); } } else { @@ -440,7 +444,7 @@ Population* SubCommunity::findPop(Species* pSp, Patch* pPch) { int npops = (int)popns.size(); for (int i = 0; i < npops; i++) { // all populations - pop = popns[i]->getStats(); + pop = popns[i]->getStats(pPatch->getDemoScaling()); if (pop.pSpecies == pSp && pop.pPatch == pPch) { // population located pPop = popns[i]; break; @@ -464,7 +468,7 @@ void SubCommunity::updateOccupancy(int row) { popStats pop; int npops = (int)popns.size(); for (int i = 0; i < npops; i++) { - pop = popns[i]->getStats(); + pop = popns[i]->getStats(pPatch->getDemoScaling()); if (pop.nInds > 0 && pop.breeding) { occupancy[row]++; i = npops; From b62d9417dfed392f173fbd0f9e97e12e62493f9e Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 18 Mar 2025 14:38:49 +0000 Subject: [PATCH 296/332] "Error" should be printed only once --- DispersalTrait.cpp | 26 +++++++-------- GeneticFitnessTrait.cpp | 70 ++++++++++++++++++++--------------------- NeutralStatsManager.h | 4 +-- Species.cpp | 2 +- 4 files changed, 51 insertions(+), 51 deletions(-) diff --git a/DispersalTrait.cpp b/DispersalTrait.cpp index 7bd30ad..8f6e7a6 100644 --- a/DispersalTrait.cpp +++ b/DispersalTrait.cpp @@ -24,24 +24,24 @@ DispersalTrait::DispersalTrait(SpeciesTrait* P) case UNIFORM: { if (mutationParameters.count(MAX) != 1) - throw logic_error("Error: mutation uniform distribution parameter must contain max value (e.g. max= ) \n"); + throw logic_error("mutation uniform distribution parameter must contain max value (e.g. max= ) \n"); if (mutationParameters.count(MIN) != 1) - throw logic_error("Error: mutation uniform distribution parameter must contain min value (e.g. min= ) \n"); + throw logic_error("mutation uniform distribution parameter must contain min value (e.g. min= ) \n"); _mutate_func_ptr = &DispersalTrait::mutateUniform; break; } case NORMAL: { if (mutationParameters.count(MEAN) != 1) - throw logic_error("Error: mutation distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); + throw logic_error("mutation distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); if (mutationParameters.count(SD) != 1) - throw logic_error("Error: mutation distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); + throw logic_error("mutation distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); _mutate_func_ptr = &DispersalTrait::mutateNormal; break; } default: { - throw logic_error("Error: wrong parameter value for mutation model, must be uniform/normal \n"); //unless want to add gamma or negative exp + throw logic_error("wrong parameter value for mutation model, must be uniform/normal \n"); //unless want to add gamma or negative exp break; } } @@ -54,9 +54,9 @@ DispersalTrait::DispersalTrait(SpeciesTrait* P) case UNIFORM: { if (initialParameters.count(MAX) != 1) - throw logic_error("Error: initial uniform distribution parameter must contain max value (e.g. max= ) \n"); + throw logic_error("initial uniform distribution parameter must contain max value (e.g. max= ) \n"); if (initialParameters.count(MIN) != 1) - throw logic_error("Error: initial uniform distribution parameter must contain min value (e.g. min= ) \n"); + throw logic_error("initial uniform distribution parameter must contain min value (e.g. min= ) \n"); float maxD = initialParameters.find(MAX)->second; float minD = initialParameters.find(MIN)->second; initialiseUniform(minD, maxD); @@ -65,9 +65,9 @@ DispersalTrait::DispersalTrait(SpeciesTrait* P) case NORMAL: { if (initialParameters.count(MEAN) != 1) - throw logic_error("Error: initial normal distribution parameter must contain mean value (e.g. mean= ) \n"); + throw logic_error("initial normal distribution parameter must contain mean value (e.g. mean= ) \n"); if (initialParameters.count(SD) != 1) - throw logic_error("Error: initial normal distribution parameter must contain sdev value (e.g. sdev= ) \n"); + throw logic_error("initial normal distribution parameter must contain sdev value (e.g. sdev= ) \n"); float mean = initialParameters.find(MEAN)->second; float sd = initialParameters.find(SD)->second; initialiseNormal(mean, sd); @@ -278,9 +278,9 @@ void DispersalTrait::reInitialiseGenes(const bool& fromMother, mapsecond; float minD = initialParameters.find(MIN)->second; initialiseUniform(minD, maxD); @@ -289,9 +289,9 @@ void DispersalTrait::reInitialiseGenes(const bool& fromMother, mapsecond; float sd = initialParameters.find(SD)->second; initialiseNormal(mean, sd); diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index c20c164..4dbfed4 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -20,31 +20,31 @@ GeneticFitnessTrait::GeneticFitnessTrait(SpeciesTrait* P) case UNIFORM: { if (initialParameters.count(MAX) != 1) - throw logic_error("Error: initial uniform distribution parameter must contain max value (e.g. max= ) \n"); + throw logic_error("initial uniform distribution parameter must contain max value (e.g. max= ) \n"); if (initialParameters.count(MIN) != 1) - throw logic_error("Error: initial uniform distribution parameter must contain min value (e.g. min= ) \n"); + throw logic_error("initial uniform distribution parameter must contain min value (e.g. min= ) \n"); break; } case NORMAL: { if (initialParameters.count(MEAN) != 1) - throw logic_error("Error: initial normal distribution parameter must contain mean value (e.g. mean= ) \n"); + throw logic_error("initial normal distribution parameter must contain mean value (e.g. mean= ) \n"); if (initialParameters.count(SD) != 1) - throw logic_error("Error: initial normal distribution parameter must contain sdev value (e.g. sdev= ) \n"); + throw logic_error("initial normal distribution parameter must contain sdev value (e.g. sdev= ) \n"); break; } case GAMMA: { if (initialParameters.count(SHAPE) != 1) - throw logic_error("Error:: genetic load dominance distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); + throw logic_error("genetic load dominance distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); if (initialParameters.count(SCALE) != 1) - throw logic_error("Error:: genetic load dominance distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); + throw logic_error("genetic load dominance distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); break; } case NEGEXP: { if (initialParameters.count(MEAN) != 1) - throw logic_error("Error:: genetic load dominance distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); + throw logic_error("genetic load dominance distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); break; } case NONE: // initialise with default (i.e. zero) values @@ -62,37 +62,37 @@ GeneticFitnessTrait::GeneticFitnessTrait(SpeciesTrait* P) case UNIFORM: { if (initDomParameters.count(MAX) != 1) - throw logic_error("Error:: genetic load dominance uniform distribution parameter must contain one max value (e.g. max= ) \n"); + throw logic_error("genetic load dominance uniform distribution parameter must contain one max value (e.g. max= ) \n"); if (initDomParameters.count(MIN) != 1) - throw logic_error("Error:: genetic load dominance uniform distribution parameter must contain one min value (e.g. min= ) \n"); + throw logic_error("genetic load dominance uniform distribution parameter must contain one min value (e.g. min= ) \n"); break; } case NORMAL: { if (initDomParameters.count(MEAN) != 1) - throw logic_error("Error:: genetic load dominance distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); + throw logic_error("genetic load dominance distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); if (initDomParameters.count(SD) != 1) - throw logic_error("Error:: genetic load dominance distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); + throw logic_error("genetic load dominance distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); break; } case GAMMA: { if (initDomParameters.count(SHAPE) != 1) - throw logic_error("Error:: genetic load dominance distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); + throw logic_error("genetic load dominance distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); if (initDomParameters.count(SCALE) != 1) - throw logic_error("Error:: genetic load dominance distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); + throw logic_error("genetic load dominance distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); break; } case NEGEXP: { if (initDomParameters.count(MEAN) != 1) - throw logic_error("Error:: genetic load dominance distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); + throw logic_error("genetic load dominance distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); break; } case SCALED: { if (initDomParameters.count(MEAN) != 1) - throw logic_error("Error:: genetic load dominance distribution set to scaled, so parameters must contain mean dominance value (e.g. mean= ) \n"); + throw logic_error("genetic load dominance distribution set to scaled, so parameters must contain mean dominance value (e.g. mean= ) \n"); // Set for drawing initial values setScaledCoeff(initialDistribution, initialParameters); break; @@ -101,7 +101,7 @@ GeneticFitnessTrait::GeneticFitnessTrait(SpeciesTrait* P) break; default: { - throw logic_error("Error:: wrong parameter value for genetic load dominance model, must be uniform/normal/gamma/negExp/scaled \n"); + throw logic_error("wrong parameter value for genetic load dominance model, must be uniform/normal/gamma/negExp/scaled \n"); break; } } @@ -115,35 +115,35 @@ GeneticFitnessTrait::GeneticFitnessTrait(SpeciesTrait* P) case UNIFORM: { if (mutationParameters.count(MAX) != 1) - throw logic_error("Error:: genetic load mutation uniform distribution parameter must contain one max value (e.g. max= ) \n"); + throw logic_error("genetic load mutation uniform distribution parameter must contain one max value (e.g. max= ) \n"); if (mutationParameters.count(MIN) != 1) - throw logic_error("Error:: genetic load mutation uniform distribution parameter must contain one min value (e.g. min= ) \n"); + throw logic_error("genetic load mutation uniform distribution parameter must contain one min value (e.g. min= ) \n"); break; } case NORMAL: { if (mutationParameters.count(MEAN) != 1) - throw logic_error("Error:: genetic load mutation distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); + throw logic_error("genetic load mutation distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); if (mutationParameters.count(SD) != 1) - throw logic_error("Error:: genetic load mutation distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); + throw logic_error("genetic load mutation distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); break; } case GAMMA: { if (mutationParameters.count(SHAPE) != 1) - throw logic_error("Error:: genetic load mutation distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); + throw logic_error("genetic load mutation distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); if (mutationParameters.count(SCALE) != 1) - throw logic_error("Error:: genetic load mutation distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); + throw logic_error("genetic load mutation distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); break; } case NEGEXP: { if (mutationParameters.count(MEAN) != 1) - throw logic_error("Error:: genetic load mutation distribution set to negative exponential (negative decay) so parameters must contain one mean value (e.g. mean= ) \n"); + throw logic_error("genetic load mutation distribution set to negative exponential (negative decay) so parameters must contain one mean value (e.g. mean= ) \n"); break; } default: - throw logic_error("Error:: wrong parameter value for genetic load mutation model, must be uniform/normal/gamma/negExp \n"); + throw logic_error("wrong parameter value for genetic load mutation model, must be uniform/normal/gamma/negExp \n"); } DistributionType dominanceDistribution = pSpeciesTrait->getDominanceDistribution(); @@ -153,37 +153,37 @@ GeneticFitnessTrait::GeneticFitnessTrait(SpeciesTrait* P) case UNIFORM: { if (dominanceParameters.count(MAX) != 1) - throw logic_error("Error:: genetic load dominance uniform distribution parameter must contain one max value (e.g. max= ) \n"); + throw logic_error("genetic load dominance uniform distribution parameter must contain one max value (e.g. max= ) \n"); if (dominanceParameters.count(MIN) != 1) - throw logic_error("Error:: genetic load dominance uniform distribution parameter must contain one min value (e.g. min= ) \n"); + throw logic_error("genetic load dominance uniform distribution parameter must contain one min value (e.g. min= ) \n"); break; } case NORMAL: { if (dominanceParameters.count(MEAN) != 1) - throw logic_error("Error:: genetic load dominance distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); + throw logic_error("genetic load dominance distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); if (dominanceParameters.count(SD) != 1) - throw logic_error("Error:: genetic load dominance distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); + throw logic_error("genetic load dominance distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); break; } case GAMMA: { if (dominanceParameters.count(SHAPE) != 1) - throw logic_error("Error:: genetic load dominance distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); + throw logic_error("genetic load dominance distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); if (dominanceParameters.count(SCALE) != 1) - throw logic_error("Error:: genetic load dominance distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); + throw logic_error("genetic load dominance distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); break; } case NEGEXP: { if (dominanceParameters.count(MEAN) != 1) - throw logic_error("Error:: genetic load dominance distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); + throw logic_error("genetic load dominance distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); break; } case SCALED: { if (dominanceParameters.count(MEAN) != 1) - throw logic_error("Error:: genetic load dominance distribution set to scaled, so parameters must contain mean dominance value (e.g. mean= ) \n"); + throw logic_error("genetic load dominance distribution set to scaled, so parameters must contain mean dominance value (e.g. mean= ) \n"); // Set for drawing mutations (overwrite initial value) setScaledCoeff(mutationDistribution, mutationParameters); @@ -191,7 +191,7 @@ GeneticFitnessTrait::GeneticFitnessTrait(SpeciesTrait* P) } default: { - throw logic_error("Error:: wrong parameter value for genetic load dominance model, must be uniform/normal/gamma/negExp/scaled \n"); + throw logic_error("wrong parameter value for genetic load dominance model, must be uniform/normal/gamma/negExp/scaled \n"); break; } } @@ -346,7 +346,7 @@ float GeneticFitnessTrait::drawDominance(float selCoef, const DistributionType& default: { - throw logic_error("Error:: wrong parameter value for genetic load dominance model, must be uniform/normal/gamma/negExp/scaled \n"); + throw logic_error("wrong parameter value for genetic load dominance model, must be uniform/normal/gamma/negExp/scaled \n"); break; } } @@ -400,7 +400,7 @@ float GeneticFitnessTrait::drawSelectionCoef(const DistributionType& mutationDis } default: { - throw logic_error("Error:: wrong parameter value for genetic load mutation model, must be uniform/normal/gamma/negExp/scaled \n"); + throw logic_error("wrong parameter value for genetic load mutation model, must be uniform/normal/gamma/negExp/scaled \n"); break; } } diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index 42e19ed..fac9791 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -21,7 +21,7 @@ struct PatchMatrix // Get value at specified position double get(unsigned int i, unsigned int j) { if (i >= cols || j >= rows) - throw runtime_error("Error: PatchMatrix::get() out of range!\n"); + throw runtime_error("PatchMatrix::get() out of range!\n"); else return value[i * cols + j]; } @@ -30,7 +30,7 @@ struct PatchMatrix /** Sets element at row i and column j to value val **/ void set(unsigned int i, unsigned int j, double val) { if (i >= cols || j >= rows) - throw runtime_error("Error: PatchMatrix::set() out of range!\n"); + throw runtime_error("PatchMatrix::set() out of range!\n"); else value[i * cols + j] = val; } diff --git a/Species.cpp b/Species.cpp index c9b06ea..dd85825 100644 --- a/Species.cpp +++ b/Species.cpp @@ -481,7 +481,7 @@ void Species::addTrait(TraitType traitType, const SpeciesTrait& trait) { } default: { - cout << endl << ("Error:: Too many genetic load traits in Traits file, max = 5 \n"); + cout << endl << ("Too many genetic load traits in Traits file, max = 5 \n"); break; } } From 7386236efd7e2ac31ef0da1f5b1ecda7274347ff Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 18 Mar 2025 16:52:47 +0000 Subject: [PATCH 297/332] fix incorrect dominance distribution value in genetic load tests --- unit_tests/testIndividual.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 8dbf8d3..aa95d30 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -940,14 +940,15 @@ void testIndividual() { set{ 0 }, // only one locus ExpressionType::MULTIPLICATIVE, DistributionType::NONE, initParams, - DistributionType::UNIFORM, domParams, // no dominance, params are ignored + DistributionType::UNIFORM, domParams, true, // isInherited 1.0, // will mutate DistributionType::UNIFORM, mutationParams, // lethal mutation - DistributionType::NONE, initParams, + DistributionType::UNIFORM, domParams, 2, // diploid false ); + pSpecies->addTrait(TraitType::GENETIC_LOAD1, *spTr); Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); @@ -964,7 +965,7 @@ void testIndividual() { assert(!ind.isViable()); } - // A largely dominant alleles overrides the expression of its homologue + // A largely dominant allele overrides the expression of its homologue { Patch* pPatch = new Patch(0, 0); Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); @@ -979,23 +980,23 @@ void testIndividual() { set{}, "none", set{}, 0 // no output so no sampling ); - // Create species trait + // Create template species trait const map distParams{ pair{GenParamType::MIN, 0.0}, pair{GenParamType::MAX, 0.0} }; - + // Pretty empty, actual values are set below SpeciesTrait* spTr = new SpeciesTrait( TraitType::GENETIC_LOAD1, sex_t::NA, set{ 0 }, // only one locus ExpressionType::MULTIPLICATIVE, DistributionType::NONE, distParams, - DistributionType::UNIFORM, distParams, // no dominance, params are ignored + DistributionType::UNIFORM, distParams, true, // isInherited 0.0, // no mutation - DistributionType::UNIFORM, distParams, // lethal mutation - DistributionType::NONE, distParams, + DistributionType::UNIFORM, distParams, + DistributionType::UNIFORM, distParams, 2, // diploid false ); From ef5cd1f8d17f938d4991591b2f88691a352e0f07 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Thu, 20 Mar 2025 11:11:10 +0100 Subject: [PATCH 298/332] Fixing compilation errors for R package StreamErrorR(): path*File is not known -> must be habfile/pchfile R interface still outputs visits (SMS heat maps) -> needs the saveVisits option --- Landscape.cpp | 28 ++++++++++++++-------------- Parameters.cpp | 1 + 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index 8352e2a..04e6662 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -2390,7 +2390,7 @@ resol = (int) tmpresol; #if RS_RCPP if (!hfile.good()) { // corrupt file stream - StreamErrorR(pathHabFile); + StreamErrorR(habfile); hfile.close(); hfile.clear(); if (patchModel) { @@ -2424,7 +2424,7 @@ resol = (int) tmpresol; #if RS_RCPP if (!pfile.good()) { // corrupt file stream - StreamErrorR(pathPatchFile); + StreamErrorR(pchfile); hfile.close(); hfile.clear(); pfile.close(); @@ -2471,7 +2471,7 @@ resol = (int) tmpresol; #if RS_RCPP && !R_CMD Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - StreamErrorR(pathPatchFile); + StreamErrorR(pchfile); hfile.close(); hfile.clear(); pfile.close(); @@ -2485,7 +2485,7 @@ resol = (int) tmpresol; #if RS_RCPP && !R_CMD Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - StreamErrorR(pathHabFile); + StreamErrorR(habfile); hfile.close(); hfile.clear(); if (patchModel) { @@ -2551,11 +2551,11 @@ resol = (int) tmpresol; } #if RS_RCPP hfile >> hfloat; -if (!hfile.eof()) EOFerrorR(pathHabFile); +if (!hfile.eof()) EOFerrorR(habfile); if (patchModel) { pfile >> pfloat; - if (!pfile.eof()) EOFerrorR(pathPatchFile); + if (!pfile.eof()) EOFerrorR(pchfile); } #endif break; @@ -2586,7 +2586,7 @@ case 1: // multiple % cover #if RS_RCPP && !R_CMD Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - StreamErrorR(pathPatchFile); + StreamErrorR(pchfile); hfile.close(); hfile.clear(); pfile.close(); @@ -2667,7 +2667,7 @@ else { // couldn't read from hfile #if RS_RCPP && !R_CMD Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - StreamErrorR(pathHabFile); + StreamErrorR(habfile); hfile.close(); hfile.clear(); if (patchModel) { @@ -2683,11 +2683,11 @@ else { // couldn't read from hfile habIndexed = true; // habitats are already numbered 1...n in correct order #if RS_RCPP hfile >> hfloat; - if (!hfile.eof()) EOFerrorR(pathHabFile); + if (!hfile.eof()) EOFerrorR(habfile); if (patchModel) { pfile >> pfloat; - if (!pfile.eof()) EOFerrorR(pathPatchFile); + if (!pfile.eof()) EOFerrorR(pchfile); } #endif break; @@ -2710,7 +2710,7 @@ case 2: // habitat quality #if RS_RCPP && !R_CMD Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - StreamErrorR(pathHabFile); + StreamErrorR(habfile); hfile.close(); hfile.clear(); if (patchModel) { @@ -2735,7 +2735,7 @@ case 2: // habitat quality #if RS_RCPP && !R_CMD Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - StreamErrorR(pathPatchFile); + StreamErrorR(pchfile); hfile.close(); hfile.clear(); pfile.close(); @@ -2795,11 +2795,11 @@ case 2: // habitat quality } #if RS_RCPP hfile >> hfloat; - if (!hfile.eof()) EOFerrorR(pathHabFile); + if (!hfile.eof()) EOFerrorR(habfile); if (patchModel) { pfile >> pfloat; - if (!pfile.eof()) EOFerrorR(pathPatchFile); + if (!pfile.eof()) EOFerrorR(habfile); } #endif break; diff --git a/Parameters.cpp b/Parameters.cpp index daefadf..9e959a5 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -296,6 +296,7 @@ simParams paramSim::getSim() { s.absorbing = absorbing; s.traitInt = traitInt; #if RS_RCPP + s.saveVisits = saveVisits; s.outStartPaths = outStartPaths; s.outIntPaths = outIntPaths; s.outPaths = outPaths; From 47e06afab2579726756173485c538dce180f6dfa Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Tue, 8 Apr 2025 09:28:12 +0200 Subject: [PATCH 299/332] added RS_RCPP macro for R specific landscape inputs updated testIndividual.cpp according to current new_genetics version --- Landscape.cpp | 9 ++++++--- Landscape.h | 5 +++-- unit_tests/testIndividual.cpp | 8 ++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index 04e6662..ffd10e2 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -1903,7 +1903,8 @@ void Landscape::deleteCostsChgMatrix(void) { // Species distribution functions -//If file input as R objects +//If file input as R objects only for #RS_RCPP +#if RS_RCPP int Landscape::newDistribution(Species *pSpecies, Rcpp::NumericMatrix distname, int spResol) { int readcode; int ndistns = (int)distns.size(); @@ -1917,6 +1918,7 @@ int Landscape::newDistribution(Species *pSpecies, Rcpp::NumericMatrix distname, } return readcode; } +#endif // Standard file input int Landscape::newDistribution(Species *pSpecies, string distname) { int readcode; @@ -2023,8 +2025,9 @@ void Landscape::clearInitCells(void) { // Read landscape file(s) // Returns error code or zero if read correctly -// for new landscape input using R objects AND spatial demography: +// for new landscape input using R objects AND spatial demography: only for RS_RCPP // RS_THREADSAFE and SPATIALDEMOG +#if RS_RCPP int Landscape::readLandscape(int fileNum, Rcpp::NumericMatrix habfile, Rcpp::NumericMatrix pchfile, Rcpp::NumericMatrix costfile, Rcpp::NumericVector scalinglayers) { if (fileNum < 0) return 19; @@ -2320,7 +2323,7 @@ int Landscape::readLandscape(int fileNum, Rcpp::NumericMatrix habfile, Rcpp::Num } return 0; } - +#endif int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string costfile) { diff --git a/Landscape.h b/Landscape.h index 18deaa9..179c31e 100644 --- a/Landscape.h +++ b/Landscape.h @@ -88,8 +88,9 @@ using namespace std; #include #endif #include -#endif #include +#endif + //--------------------------------------------------------------------------- // not sure whether it needs to be added here for the readDistribution() function to work @@ -502,7 +503,7 @@ class Landscape{ Rcpp::NumericMatrix // cost raster ,Rcpp::NumericVector // array of demographic scaling layers ); -#endif //for RS_THREADSAFE +#endif int readLandscape( int, // fileNum == 0 for (first) habitat file and optional patch file // fileNum > 0 for subsequent habitat files under the %cover option diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index aa95d30..185a45a 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -944,7 +944,7 @@ void testIndividual() { true, // isInherited 1.0, // will mutate DistributionType::UNIFORM, mutationParams, // lethal mutation - DistributionType::UNIFORM, domParams, + DistributionType::NONE, domParams, 2, // diploid false ); @@ -995,8 +995,8 @@ void testIndividual() { DistributionType::UNIFORM, distParams, true, // isInherited 0.0, // no mutation - DistributionType::UNIFORM, distParams, - DistributionType::UNIFORM, distParams, + DistributionType::UNIFORM, distParams, // lethal mutation + DistributionType::NONE, distParams, 2, // diploid false ); @@ -1356,4 +1356,4 @@ void testIndividual() { } -#endif //NDEBUG \ No newline at end of file +#endif //NDEBUG From ced9044d2b6716cb5322383d0892b26ad62b968d Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Tue, 8 Apr 2025 15:25:08 +0200 Subject: [PATCH 300/332] compared to RangeShifter_batch/new_genetics; now in line --- Model.h | 1 + unit_tests/testIndividual.cpp | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Model.h b/Model.h index 65c40e3..5195f05 100644 --- a/Model.h +++ b/Model.h @@ -52,6 +52,7 @@ Authors: Greta Bocedi & Steve Palmer, University of Aberdeen #include #include "../Rinterface.h" #endif // RS_RCPP +#include #include "Parameters.h" #include "Landscape.h" diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 185a45a..5af96c2 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -940,15 +940,14 @@ void testIndividual() { set{ 0 }, // only one locus ExpressionType::MULTIPLICATIVE, DistributionType::NONE, initParams, - DistributionType::UNIFORM, domParams, + DistributionType::UNIFORM, domParams, // no dominance, params are ignored true, // isInherited 1.0, // will mutate DistributionType::UNIFORM, mutationParams, // lethal mutation - DistributionType::NONE, domParams, + DistributionType::NONE, initParams, 2, // diploid false ); - pSpecies->addTrait(TraitType::GENETIC_LOAD1, *spTr); Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); @@ -965,7 +964,7 @@ void testIndividual() { assert(!ind.isViable()); } - // A largely dominant allele overrides the expression of its homologue + // A largely dominant alleles overrides the expression of its homologue { Patch* pPatch = new Patch(0, 0); Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); @@ -980,19 +979,19 @@ void testIndividual() { set{}, "none", set{}, 0 // no output so no sampling ); - // Create template species trait + // Create species trait const map distParams{ pair{GenParamType::MIN, 0.0}, pair{GenParamType::MAX, 0.0} }; - // Pretty empty, actual values are set below + SpeciesTrait* spTr = new SpeciesTrait( TraitType::GENETIC_LOAD1, sex_t::NA, set{ 0 }, // only one locus ExpressionType::MULTIPLICATIVE, DistributionType::NONE, distParams, - DistributionType::UNIFORM, distParams, + DistributionType::UNIFORM, distParams, // no dominance, params are ignored true, // isInherited 0.0, // no mutation DistributionType::UNIFORM, distParams, // lethal mutation From 365d7364a13e438f853f38149ac926d74f3f1168 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 22 Apr 2025 20:52:17 +0100 Subject: [PATCH 301/332] rm duplicated batch name --- Population.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Population.cpp b/Population.cpp index 00d31e2..22f09dd 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1541,7 +1541,6 @@ bool Population::outPopHeaders(int landNr, bool patchModel) { stageParams sstruct = pSpecies->getStageParams(); name = paramsSim->getDir(2) + (sim.batchMode ? "Batch" + to_string(sim.batchNum) + "_" : "") - + "Batch" + to_string(sim.batchNum) + "_" + "Sim" + to_string(sim.simulation) + "_Land" + to_string(landNr) + "_Pop.txt"; outPop.open(name.c_str()); From b0df20d01fdcee6dc3fbcd95c0146fbdd875fc3f Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 25 Apr 2025 16:13:20 +0100 Subject: [PATCH 302/332] refactor trait summaries --- Population.cpp | 110 ++++++------- SubCommunity.cpp | 395 +++++++++++++++++++++++------------------------ 2 files changed, 236 insertions(+), 269 deletions(-) diff --git a/Population.cpp b/Population.cpp index 22f09dd..3a035ad 100644 --- a/Population.cpp +++ b/Population.cpp @@ -202,7 +202,7 @@ Population::~Population(void) { } traitsums Population::getIndTraitsSums(Species* pSpecies) { - int g; + traitsums ts = traitsums(); for (int sex = 0; sex < gMaxNbSexes; sex++) { ts.ninds[sex] = 0; @@ -228,52 +228,43 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { transferRules trfr = pSpecies->getTransferRules(); settleType sett = pSpecies->getSettle(); - int ninds = (int)inds.size(); - for (int iInd = 0; iInd < ninds; iInd++) { - int sex = inds[iInd]->getSex(); - if (emig.sexDep || trfr.sexDep || sett.sexDep) - g = sex; - else g = 0; - ts.ninds[g] += 1; + for (auto& ind : inds) { + + int sex = ind->getSex(); + ts.ninds[sex] += 1; // emigration traits - emigTraits e = inds[iInd]->getIndEmigTraits(); - if (emig.sexDep) g = sex; - else g = 0; - ts.sumD0[g] += e.d0; - ts.ssqD0[g] += e.d0 * e.d0; - ts.sumAlpha[g] += e.alpha; - ts.ssqAlpha[g] += e.alpha * e.alpha; - ts.sumBeta[g] += e.beta; - ts.ssqBeta[g] += e.beta * e.beta; + emigTraits e = ind->getIndEmigTraits(); + ts.sumD0[sex] += e.d0; + ts.ssqD0[sex] += e.d0 * e.d0; + ts.sumAlpha[sex] += e.alpha; + ts.ssqAlpha[sex] += e.alpha * e.alpha; + ts.sumBeta[sex] += e.beta; + ts.ssqBeta[sex] += e.beta * e.beta; // transfer traits if (trfr.usesMovtProc) { switch (trfr.moveType) { - case 1: // SMS - { - trfrSMSTraits sms = inds[iInd]->getIndSMSTraits(); - g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ts.sumDP[g] += sms.dp; - ts.ssqDP[g] += sms.dp * sms.dp; - ts.sumGB[g] += sms.gb; - ts.ssqGB[g] += sms.gb * sms.gb; - ts.sumAlphaDB[g] += sms.alphaDB; - ts.ssqAlphaDB[g] += sms.alphaDB * sms.alphaDB; - ts.sumBetaDB[g] += sms.betaDB; - ts.ssqBetaDB[g] += sms.betaDB * sms.betaDB; + case 1: { // SMS + trfrSMSTraits sms = ind->getIndSMSTraits(); + ts.sumDP[sex] += sms.dp; + ts.ssqDP[sex] += sms.dp * sms.dp; + ts.sumGB[sex] += sms.gb; + ts.ssqGB[sex] += sms.gb * sms.gb; + ts.sumAlphaDB[sex] += sms.alphaDB; + ts.ssqAlphaDB[sex] += sms.alphaDB * sms.alphaDB; + ts.sumBetaDB[sex] += sms.betaDB; + ts.ssqBetaDB[sex] += sms.betaDB * sms.betaDB; break; } - case 2: - { - trfrCRWTraits c = inds[iInd]->getIndCRWTraits(); - g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ts.sumStepL[g] += c.stepLength; - ts.ssqStepL[g] += c.stepLength * c.stepLength; - ts.sumRho[g] += c.rho; - ts.ssqRho[g] += c.rho * c.rho; + case 2: { + trfrCRWTraits c = ind->getIndCRWTraits(); + ts.sumStepL[sex] += c.stepLength; + ts.ssqStepL[sex] += c.stepLength * c.stepLength; + ts.sumRho[sex] += c.rho; + ts.ssqRho[sex] += c.rho * c.rho; break; } default: @@ -282,38 +273,31 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { } } else { - trfrKernelParams k = inds[iInd]->getIndKernTraits(); - if (trfr.sexDep) g = sex; - else g = 0; - ts.sumDist1[g] += k.meanDist1; - ts.ssqDist1[g] += k.meanDist1 * k.meanDist1; - ts.sumDist2[g] += k.meanDist2; - ts.ssqDist2[g] += k.meanDist2 * k.meanDist2; - ts.sumProp1[g] += k.probKern1; - ts.ssqProp1[g] += k.probKern1 * k.probKern1; + trfrKernelParams k = ind->getIndKernTraits(); + ts.sumDist1[sex] += k.meanDist1; + ts.ssqDist1[sex] += k.meanDist1 * k.meanDist1; + ts.sumDist2[sex] += k.meanDist2; + ts.ssqDist2[sex] += k.meanDist2 * k.meanDist2; + ts.sumProp1[sex] += k.probKern1; + ts.ssqProp1[sex] += k.probKern1 * k.probKern1; } // settlement traits - settleTraits s = inds[iInd]->getIndSettTraits(); - if (sett.sexDep) g = sex; - else g = 0; - // g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ts.sumS0[g] += s.s0; - ts.ssqS0[g] += s.s0 * s.s0; - ts.sumAlphaS[g] += s.alpha; - ts.ssqAlphaS[g] += s.alpha * s.alpha; - ts.sumBetaS[g] += s.beta; - ts.ssqBetaS[g] += s.beta * s.beta; - - if (gMaxNbSexes > 1) g = sex; - else g = 0; - - ts.sumGeneticFitness[g] += inds[iInd]->getGeneticFitness(); - ts.ssqGeneticFitness[g] += inds[iInd]->getGeneticFitness() * inds[iInd]->getGeneticFitness(); + settleTraits s = ind->getIndSettTraits(); + ts.sumS0[sex] += s.s0; + ts.ssqS0[sex] += s.s0 * s.s0; + ts.sumAlphaS[sex] += s.alpha; + ts.ssqAlphaS[sex] += s.alpha * s.alpha; + ts.sumBetaS[sex] += s.beta; + ts.ssqBetaS[sex] += s.beta * s.beta; + + double fitness = ind->getGeneticFitness(); + ts.sumGeneticFitness[sex] += fitness; + ts.ssqGeneticFitness[sex] += fitness * fitness; } return ts; } -int Population::getNInds(void) { return (int)inds.size(); } +int Population::getNInds() { return static_cast(inds.size()); } // ---------------------------------------------------------------------------------------- // reset allele table diff --git a/SubCommunity.cpp b/SubCommunity.cpp index bb23b3d..5292c2d 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -709,12 +709,8 @@ bool SubCommunity::outTraitsHeaders(Landscape* pLandscape, Species* pSpecies, in // Write records to traits file and return aggregated sums traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int gen, bool commlevel) { - int popsize, ploidy; landParams land = pLandscape->getLandParams(); simParams sim = paramsSim->getSim(); - bool writefile = false; - if (sim.outTraitsCells && yr % sim.outIntTraitCell == 0 && !commlevel) - writefile = true; traitsums ts, indTraitsSums; for (int i = 0; i < gMaxNbSexes; i++) { ts.ninds[i] = 0; @@ -736,11 +732,10 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge // provided that the patch is suitable (i.e. non-zero carrying capacity) int npops = (int)popns.size(); Species* pSpecies; - float localK; for (int iPop = 0; iPop < npops; iPop++) { // all populations - localK = pPatch->getK(); - if (localK > 0.0 && popns[iPop]->getNInds() > 0) { + + if (pPatch->getK() > 0.0 && popns[iPop]->getNInds() > 0) { pSpecies = popns[iPop]->getSpecies(); demogrParams dem = pSpecies->getDemogrParams(); emigRules emig = pSpecies->getEmigRules(); @@ -748,7 +743,47 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge settleType sett = pSpecies->getSettle(); indTraitsSums = popns[iPop]->getIndTraitsSums(pSpecies); - if (writefile) { + // Sum over populations + for (int iSex = 0; iSex < gMaxNbSexes; iSex++) { + ts.ninds[iSex] += indTraitsSums.ninds[iSex]; + ts.sumD0[iSex] += indTraitsSums.sumD0[iSex]; + ts.ssqD0[iSex] += indTraitsSums.ssqD0[iSex]; + ts.sumAlpha[iSex] += indTraitsSums.sumAlpha[iSex]; + ts.ssqAlpha[iSex] += indTraitsSums.ssqAlpha[iSex]; + ts.sumBeta[iSex] += indTraitsSums.sumBeta[iSex]; + ts.ssqBeta[iSex] += indTraitsSums.ssqBeta[iSex]; + ts.sumDist1[iSex] += indTraitsSums.sumDist1[iSex]; + ts.ssqDist1[iSex] += indTraitsSums.ssqDist1[iSex]; + ts.sumDist2[iSex] += indTraitsSums.sumDist2[iSex]; + ts.ssqDist2[iSex] += indTraitsSums.ssqDist2[iSex]; + ts.sumProp1[iSex] += indTraitsSums.sumProp1[iSex]; + ts.ssqProp1[iSex] += indTraitsSums.ssqProp1[iSex]; + ts.sumDP[iSex] += indTraitsSums.sumDP[iSex]; + ts.ssqDP[iSex] += indTraitsSums.ssqDP[iSex]; + ts.sumGB[iSex] += indTraitsSums.sumGB[iSex]; + ts.ssqGB[iSex] += indTraitsSums.ssqGB[iSex]; + ts.sumAlphaDB[iSex] += indTraitsSums.sumAlphaDB[iSex]; + ts.ssqAlphaDB[iSex] += indTraitsSums.ssqAlphaDB[iSex]; + ts.sumBetaDB[iSex] += indTraitsSums.sumBetaDB[iSex]; + ts.ssqBetaDB[iSex] += indTraitsSums.ssqBetaDB[iSex]; + ts.sumStepL[iSex] += indTraitsSums.sumStepL[iSex]; + ts.ssqStepL[iSex] += indTraitsSums.ssqStepL[iSex]; + ts.sumRho[iSex] += indTraitsSums.sumRho[iSex]; + ts.ssqRho[iSex] += indTraitsSums.ssqRho[iSex]; + ts.sumS0[iSex] += indTraitsSums.sumS0[iSex]; + ts.ssqS0[iSex] += indTraitsSums.ssqS0[iSex]; + ts.sumAlphaS[iSex] += indTraitsSums.sumAlphaS[iSex]; + ts.ssqAlphaS[iSex] += indTraitsSums.ssqAlphaS[iSex]; + ts.sumBetaS[iSex] += indTraitsSums.sumBetaS[iSex]; + ts.ssqBetaS[iSex] += indTraitsSums.ssqBetaS[iSex]; + ts.sumGeneticFitness[iSex] += indTraitsSums.sumGeneticFitness[iSex]; + ts.ssqGeneticFitness[iSex] += indTraitsSums.ssqGeneticFitness[iSex]; + } + + // Produce trait-per-cell output + if (sim.outTraitsCells && yr % sim.outIntTraitCell == 0 + && !commlevel) { + outtraits << rep << "\t" << yr << "\t" << gen; if (land.patchModel) { outtraits << "\t" << pPatch->getPatchNum(); @@ -757,46 +792,34 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge locn loc = pPatch->getCellLocn(0); outtraits << "\t" << loc.x << "\t" << loc.y; } - } - if (emig.indVar) { - if (emig.sexDep) { // must be a sexual species - ploidy = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction - ploidy = 1; - } - else { // sexual reproduction - ploidy = 1; - } - } - double mnD0[2], mnAlpha[2], mnBeta[2], sdD0[2], sdAlpha[2], sdBeta[2]; - for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { - mnD0[whichChromosome] = mnAlpha[whichChromosome] = mnBeta[whichChromosome] = sdD0[whichChromosome] = sdAlpha[whichChromosome] = sdBeta[whichChromosome] = 0.0; - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - if (ploidy == 2) popsize = indTraitsSums.ninds[whichChromosome]; - else popsize = indTraitsSums.ninds[0] + indTraitsSums.ninds[1]; - if (popsize > 0) { - mnD0[whichChromosome] = indTraitsSums.sumD0[whichChromosome] / (double)popsize; - mnAlpha[whichChromosome] = indTraitsSums.sumAlpha[whichChromosome] / (double)popsize; - mnBeta[whichChromosome] = indTraitsSums.sumBeta[whichChromosome] / (double)popsize; - if (popsize > 1) { - sdD0[whichChromosome] = indTraitsSums.ssqD0[whichChromosome] / (double)popsize - mnD0[whichChromosome] * mnD0[whichChromosome]; - if (sdD0[whichChromosome] > 0.0) sdD0[whichChromosome] = sqrt(sdD0[whichChromosome]); else sdD0[whichChromosome] = 0.0; - sdAlpha[whichChromosome] = indTraitsSums.ssqAlpha[whichChromosome] / (double)popsize - mnAlpha[whichChromosome] * mnAlpha[whichChromosome]; - if (sdAlpha[whichChromosome] > 0.0) sdAlpha[whichChromosome] = sqrt(sdAlpha[whichChromosome]); else sdAlpha[whichChromosome] = 0.0; - sdBeta[whichChromosome] = indTraitsSums.ssqBeta[whichChromosome] / (double)popsize - mnBeta[whichChromosome] * mnBeta[whichChromosome]; - if (sdBeta[whichChromosome] > 0.0) sdBeta[whichChromosome] = sqrt(sdBeta[whichChromosome]); else sdBeta[whichChromosome] = 0.0; - } - else { - sdD0[whichChromosome] = sdAlpha[whichChromosome] = sdBeta[whichChromosome] = 0.0; - } - } - } - if (writefile) { + if (emig.indVar) { + if (emig.sexDep) { + vector mnD0(2, 0.0), mnAlpha(2, 0.0), mnBeta(2, 0.0), sdD0(2, 0.0), sdAlpha(2, 0.0), sdBeta(2, 0.0); + for (int sex = 0; sex < gMaxNbSexes; sex++) { + + double popsize = static_cast(indTraitsSums.ninds[sex]); + + if (popsize > 0) { + + mnD0[sex] = indTraitsSums.sumD0[sex] / popsize; + mnAlpha[sex] = indTraitsSums.sumAlpha[sex] / popsize; + mnBeta[sex] = indTraitsSums.sumBeta[sex] / popsize; + + if (popsize > 1) { + sdD0[sex] = indTraitsSums.ssqD0[sex] / popsize - mnD0[sex] * mnD0[sex]; + if (sdD0[sex] > 0.0) sdD0[sex] = sqrt(sdD0[sex]); else sdD0[sex] = 0.0; + sdAlpha[sex] = indTraitsSums.ssqAlpha[sex] / popsize - mnAlpha[sex] * mnAlpha[sex]; + if (sdAlpha[sex] > 0.0) sdAlpha[sex] = sqrt(sdAlpha[sex]); else sdAlpha[sex] = 0.0; + sdBeta[sex] = indTraitsSums.ssqBeta[sex] / popsize - mnBeta[sex] * mnBeta[sex]; + if (sdBeta[sex] > 0.0) sdBeta[sex] = sqrt(sdBeta[sex]); else sdBeta[sex] = 0.0; + } + else { + sdD0[sex] = sdAlpha[sex] = sdBeta[sex] = 0.0; + } + } + } outtraits << "\t" << mnD0[0] << "\t" << sdD0[0]; outtraits << "\t" << mnD0[1] << "\t" << sdD0[1]; if (emig.densDep) { @@ -806,75 +829,88 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge outtraits << "\t" << mnBeta[1] << "\t" << sdBeta[1]; } } - else { // sex-independent - outtraits << "\t" << mnD0[0] << "\t" << sdD0[0]; + else { // not sex-dependent + double mnD0 = 0, mnAlpha = 0, mnBeta = 0, popsize = 0; + double sdD0 = 0, sdAlpha = 0, sdBeta = 0; + for (int sex = 0; sex < gMaxNbSexes; sex++) { + mnD0 += indTraitsSums.sumD0[sex]; + mnAlpha += indTraitsSums.sumAlpha[sex]; + mnBeta += indTraitsSums.sumBeta[sex]; + popsize += indTraitsSums.ninds[sex]; + sdD0 += indTraitsSums.ssqD0[sex]; + sdAlpha += indTraitsSums.ssqAlpha[sex]; + sdBeta += indTraitsSums.ssqBeta[sex]; + } + mnD0 /= popsize; + mnAlpha /= popsize; + mnBeta /= popsize; + if (popsize > 1) { + sdD0 = sdD0 / popsize - mnD0 * mnD0; + sdAlpha = sdAlpha / popsize - mnAlpha * mnAlpha; + sdBeta = sdBeta / popsize - mnBeta * mnBeta; + sdD0 = sdD0 == 0.0 ? 0.0 : sqrt(sdD0); + sdAlpha = sdAlpha == 0.0 ? 0.0 : sqrt(sdAlpha); + sdBeta = sdBeta == 0.0 ? 0.0 : sqrt(sdBeta); + } + else { + sdD0 = 0.0; + sdAlpha = 0.0; + sdBeta = 0.0; + } + + outtraits << "\t" << mnD0 << "\t" << sdD0; if (emig.densDep) { - outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + outtraits << "\t" << mnAlpha << "\t" << sdAlpha; + outtraits << "\t" << mnBeta << "\t" << sdBeta; } } } - } - if (trfr.indVar) { - if (trfr.usesMovtProc) { - // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ploidy = 1; - } - else { - if (trfr.sexDep) { // must be a sexual species - ploidy = 2; - } - else { - ploidy = 1; - } - } - double mnDist1[2], mnDist2[2], mnProp1[2], mnStepL[2], mnRho[2]; - double sdDist1[2], sdDist2[2], sdProp1[2], sdStepL[2], sdRho[2]; - double mnDP[2], mnGB[2], mnAlphaDB[2], mnBetaDB[2]; - double sdDP[2], sdGB[2], sdAlphaDB[2], sdBetaDB[2]; - for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { - mnDist1[whichChromosome] = mnDist2[whichChromosome] = mnProp1[whichChromosome] = mnStepL[whichChromosome] = mnRho[whichChromosome] = 0.0; - sdDist1[whichChromosome] = sdDist2[whichChromosome] = sdProp1[whichChromosome] = sdStepL[whichChromosome] = sdRho[whichChromosome] = 0.0; - mnDP[whichChromosome] = mnGB[whichChromosome] = mnAlphaDB[whichChromosome] = mnBetaDB[whichChromosome] = 0.0; - sdDP[whichChromosome] = sdGB[whichChromosome] = sdAlphaDB[whichChromosome] = sdBetaDB[whichChromosome] = 0.0; - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - if (ploidy == 2) popsize = indTraitsSums.ninds[whichChromosome]; - else popsize = indTraitsSums.ninds[0] + indTraitsSums.ninds[1]; - if (popsize > 0) { - mnDist1[whichChromosome] = indTraitsSums.sumDist1[whichChromosome] / (double)popsize; - mnDist2[whichChromosome] = indTraitsSums.sumDist2[whichChromosome] / (double)popsize; - mnProp1[whichChromosome] = indTraitsSums.sumProp1[whichChromosome] / (double)popsize; - mnStepL[whichChromosome] = indTraitsSums.sumStepL[whichChromosome] / (double)popsize; - mnRho[whichChromosome] = indTraitsSums.sumRho[whichChromosome] / (double)popsize; - mnDP[whichChromosome] = indTraitsSums.sumDP[whichChromosome] / (double)popsize; - mnGB[whichChromosome] = indTraitsSums.sumGB[whichChromosome] / (double)popsize; - mnAlphaDB[whichChromosome] = indTraitsSums.sumAlphaDB[whichChromosome] / (double)popsize; - mnBetaDB[whichChromosome] = indTraitsSums.sumBetaDB[whichChromosome] / (double)popsize; - if (popsize > 1) { - sdDist1[whichChromosome] = indTraitsSums.ssqDist1[whichChromosome] / (double)popsize - mnDist1[whichChromosome] * mnDist1[whichChromosome]; - if (sdDist1[whichChromosome] > 0.0) sdDist1[whichChromosome] = sqrt(sdDist1[whichChromosome]); else sdDist1[whichChromosome] = 0.0; - sdDist2[whichChromosome] = indTraitsSums.ssqDist2[whichChromosome] / (double)popsize - mnDist2[whichChromosome] * mnDist2[whichChromosome]; - if (sdDist2[whichChromosome] > 0.0) sdDist2[whichChromosome] = sqrt(sdDist2[whichChromosome]); else sdDist2[whichChromosome] = 0.0; - sdProp1[whichChromosome] = indTraitsSums.ssqProp1[whichChromosome] / (double)popsize - mnProp1[whichChromosome] * mnProp1[whichChromosome]; - if (sdProp1[whichChromosome] > 0.0) sdProp1[whichChromosome] = sqrt(sdProp1[whichChromosome]); else sdProp1[whichChromosome] = 0.0; - sdStepL[whichChromosome] = indTraitsSums.ssqStepL[whichChromosome] / (double)popsize - mnStepL[whichChromosome] * mnStepL[whichChromosome]; - if (sdStepL[whichChromosome] > 0.0) sdStepL[whichChromosome] = sqrt(sdStepL[whichChromosome]); else sdStepL[whichChromosome] = 0.0; - sdRho[whichChromosome] = indTraitsSums.ssqRho[whichChromosome] / (double)popsize - mnRho[whichChromosome] * mnRho[whichChromosome]; - if (sdRho[whichChromosome] > 0.0) sdRho[whichChromosome] = sqrt(sdRho[whichChromosome]); else sdRho[whichChromosome] = 0.0; - sdDP[whichChromosome] = indTraitsSums.ssqDP[whichChromosome] / (double)popsize - mnDP[whichChromosome] * mnDP[whichChromosome]; - if (sdDP[whichChromosome] > 0.0) sdDP[whichChromosome] = sqrt(sdDP[whichChromosome]); else sdDP[whichChromosome] = 0.0; - sdGB[whichChromosome] = indTraitsSums.ssqGB[whichChromosome] / (double)popsize - mnGB[whichChromosome] * mnGB[whichChromosome]; - if (sdGB[whichChromosome] > 0.0) sdGB[whichChromosome] = sqrt(sdGB[whichChromosome]); else sdGB[whichChromosome] = 0.0; - sdAlphaDB[whichChromosome] = indTraitsSums.ssqAlphaDB[whichChromosome] / (double)popsize - mnAlphaDB[whichChromosome] * mnAlphaDB[whichChromosome]; - if (sdAlphaDB[whichChromosome] > 0.0) sdAlphaDB[whichChromosome] = sqrt(sdAlphaDB[whichChromosome]); else sdAlphaDB[whichChromosome] = 0.0; - sdBetaDB[whichChromosome] = indTraitsSums.ssqBetaDB[whichChromosome] / (double)popsize - mnBetaDB[whichChromosome] * mnBetaDB[whichChromosome]; - if (sdBetaDB[whichChromosome] > 0.0) sdBetaDB[whichChromosome] = sqrt(sdBetaDB[whichChromosome]); else sdBetaDB[whichChromosome] = 0.0; + if (trfr.indVar) { + + vector mnDist1(2, 0.0), mnDist2(2, 0.0), mnProp1(2, 0.0), mnStepL(2, 0.0), mnRho(2, 0.0); + vector sdDist1(2, 0.0), sdDist2(2, 0.0), sdProp1(2, 0.0), sdStepL(2, 0.0), sdRho(2, 0.0); + vector mnDP(2, 0.0), mnGB(2, 0.0), mnAlphaDB(2, 0.0), mnBetaDB(2, 0.0); + vector sdDP(2, 0.0), sdGB(2, 0.0), sdAlphaDB(2, 0.0), sdBetaDB(2, 0.0); + + for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { + + // individuals may have been counted by sex if there was + // sex dependency in another dispersal phase + double popsize = static_cast(indTraitsSums.ninds[sex]); + + if (popsize > 0) { + mnDist1[sex] = indTraitsSums.sumDist1[sex] / popsize; + mnDist2[sex] = indTraitsSums.sumDist2[sex] / popsize; + mnProp1[sex] = indTraitsSums.sumProp1[sex] / popsize; + mnStepL[sex] = indTraitsSums.sumStepL[sex] / popsize; + mnRho[sex] = indTraitsSums.sumRho[sex] / popsize; + mnDP[sex] = indTraitsSums.sumDP[sex] / popsize; + mnGB[sex] = indTraitsSums.sumGB[sex] / popsize; + mnAlphaDB[sex] = indTraitsSums.sumAlphaDB[sex] / popsize; + mnBetaDB[sex] = indTraitsSums.sumBetaDB[sex] / popsize; + if (popsize > 1) { + sdDist1[sex] = indTraitsSums.ssqDist1[sex] / popsize - mnDist1[sex] * mnDist1[sex]; + if (sdDist1[sex] > 0.0) sdDist1[sex] = sqrt(sdDist1[sex]); else sdDist1[sex] = 0.0; + sdDist2[sex] = indTraitsSums.ssqDist2[sex] / popsize - mnDist2[sex] * mnDist2[sex]; + if (sdDist2[sex] > 0.0) sdDist2[sex] = sqrt(sdDist2[sex]); else sdDist2[sex] = 0.0; + sdProp1[sex] = indTraitsSums.ssqProp1[sex] / popsize - mnProp1[sex] * mnProp1[sex]; + if (sdProp1[sex] > 0.0) sdProp1[sex] = sqrt(sdProp1[sex]); else sdProp1[sex] = 0.0; + sdStepL[sex] = indTraitsSums.ssqStepL[sex] / popsize - mnStepL[sex] * mnStepL[sex]; + if (sdStepL[sex] > 0.0) sdStepL[sex] = sqrt(sdStepL[sex]); else sdStepL[sex] = 0.0; + sdRho[sex] = indTraitsSums.ssqRho[sex] / popsize - mnRho[sex] * mnRho[sex]; + if (sdRho[sex] > 0.0) sdRho[sex] = sqrt(sdRho[sex]); else sdRho[sex] = 0.0; + sdDP[sex] = indTraitsSums.ssqDP[sex] / popsize - mnDP[sex] * mnDP[sex]; + if (sdDP[sex] > 0.0) sdDP[sex] = sqrt(sdDP[sex]); else sdDP[sex] = 0.0; + sdGB[sex] = indTraitsSums.ssqGB[sex] / popsize - mnGB[sex] * mnGB[sex]; + if (sdGB[sex] > 0.0) sdGB[sex] = sqrt(sdGB[sex]); else sdGB[sex] = 0.0; + sdAlphaDB[sex] = indTraitsSums.ssqAlphaDB[sex] / popsize - mnAlphaDB[sex] * mnAlphaDB[sex]; + if (sdAlphaDB[sex] > 0.0) sdAlphaDB[sex] = sqrt(sdAlphaDB[sex]); else sdAlphaDB[sex] = 0.0; + sdBetaDB[sex] = indTraitsSums.ssqBetaDB[sex] / popsize - mnBetaDB[sex] * mnBetaDB[sex]; + if (sdBetaDB[sex] > 0.0) sdBetaDB[sex] = sqrt(sdBetaDB[sex]); else sdBetaDB[sex] = 0.0; + } } } - } - if (writefile) { if (trfr.usesMovtProc) { if (trfr.moveType == 1) { outtraits << "\t" << mnDP[0] << "\t" << sdDP[0]; @@ -909,49 +945,36 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge } } } - } - if (sett.indVar) { - if (sett.sexDep) { // must be a sexual species - ploidy = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction - ploidy = 1; - } - else { // sexual reproduction - ploidy = 1; - } - } - // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - double mnS0[2], mnAlpha[2], mnBeta[2], sdS0[2], sdAlpha[2], sdBeta[2]; - for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { - mnS0[whichChromosome] = mnAlpha[whichChromosome] = mnBeta[whichChromosome] = sdS0[whichChromosome] = sdAlpha[whichChromosome] = sdBeta[whichChromosome] = 0.0; - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - if (ploidy == 2) popsize = indTraitsSums.ninds[whichChromosome]; - else popsize = indTraitsSums.ninds[0] + indTraitsSums.ninds[1]; - - if (popsize > 0) { - - mnS0[whichChromosome] = indTraitsSums.sumS0[whichChromosome] / (double)popsize; - mnAlpha[whichChromosome] = indTraitsSums.sumAlphaS[whichChromosome] / (double)popsize; - mnBeta[whichChromosome] = indTraitsSums.sumBetaS[whichChromosome] / (double)popsize; - - if (popsize > 1) { - sdS0[whichChromosome] = indTraitsSums.ssqS0[whichChromosome] / (double)popsize - mnS0[whichChromosome] * mnS0[whichChromosome]; - if (sdS0[whichChromosome] > 0.0) sdS0[whichChromosome] = sqrt(sdS0[whichChromosome]); else sdS0[whichChromosome] = 0.0; - sdAlpha[whichChromosome] = indTraitsSums.ssqAlphaS[whichChromosome] / (double)popsize - mnAlpha[whichChromosome] * mnAlpha[whichChromosome]; - if (sdAlpha[whichChromosome] > 0.0) sdAlpha[whichChromosome] = sqrt(sdAlpha[whichChromosome]); else sdAlpha[whichChromosome] = 0.0; - sdBeta[whichChromosome] = indTraitsSums.ssqBetaS[whichChromosome] / (double)popsize - mnBeta[whichChromosome] * mnBeta[whichChromosome]; - if (sdBeta[whichChromosome] > 0.0) sdBeta[whichChromosome] = sqrt(sdBeta[whichChromosome]); else sdBeta[whichChromosome] = 0.0; - } - else { - sdS0[whichChromosome] = sdAlpha[whichChromosome] = sdBeta[whichChromosome] = 0.0; + if (sett.indVar) { + + vector mnS0(2, 0.0), mnAlpha(2, 0.0), mnBeta(2, 0.0), sdS0(2, 0.0), sdAlpha(2, 0.0), sdBeta(2, 0.0); + + for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { + + // individuals may have been counted by sex if there was + // sex dependency in another dispersal phase + double popsize = static_cast(indTraitsSums.ninds[sex]); + + if (popsize > 0) { + + mnS0[sex] = indTraitsSums.sumS0[sex] / popsize; + mnAlpha[sex] = indTraitsSums.sumAlphaS[sex] / popsize; + mnBeta[sex] = indTraitsSums.sumBetaS[sex] / popsize; + + if (popsize > 1) { + sdS0[sex] = indTraitsSums.ssqS0[sex] / popsize - mnS0[sex] * mnS0[sex]; + if (sdS0[sex] > 0.0) sdS0[sex] = sqrt(sdS0[sex]); else sdS0[sex] = 0.0; + sdAlpha[sex] = indTraitsSums.ssqAlphaS[sex] / popsize - mnAlpha[sex] * mnAlpha[sex]; + if (sdAlpha[sex] > 0.0) sdAlpha[sex] = sqrt(sdAlpha[sex]); else sdAlpha[sex] = 0.0; + sdBeta[sex] = indTraitsSums.ssqBetaS[sex] / popsize - mnBeta[sex] * mnBeta[sex]; + if (sdBeta[sex] > 0.0) sdBeta[sex] = sqrt(sdBeta[sex]); else sdBeta[sex] = 0.0; + } + else { + sdS0[sex] = sdAlpha[sex] = sdBeta[sex] = 0.0; + } } } - } - if (writefile) { if (sett.sexDep) { outtraits << "\t" << mnS0[0] << "\t" << sdS0[0]; outtraits << "\t" << mnS0[1] << "\t" << sdS0[1]; @@ -966,34 +989,31 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; } } - } - - // Genetic load - if (pSpecies->getNbGenLoadTraits() > 0) { - ploidy = pSpecies->isDiploid() + 1; - double mnGenFitness[2], sdGenFitness[2]; + // Genetic load + if (pSpecies->getNbGenLoadTraits() > 0) { - for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { - mnGenFitness[whichChromosome] = sdGenFitness[whichChromosome] = 0.0; + ploidy = pSpecies->isDiploid() + 1; + vector mnGenFitness(2, 0.0), sdGenFitness(2, 0.0); - if (ploidy == 2) popsize = indTraitsSums.ninds[whichChromosome]; - else popsize = indTraitsSums.ninds[0] + indTraitsSums.ninds[1]; + for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { - if (popsize > 0) { + double popsize = static_cast(indTraitsSums.ninds[sex]); - mnGenFitness[whichChromosome] = indTraitsSums.sumGeneticFitness[whichChromosome] / (double)popsize; + mnGenFitness[sex] = indTraitsSums.sumGeneticFitness[sex] + / popsize; if (popsize > 1) { - sdGenFitness[whichChromosome] = indTraitsSums.ssqGeneticFitness[whichChromosome] / (double)popsize - mnGenFitness[whichChromosome] * mnGenFitness[whichChromosome]; - if (sdGenFitness[whichChromosome] > 0.0) sdGenFitness[whichChromosome] = sqrt(sdGenFitness[whichChromosome]); else sdGenFitness[whichChromosome] = 0.0; + sdGenFitness[sex] = indTraitsSums.ssqGeneticFitness[sex] + / popsize - mnGenFitness[sex] + * mnGenFitness[sex]; + if (sdGenFitness[sex] > 0.0) sdGenFitness[sex] = sqrt(sdGenFitness[sex]); + else sdGenFitness[sex] = 0.0; } else { - sdGenFitness[whichChromosome] = 0.0; + sdGenFitness[sex] = 0.0; } } - } - if (writefile) { if (pSpecies->getDemogrParams().repType > 0) { outtraits << "\t" << mnGenFitness[0] << "\t" << sdGenFitness[0]; outtraits << "\t" << mnGenFitness[1] << "\t" << sdGenFitness[1]; @@ -1002,48 +1022,11 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge outtraits << "\t" << mnGenFitness[0] << "\t" << sdGenFitness[0]; } } - } + outtraits << endl; + } // end trait-per-cell output - // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - if (writefile) outtraits << endl; - - for (int iSex = 0; iSex < gMaxNbSexes; iSex++) { - ts.ninds[iSex] += indTraitsSums.ninds[iSex]; - ts.sumD0[iSex] += indTraitsSums.sumD0[iSex]; - ts.ssqD0[iSex] += indTraitsSums.ssqD0[iSex]; - ts.sumAlpha[iSex] += indTraitsSums.sumAlpha[iSex]; - ts.ssqAlpha[iSex] += indTraitsSums.ssqAlpha[iSex]; - ts.sumBeta[iSex] += indTraitsSums.sumBeta[iSex]; - ts.ssqBeta[iSex] += indTraitsSums.ssqBeta[iSex]; - ts.sumDist1[iSex] += indTraitsSums.sumDist1[iSex]; - ts.ssqDist1[iSex] += indTraitsSums.ssqDist1[iSex]; - ts.sumDist2[iSex] += indTraitsSums.sumDist2[iSex]; - ts.ssqDist2[iSex] += indTraitsSums.ssqDist2[iSex]; - ts.sumProp1[iSex] += indTraitsSums.sumProp1[iSex]; - ts.ssqProp1[iSex] += indTraitsSums.ssqProp1[iSex]; - ts.sumDP[iSex] += indTraitsSums.sumDP[iSex]; - ts.ssqDP[iSex] += indTraitsSums.ssqDP[iSex]; - ts.sumGB[iSex] += indTraitsSums.sumGB[iSex]; - ts.ssqGB[iSex] += indTraitsSums.ssqGB[iSex]; - ts.sumAlphaDB[iSex] += indTraitsSums.sumAlphaDB[iSex]; - ts.ssqAlphaDB[iSex] += indTraitsSums.ssqAlphaDB[iSex]; - ts.sumBetaDB[iSex] += indTraitsSums.sumBetaDB[iSex]; - ts.ssqBetaDB[iSex] += indTraitsSums.ssqBetaDB[iSex]; - ts.sumStepL[iSex] += indTraitsSums.sumStepL[iSex]; - ts.ssqStepL[iSex] += indTraitsSums.ssqStepL[iSex]; - ts.sumRho[iSex] += indTraitsSums.sumRho[iSex]; - ts.ssqRho[iSex] += indTraitsSums.ssqRho[iSex]; - ts.sumS0[iSex] += indTraitsSums.sumS0[iSex]; - ts.ssqS0[iSex] += indTraitsSums.ssqS0[iSex]; - ts.sumAlphaS[iSex] += indTraitsSums.sumAlphaS[iSex]; - ts.ssqAlphaS[iSex] += indTraitsSums.ssqAlphaS[iSex]; - ts.sumBetaS[iSex] += indTraitsSums.sumBetaS[iSex]; - ts.ssqBetaS[iSex] += indTraitsSums.ssqBetaS[iSex]; - ts.sumGeneticFitness[iSex] += indTraitsSums.sumGeneticFitness[iSex]; - ts.ssqGeneticFitness[iSex] += indTraitsSums.ssqGeneticFitness[iSex]; - } - } - } + } + } // end population loop return ts; } From 3b010f744e019e32013fa521a5db5639eea515d3 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 25 Apr 2025 16:24:06 +0100 Subject: [PATCH 303/332] settlement and genetic load per cell trait refactor --- SubCommunity.cpp | 131 ++++++++++++++++++++++++++++++----------------- 1 file changed, 85 insertions(+), 46 deletions(-) diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 5292c2d..03b5a5d 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -948,34 +948,36 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge if (sett.indVar) { - vector mnS0(2, 0.0), mnAlpha(2, 0.0), mnBeta(2, 0.0), sdS0(2, 0.0), sdAlpha(2, 0.0), sdBeta(2, 0.0); + if (sett.sexDep) { - for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { + vector mnS0(2, 0.0), mnAlpha(2, 0.0), mnBeta(2, 0.0), sdS0(2, 0.0), sdAlpha(2, 0.0), sdBeta(2, 0.0); - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - double popsize = static_cast(indTraitsSums.ninds[sex]); + for (int sex = 0; sex < gMaxNbSexes; sex++) { - if (popsize > 0) { + // individuals may have been counted by sex if there was + // sex dependency in another dispersal phase + double popsize = static_cast(indTraitsSums.ninds[sex]); - mnS0[sex] = indTraitsSums.sumS0[sex] / popsize; - mnAlpha[sex] = indTraitsSums.sumAlphaS[sex] / popsize; - mnBeta[sex] = indTraitsSums.sumBetaS[sex] / popsize; + if (popsize > 0) { - if (popsize > 1) { - sdS0[sex] = indTraitsSums.ssqS0[sex] / popsize - mnS0[sex] * mnS0[sex]; - if (sdS0[sex] > 0.0) sdS0[sex] = sqrt(sdS0[sex]); else sdS0[sex] = 0.0; - sdAlpha[sex] = indTraitsSums.ssqAlphaS[sex] / popsize - mnAlpha[sex] * mnAlpha[sex]; - if (sdAlpha[sex] > 0.0) sdAlpha[sex] = sqrt(sdAlpha[sex]); else sdAlpha[sex] = 0.0; - sdBeta[sex] = indTraitsSums.ssqBetaS[sex] / popsize - mnBeta[sex] * mnBeta[sex]; - if (sdBeta[sex] > 0.0) sdBeta[sex] = sqrt(sdBeta[sex]); else sdBeta[sex] = 0.0; - } - else { - sdS0[sex] = sdAlpha[sex] = sdBeta[sex] = 0.0; + mnS0[sex] = indTraitsSums.sumS0[sex] / popsize; + mnAlpha[sex] = indTraitsSums.sumAlphaS[sex] / popsize; + mnBeta[sex] = indTraitsSums.sumBetaS[sex] / popsize; + + if (popsize > 1) { + sdS0[sex] = indTraitsSums.ssqS0[sex] / popsize - mnS0[sex] * mnS0[sex]; + if (sdS0[sex] > 0.0) sdS0[sex] = sqrt(sdS0[sex]); else sdS0[sex] = 0.0; + sdAlpha[sex] = indTraitsSums.ssqAlphaS[sex] / popsize - mnAlpha[sex] * mnAlpha[sex]; + if (sdAlpha[sex] > 0.0) sdAlpha[sex] = sqrt(sdAlpha[sex]); else sdAlpha[sex] = 0.0; + sdBeta[sex] = indTraitsSums.ssqBetaS[sex] / popsize - mnBeta[sex] * mnBeta[sex]; + if (sdBeta[sex] > 0.0) sdBeta[sex] = sqrt(sdBeta[sex]); else sdBeta[sex] = 0.0; + } + else { + sdS0[sex] = sdAlpha[sex] = sdBeta[sex] = 0.0; + } } } - } - if (sett.sexDep) { + outtraits << "\t" << mnS0[0] << "\t" << sdS0[0]; outtraits << "\t" << mnS0[1] << "\t" << sdS0[1]; outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; @@ -984,42 +986,79 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge outtraits << "\t" << mnBeta[1] << "\t" << sdBeta[1]; } else { // sex-independent - outtraits << "\t" << mnS0[0] << "\t" << sdS0[0]; - outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + double mnS0 = 0, mnAlpha = 0, mnBeta = 0, popsize = 0; + double sdS0 = 0, sdAlpha = 0, sdBeta = 0; + for (int sex = 0; sex < gMaxNbSexes; sex++) { + mnS0 += indTraitsSums.sumS0[sex]; + mnAlpha += indTraitsSums.sumAlphaS[sex]; + mnBeta += indTraitsSums.sumBetaS[sex]; + popsize += indTraitsSums.ninds[sex]; + sdS0 += indTraitsSums.ssqS0[sex]; + sdAlpha += indTraitsSums.ssqAlphaS[sex]; + sdBeta += indTraitsSums.ssqBetaS[sex]; + } + mnS0 /= popsize; + mnAlpha /= popsize; + mnBeta /= popsize; + if (popsize > 1) { + sdS0 = sdS0 / popsize - mnS0 * mnS0; + sdAlpha = sdAlpha / popsize - mnAlpha * mnAlpha; + sdBeta = sdBeta / popsize - mnBeta * mnBeta; + sdS0 = sdS0 == 0.0 ? 0.0 : sqrt(sdS0); + sdAlpha = sdAlpha == 0.0 ? 0.0 : sqrt(sdAlpha); + sdBeta = sdBeta == 0.0 ? 0.0 : sqrt(sdBeta); + } + else { + sdS0 = 0.0; + sdAlpha = 0.0; + sdBeta = 0.0; + } + outtraits << "\t" << mnS0 << "\t" << sdS0; + outtraits << "\t" << mnAlpha << "\t" << sdAlpha; + outtraits << "\t" << mnBeta << "\t" << sdBeta; } } // Genetic load if (pSpecies->getNbGenLoadTraits() > 0) { - ploidy = pSpecies->isDiploid() + 1; - vector mnGenFitness(2, 0.0), sdGenFitness(2, 0.0); + if (pSpecies->getDemogrParams().repType > 0) { // sexual model + vector mnGenFitness(2, 0.0), sdGenFitness(2, 0.0); - for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { - - double popsize = static_cast(indTraitsSums.ninds[sex]); - - mnGenFitness[sex] = indTraitsSums.sumGeneticFitness[sex] - / popsize; - if (popsize > 1) { - sdGenFitness[sex] = indTraitsSums.ssqGeneticFitness[sex] - / popsize - mnGenFitness[sex] - * mnGenFitness[sex]; - if (sdGenFitness[sex] > 0.0) sdGenFitness[sex] = sqrt(sdGenFitness[sex]); - else sdGenFitness[sex] = 0.0; - } - else { - sdGenFitness[sex] = 0.0; + for (int sex = 0; sex < gMaxNbSexes; sex++) { + double popsize = static_cast(indTraitsSums.ninds[sex]); + mnGenFitness[sex] = indTraitsSums.sumGeneticFitness[sex] + / popsize; + if (popsize > 1) { + sdGenFitness[sex] = indTraitsSums.ssqGeneticFitness[sex] + / popsize - mnGenFitness[sex] + * mnGenFitness[sex]; + if (sdGenFitness[sex] > 0.0) + sdGenFitness[sex] = sqrt(sdGenFitness[sex]); + else sdGenFitness[sex] = 0.0; + } + else { + sdGenFitness[sex] = 0.0; + } } - } - - if (pSpecies->getDemogrParams().repType > 0) { outtraits << "\t" << mnGenFitness[0] << "\t" << sdGenFitness[0]; outtraits << "\t" << mnGenFitness[1] << "\t" << sdGenFitness[1]; } - else { // sex-independent - outtraits << "\t" << mnGenFitness[0] << "\t" << sdGenFitness[0]; + else { // asexual + + double mnGenFitness = 0.0, popsize = 0.0, sdGenFitness= 0.0; + for (int sex = 0; sex < gMaxNbSexes; sex++) { + mnGenFitness += indTraitsSums.sumGeneticFitness[sex]; + popsize += indTraitsSums.ninds[sex]; + sdGenFitness += indTraitsSums.ssqGeneticFitness[sex]; + } + mnGenFitness /= popsize; + if (popsize > 1) { + sdGenFitness = sdGenFitness / popsize - mnGenFitness * mnGenFitness; + sdGenFitness = sdGenFitness == 0.0 ? 0.0 : sqrt(sdGenFitness); + } + else sdGenFitness = 0.0; + outtraits << "\t" << mnGenFitness << "\t" << sdGenFitness; } } outtraits << endl; From ea64bb5b527482874c2783cd207ee5581ba48f49 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 25 Apr 2025 17:11:22 +0100 Subject: [PATCH 304/332] refactor transfer --- SubCommunity.cpp | 179 +++++++++++++++++++++++++++++++---------------- 1 file changed, 120 insertions(+), 59 deletions(-) diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 03b5a5d..f85c710 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -794,7 +794,6 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge } if (emig.indVar) { - if (emig.sexDep) { vector mnD0(2, 0.0), mnAlpha(2, 0.0), mnBeta(2, 0.0), sdD0(2, 0.0), sdAlpha(2, 0.0), sdBeta(2, 0.0); for (int sex = 0; sex < gMaxNbSexes; sex++) { @@ -868,67 +867,103 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge if (trfr.indVar) { - vector mnDist1(2, 0.0), mnDist2(2, 0.0), mnProp1(2, 0.0), mnStepL(2, 0.0), mnRho(2, 0.0); - vector sdDist1(2, 0.0), sdDist2(2, 0.0), sdProp1(2, 0.0), sdStepL(2, 0.0), sdRho(2, 0.0); - vector mnDP(2, 0.0), mnGB(2, 0.0), mnAlphaDB(2, 0.0), mnBetaDB(2, 0.0); - vector sdDP(2, 0.0), sdGB(2, 0.0), sdAlphaDB(2, 0.0), sdBetaDB(2, 0.0); - - for (int whichChromosome = 0; whichChromosome < ploidy; whichChromosome++) { - - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - double popsize = static_cast(indTraitsSums.ninds[sex]); - - if (popsize > 0) { - mnDist1[sex] = indTraitsSums.sumDist1[sex] / popsize; - mnDist2[sex] = indTraitsSums.sumDist2[sex] / popsize; - mnProp1[sex] = indTraitsSums.sumProp1[sex] / popsize; - mnStepL[sex] = indTraitsSums.sumStepL[sex] / popsize; - mnRho[sex] = indTraitsSums.sumRho[sex] / popsize; - mnDP[sex] = indTraitsSums.sumDP[sex] / popsize; - mnGB[sex] = indTraitsSums.sumGB[sex] / popsize; - mnAlphaDB[sex] = indTraitsSums.sumAlphaDB[sex] / popsize; - mnBetaDB[sex] = indTraitsSums.sumBetaDB[sex] / popsize; + if (trfr.usesMovtProc) { // not sex-dependent + if (trfr.moveType == 1) { // SMS + double mnDP = 0.0, mnGB = 0.0, mnAlphaDB = 0.0, mnBetaDB = 0.0; + double sdDP = 0.0, sdGB = 0.0, sdAlphaDB = 0.0, sdBetaDB = 0.0; + double popsize = 0.0; + for (int sex = 0; sex < gMaxNbSexes; sex++) { + mnDP += indTraitsSums.sumDP[sex]; + mnGB += indTraitsSums.sumGB[sex]; + mnAlphaDB += indTraitsSums.sumAlphaDB[sex]; + mnBetaDB+= indTraitsSums.sumBetaDB[sex]; + popsize += indTraitsSums.ninds[sex]; + sdDP += indTraitsSums.ssqDP[sex]; + sdGB += indTraitsSums.ssqGB[sex]; + sdAlphaDB += indTraitsSums.ssqAlphaDB[sex]; + sdBetaDB += indTraitsSums.ssqBetaDB[sex]; + } + mnDP /= popsize; + mnGB /= popsize; + mnAlphaDB /= popsize; + mnBetaDB /= popsize; if (popsize > 1) { - sdDist1[sex] = indTraitsSums.ssqDist1[sex] / popsize - mnDist1[sex] * mnDist1[sex]; - if (sdDist1[sex] > 0.0) sdDist1[sex] = sqrt(sdDist1[sex]); else sdDist1[sex] = 0.0; - sdDist2[sex] = indTraitsSums.ssqDist2[sex] / popsize - mnDist2[sex] * mnDist2[sex]; - if (sdDist2[sex] > 0.0) sdDist2[sex] = sqrt(sdDist2[sex]); else sdDist2[sex] = 0.0; - sdProp1[sex] = indTraitsSums.ssqProp1[sex] / popsize - mnProp1[sex] * mnProp1[sex]; - if (sdProp1[sex] > 0.0) sdProp1[sex] = sqrt(sdProp1[sex]); else sdProp1[sex] = 0.0; - sdStepL[sex] = indTraitsSums.ssqStepL[sex] / popsize - mnStepL[sex] * mnStepL[sex]; - if (sdStepL[sex] > 0.0) sdStepL[sex] = sqrt(sdStepL[sex]); else sdStepL[sex] = 0.0; - sdRho[sex] = indTraitsSums.ssqRho[sex] / popsize - mnRho[sex] * mnRho[sex]; - if (sdRho[sex] > 0.0) sdRho[sex] = sqrt(sdRho[sex]); else sdRho[sex] = 0.0; - sdDP[sex] = indTraitsSums.ssqDP[sex] / popsize - mnDP[sex] * mnDP[sex]; - if (sdDP[sex] > 0.0) sdDP[sex] = sqrt(sdDP[sex]); else sdDP[sex] = 0.0; - sdGB[sex] = indTraitsSums.ssqGB[sex] / popsize - mnGB[sex] * mnGB[sex]; - if (sdGB[sex] > 0.0) sdGB[sex] = sqrt(sdGB[sex]); else sdGB[sex] = 0.0; - sdAlphaDB[sex] = indTraitsSums.ssqAlphaDB[sex] / popsize - mnAlphaDB[sex] * mnAlphaDB[sex]; - if (sdAlphaDB[sex] > 0.0) sdAlphaDB[sex] = sqrt(sdAlphaDB[sex]); else sdAlphaDB[sex] = 0.0; - sdBetaDB[sex] = indTraitsSums.ssqBetaDB[sex] / popsize - mnBetaDB[sex] * mnBetaDB[sex]; - if (sdBetaDB[sex] > 0.0) sdBetaDB[sex] = sqrt(sdBetaDB[sex]); else sdBetaDB[sex] = 0.0; + sdDP = sdDP / popsize - mnDP * mnDP; + sdGB = sdGB / popsize - mnGB * mnGB; + sdAlphaDB = sdAlphaDB / popsize - mnAlphaDB * mnAlphaDB; + sdBetaDB = sdBetaDB / popsize - mnBetaDB * mnBetaDB; + sdDP = sdDP == 0.0 ? 0.0 : sqrt(sdDP); + sdGB = sdGB == 0.0 ? 0.0 : sqrt(sdGB); + sdAlphaDB = sdAlphaDB == 0.0 ? 0.0 : sqrt(sdAlphaDB); + sdBetaDB = sdBetaDB == 0.0 ? 0.0 : sqrt(sdBetaDB); } + else { + sdDP = 0.0; + sdGB = 0.0; + sdAlphaDB = 0.0; + sdBetaDB = 0.0; + } + outtraits << "\t" << mnDP << "\t" << sdDP; + outtraits << "\t" << mnGB << "\t" << sdGB; + outtraits << "\t" << mnAlphaDB << "\t" << sdAlphaDB; + outtraits << "\t" << mnBetaDB << "\t" << sdBetaDB; } - } - if (trfr.usesMovtProc) { - if (trfr.moveType == 1) { - outtraits << "\t" << mnDP[0] << "\t" << sdDP[0]; - outtraits << "\t" << mnGB[0] << "\t" << sdGB[0]; - outtraits << "\t" << mnAlphaDB[0] << "\t" << sdAlphaDB[0]; - outtraits << "\t" << mnBetaDB[0] << "\t" << sdBetaDB[0]; - } - if (trfr.moveType == 2) { - outtraits << "\t" << mnStepL[0] << "\t" << sdStepL[0]; - outtraits << "\t" << mnRho[0] << "\t" << sdRho[0]; + if (trfr.moveType == 2) { // CRW + double mnStepL = 0.0, mnRho = 0.0, sdStepL = 0.0, sdRho = 0.0; + double popsize = 0.0; + for (int sex = 0; sex < gMaxNbSexes; sex++) { + mnStepL += indTraitsSums.sumStepL[sex]; + mnRho += indTraitsSums.sumRho[sex]; + popsize += indTraitsSums.ninds[sex]; + sdStepL += indTraitsSums.ssqStepL[sex]; + sdRho += indTraitsSums.ssqRho[sex]; + } + mnStepL /= popsize; + mnRho /= popsize; + if (popsize > 1) { + sdStepL = sdStepL / popsize - mnStepL * mnStepL; + sdRho = sdRho / popsize - mnRho * mnRho; + sdStepL = sdStepL == 0.0 ? 0.0 : sqrt(sdStepL); + sdRho = sdRho == 0.0 ? 0.0 : sqrt(sdRho); + } + else { + sdStepL = 0.0; + sdRho = 0.0; + } + outtraits << "\t" << mnStepL << "\t" << sdStepL; + outtraits << "\t" << mnRho << "\t" << sdRho; } } - else { + else { // kernels if (trfr.sexDep) { + + vector mnDist1(2, 0.0), mnDist2(2, 0.0), mnProp1(2, 0.0), mnStepL(2, 0.0), mnRho(2, 0.0); + vector sdDist1(2, 0.0), sdDist2(2, 0.0), sdProp1(2, 0.0), sdStepL(2, 0.0), sdRho(2, 0.0); + + for (int sex = 0; sex < gMaxNbSexes; sex++) { + + // individuals may have been counted by sex if there was + // sex dependency in another dispersal phase + double popsize = static_cast(indTraitsSums.ninds[sex]); + + if (popsize > 0) { + mnDist1[sex] = indTraitsSums.sumDist1[sex] / popsize; + mnDist2[sex] = indTraitsSums.sumDist2[sex] / popsize; + mnProp1[sex] = indTraitsSums.sumProp1[sex] / popsize; + if (popsize > 1) { + sdDist1[sex] = indTraitsSums.ssqDist1[sex] / popsize - mnDist1[sex] * mnDist1[sex]; + if (sdDist1[sex] > 0.0) sdDist1[sex] = sqrt(sdDist1[sex]); else sdDist1[sex] = 0.0; + sdDist2[sex] = indTraitsSums.ssqDist2[sex] / popsize - mnDist2[sex] * mnDist2[sex]; + if (sdDist2[sex] > 0.0) sdDist2[sex] = sqrt(sdDist2[sex]); else sdDist2[sex] = 0.0; + sdProp1[sex] = indTraitsSums.ssqProp1[sex] / popsize - mnProp1[sex] * mnProp1[sex]; + if (sdProp1[sex] > 0.0) sdProp1[sex] = sqrt(sdProp1[sex]); else sdProp1[sex] = 0.0; + sdStepL[sex] = indTraitsSums.ssqStepL[sex] / popsize - mnStepL[sex] * mnStepL[sex]; + } + } + } outtraits << "\t" << mnDist1[0] << "\t" << sdDist1[0]; outtraits << "\t" << mnDist1[1] << "\t" << sdDist1[1]; - if (trfr.twinKern) - { + if (trfr.twinKern) { outtraits << "\t" << mnDist2[0] << "\t" << sdDist2[0]; outtraits << "\t" << mnDist2[1] << "\t" << sdDist2[1]; outtraits << "\t" << mnProp1[0] << "\t" << sdProp1[0]; @@ -936,11 +971,37 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge } } else { // sex-independent - outtraits << "\t" << mnDist1[0] << "\t" << sdDist1[0]; - if (trfr.twinKern) - { - outtraits << "\t" << mnDist2[0] << "\t" << sdDist2[0]; - outtraits << "\t" << mnProp1[0] << "\t" << sdProp1[0]; + double mnDist1 = 0.0, mnDist2 = 0.0, mnProp1 = 0.0, popsize = 0.0; + double sdDist1 = 0.0, sdDist2 = 0.0, sdProp1 = 0.0; + for (int sex = 0; sex < gMaxNbSexes; sex++) { + mnDist1 += indTraitsSums.sumDist1[sex]; + mnDist2 += indTraitsSums.sumDist2[sex]; + mnProp1 += indTraitsSums.sumProp1[sex]; + popsize += indTraitsSums.ninds[sex]; + sdDist1 += indTraitsSums.ssqDist1[sex]; + sdDist2 += indTraitsSums.ssqDist2[sex]; + sdProp1 += indTraitsSums.ssqProp1[sex]; + } + mnDist1 /= popsize; + mnDist2 /= popsize; + mnProp1 /= popsize; + if (popsize > 1) { + sdDist1 = sdDist1 / popsize - mnDist1 * mnDist1; + sdDist2 = sdDist2 / popsize - mnDist2 * mnDist2; + sdProp1 = sdProp1 / popsize - mnProp1 * mnProp1; + sdDist1 = sdDist1 == 0.0 ? 0.0 : sqrt(sdDist1); + sdDist2 = sdDist2 == 0.0 ? 0.0 : sqrt(sdDist2); + sdProp1 = sdProp1 == 0.0 ? 0.0 : sqrt(sdProp1); + } + else { + sdDist1 = 0.0; + sdDist2 = 0.0; + sdProp1 = 0.0; + } + outtraits << "\t" << mnDist1 << "\t" << sdDist1; + if (trfr.twinKern) { + outtraits << "\t" << mnDist2 << "\t" << sdDist2; + outtraits << "\t" << mnProp1 << "\t" << sdProp1; } } } From 5f014acb794bb5b2865c4e872aa76f4f60bb9b0b Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 28 Apr 2025 11:32:09 +0100 Subject: [PATCH 305/332] initial individuals suffer genetic load --- Individual.cpp | 40 ++++++++++++++++++++++------------------ Individual.h | 4 +++- Population.cpp | 15 +++++++++------ SubCommunity.cpp | 3 +-- 4 files changed, 35 insertions(+), 27 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 393a357..13686a7 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -189,9 +189,6 @@ void Individual::inherit(Species* pSpecies, const Individual* mother) { if (newTrait->getMutationRate() > 0 && pSpecies->areMutationsOn()) newTrait->mutate(); } - if (trait == GENETIC_LOAD1 || trait == GENETIC_LOAD2 || trait == GENETIC_LOAD3 || trait == GENETIC_LOAD4 || trait == GENETIC_LOAD5) - geneticFitness *= newTrait->express(); - // Add the inherited trait and genes to the newborn's list spTraitTable.insert(make_pair(trait, move(newTrait))); } @@ -208,10 +205,11 @@ void Individual::setUpGenes(Species* pSpecies, int resol) { const auto spTrait = pSpecies->getSpTrait(traitType); this->spTraitTable.emplace(traitType, traitFactory.Create(traitType, spTrait)); } - setDispersalPhenotypes(pSpecies, resol); + expressDispersalPhenotypes(pSpecies, resol); + expressGeneticLoad(pSpecies); } -void Individual::setDispersalPhenotypes(Species* pSpecies, int resol) { +void Individual::expressDispersalPhenotypes(Species* pSpecies, int resol) { const emigRules emig = pSpecies->getEmigRules(); const transferRules trfr = pSpecies->getTransferRules(); @@ -219,12 +217,20 @@ void Individual::setDispersalPhenotypes(Species* pSpecies, int resol) { const settleRules settRules = pSpecies->getSettRules(stage, sex); // record phenotypic traits - if (emig.indVar) - this->setEmigTraits(pSpecies, emig.sexDep, emig.densDep); - if (trfr.indVar) - this->setTransferTraits(pSpecies, trfr, resol); - if (sett.indVar) - this->setSettlementTraits(pSpecies, sett.sexDep, settRules.densDep); + if (emig.indVar) setEmigTraits(pSpecies, emig.sexDep, emig.densDep); + if (trfr.indVar) setTransferTraits(pSpecies, trfr, resol); + if (sett.indVar) setSettlementTraits(pSpecies, sett.sexDep, settRules.densDep); +} + +// Set the fitness attribute of individuals +// Only called at initialisation, otherwise probably faster to compute directly during inheritance +void Individual::expressGeneticLoad(Species* pSpecies) { + const int nbGenLoadTraits = pSpecies->getNbGenLoadTraits(); + const vector whichTrait = { GENETIC_LOAD1 , GENETIC_LOAD2, GENETIC_LOAD3, GENETIC_LOAD4, GENETIC_LOAD5 }; + for (int i = 0; i < nbGenLoadTraits; i++) { + if (spTraitTable.contains(whichTrait[i])) + geneticFitness *= getTrait(whichTrait[i])->express(); + } } void Individual::setTransferTraits(Species* pSpecies, transferRules trfr, int resol) { @@ -232,11 +238,9 @@ void Individual::setTransferTraits(Species* pSpecies, transferRules trfr, int re if (trfr.moveType == 1) { setIndSMSTraits(pSpecies); } - else - setIndCRWTraits(pSpecies); + else setIndCRWTraits(pSpecies); } - else - setIndKernelTraits(pSpecies, trfr.sexDep, trfr.twinKern, resol); + else setIndKernelTraits(pSpecies, trfr.sexDep, trfr.twinKern, resol); } void Individual::setSettlementTraits(Species* pSpecies, bool sexDep, bool densDep) { @@ -283,14 +287,14 @@ void Individual::setSettlementTraits(Species* pSpecies, bool sexDep, bool densDe void Individual::inheritTraits(Species* pSpecies, Individual* mother, Individual* father, int resol) { inherit(pSpecies, mother, father); - setDispersalPhenotypes(pSpecies, resol); + expressDispersalPhenotypes(pSpecies, resol); } // Inherit genome from mother, haploid void Individual::inheritTraits(Species* pSpecies, Individual* mother, int resol) { inherit(pSpecies, mother); - setDispersalPhenotypes(pSpecies, resol); + expressDispersalPhenotypes(pSpecies, resol); } //--------------------------------------------------------------------------- @@ -1619,7 +1623,7 @@ void Individual::triggerMutations(Species* pSp) { || trType == GENETIC_LOAD5) geneticFitness *= indTrait->express(); } - this->setDispersalPhenotypes(pSp, 1.0); + this->expressDispersalPhenotypes(pSp, 1.0); } // Shorthand function to edit a genotype with custom values diff --git a/Individual.h b/Individual.h index b4117ed..41963d3 100644 --- a/Individual.h +++ b/Individual.h @@ -223,7 +223,9 @@ class Individual { void inheritTraits(Species* pSpecies, Individual* mother, int resol); //haploid - void setDispersalPhenotypes(Species* pSpecies, int resol); + void expressDispersalPhenotypes(Species* pSpecies, int resol); + + void expressGeneticLoad(Species* pSpecies); QuantitativeTrait* getTrait(TraitType trait) const; diff --git a/Population.cpp b/Population.cpp index 3a035ad..22abf98 100644 --- a/Population.cpp +++ b/Population.cpp @@ -175,15 +175,18 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) } else age = stg; - inds.push_back(new Individual(pCell, pPatch, stg, age, sstruct.repInterval, - probmale, trfr.usesMovtProc, trfr.moveType)); + Individual* newInd = new Individual(pCell, pPatch, stg, age, sstruct.repInterval, + probmale, trfr.usesMovtProc, trfr.moveType); - sex = inds[nindivs + i]->getSex(); if (pSpecies->getNTraits() > 0) { - // individual variation - set up genetics - inds[nindivs + i]->setUpGenes(pSpecies, resol); + newInd->setUpGenes(pSpecies, resol); + } + // Resolve genetic load + if (!newInd->isViable()) delete newInd; + else { + inds.push_back(newInd); + nInds[stg][newInd->getSex()]++; } - nInds[stg][sex]++; } } } diff --git a/SubCommunity.cpp b/SubCommunity.cpp index f85c710..7db8ad9 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -140,8 +140,7 @@ void SubCommunity::initialInd(Landscape* pLandscape, Species* pSpecies, // NB THIS WILL NEED TO BE CHANGED FOR MULTIPLE SPECIES... popns[0]->recruit(pInd); - if (pSpecies->getNTraits() > 0) - { + if (pSpecies->getNTraits() > 0) { // individual variation - set up genetics landData land = pLandscape->getLandData(); pInd->setUpGenes(pSpecies, land.resol); From d5cf8c013bb9337bfe78fde3f3d248ac63d0459a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 28 Apr 2025 12:07:18 +0100 Subject: [PATCH 306/332] restore accidentally removed genetic load ofr asexual species. thanks unit tests! --- Individual.cpp | 4 ++++ unit_tests/testPopulation.cpp | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 1f92400..909b756 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -189,6 +189,10 @@ void Individual::inherit(Species* pSpecies, const Individual* mother) { if (newTrait->getMutationRate() > 0 && pSpecies->areMutationsOn()) newTrait->mutate(); } + + if (trait == GENETIC_LOAD1 || trait == GENETIC_LOAD2 || trait == GENETIC_LOAD3 || trait == GENETIC_LOAD4 || trait == GENETIC_LOAD5) + geneticFitness *= newTrait->express(); + // Add the inherited trait and genes to the newborn's list spTraitTable.insert(make_pair(trait, move(newTrait))); } diff --git a/unit_tests/testPopulation.cpp b/unit_tests/testPopulation.cpp index 3cfe9df..3979a30 100644 --- a/unit_tests/testPopulation.cpp +++ b/unit_tests/testPopulation.cpp @@ -8,7 +8,7 @@ void testPopulation() // Given a genetic load trait, offspring // Survival is (inversely) proportional to the mutation rate { - vector mutationRates = { 0.0, 0.05, 0.1 }; + vector mutationRates = { 0.0, 0.1, 0.2 }; vector survivingInds; const int initialNbInds = 1000; const float localK = 10000; // not limiting @@ -63,7 +63,8 @@ void testPopulation() pop.fledge(); // non-overlapping: adults are replaced with juveniles survivingInds.push_back(pop.getNInds()); } - assert(survivingInds[0] > survivingInds[1] && survivingInds[1] > survivingInds[2]); + assert(survivingInds[0] > survivingInds[1] + && survivingInds[1] > survivingInds[2]); } // Dispersal is proportional to the mutation rate From 0544fc11a328f91d81e5d2686c6a8661825ed4b0 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 28 Apr 2025 13:46:07 +0100 Subject: [PATCH 307/332] individuals initialised from files also suffer genetic load --- SubCommunity.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 7db8ad9..e9e8e28 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -136,16 +136,15 @@ void SubCommunity::initialInd(Landscape* pLandscape, Species* pSpecies, } pInd = new Individual(pCell, pPatch, stg, age, repInt, probmale, trfr.usesMovtProc, trfr.moveType); - // add new individual to the population - // NB THIS WILL NEED TO BE CHANGED FOR MULTIPLE SPECIES... - popns[0]->recruit(pInd); - if (pSpecies->getNTraits() > 0) { // individual variation - set up genetics landData land = pLandscape->getLandData(); pInd->setUpGenes(pSpecies, land.resol); } + // Resolve genetic load + if (!pInd->isViable()) delete pInd; + else popns[0]->recruit(pInd); } // Create a new population, and return its address From 34b34141465fd393830465ac888059b24619d4ab Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 29 Apr 2025 14:25:11 +0100 Subject: [PATCH 308/332] can initialise only a subset of positions --- GeneticFitnessTrait.cpp | 28 ++++++++++++++++++++-------- NeutralTrait.cpp | 8 ++++++-- SpeciesTrait.cpp | 5 +++++ SpeciesTrait.h | 3 +++ 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/GeneticFitnessTrait.cpp b/GeneticFitnessTrait.cpp index 4dbfed4..151110a 100644 --- a/GeneticFitnessTrait.cpp +++ b/GeneticFitnessTrait.cpp @@ -243,13 +243,16 @@ void GeneticFitnessTrait::initialise() { auto initDomParams = pSpeciesTrait->getInitDomParameters(); const set genePositions = pSpeciesTrait->getGenePositions(); + const set initPositions = pSpeciesTrait->getInitPositions(); + for (auto position : genePositions) { vector> initialGene(ploidy); for (int p = 0; p < ploidy; p++) { - initSelCoeff = initDist == NONE ? 0.0 - : drawSelectionCoef(initDist, initParams); - initDomCoeff = initDomDist == NONE ? 0.0 - : drawDominance(initSelCoeff, initDomDist, initDomParams); + initSelCoeff = initDomCoeff = 0.0; + if (initPositions.contains(position)) { + initSelCoeff = drawSelectionCoef(initDist, initParams); + initDomCoeff = drawDominance(initSelCoeff, initDomDist, initDomParams); + } initialGene[p] = make_shared(initSelCoeff, initDomCoeff); } genes.insert(make_pair(position, initialGene)); @@ -304,7 +307,7 @@ void GeneticFitnessTrait::mutate() // ---------------------------------------------------------------------------------------- float GeneticFitnessTrait::drawDominance(float selCoef, const DistributionType& domDist, const map& domParams) { - float h; + float h = 0.0; switch (domDist) { case UNIFORM: { @@ -343,10 +346,14 @@ float GeneticFitnessTrait::drawDominance(float selCoef, const DistributionType& h = pRandom->FRandom(0, max); break; } - + case NONE: + { + // nothing, s remains 0.0 + break; + } default: { - throw logic_error("wrong parameter value for genetic load dominance model, must be uniform/normal/gamma/negExp/scaled \n"); + throw logic_error("wrong parameter value for genetic load dominance model, must be uniform/normal/gamma/negExp/scaled/none \n"); break; } } @@ -398,9 +405,14 @@ float GeneticFitnessTrait::drawSelectionCoef(const DistributionType& mutationDis } while (!pSpeciesTrait->isValidTraitVal(s)); break; } + case NONE: + { + // nothing, s remains 0.0 + break; + } default: { - throw logic_error("wrong parameter value for genetic load mutation model, must be uniform/normal/gamma/negExp/scaled \n"); + throw logic_error("wrong parameter value for genetic load mutation model, must be uniform/normal/gamma/negExp/scaled/none \n"); break; } } diff --git a/NeutralTrait.cpp b/NeutralTrait.cpp index 8d40481..7b50e92 100644 --- a/NeutralTrait.cpp +++ b/NeutralTrait.cpp @@ -240,14 +240,18 @@ void NeutralTrait::inheritHaploid(const bool& fromMother, mapgetGenePositions(); + const auto& initPositions = pSpeciesTrait->getInitPositions(); short ploidy = pSpeciesTrait->getPloidy(); for (auto position : genePositions) { vector allelePair; for (int i = 0; i < ploidy; i++) { - // allele values span 0 - max inclusive, max is wildtype - auto alleleVal = (unsigned char)pRandom->IRandom(0, maxAlleleVal); + unsigned char alleleVal = char(0); + if (initPositions.contains(position)) { + // allele values span 0 - max inclusive, max is wildtype + alleleVal = (unsigned char)pRandom->IRandom(0, maxAlleleVal); + } allelePair.emplace_back(alleleVal); } genes.insert(make_pair(position, allelePair)); diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 09afa6f..ec7358b 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -7,6 +7,7 @@ SpeciesTrait::SpeciesTrait( const sex_t& sx, const set& pos, const ExpressionType& expr, + const set& initialPositions, const DistributionType& initDist, const map initParams, const DistributionType& initDomDist, @@ -23,6 +24,7 @@ SpeciesTrait::SpeciesTrait( sex{ sx }, genePositions{ pos }, expressionType{ expr }, + initPositions{ initialPositions }, initialDistribution{ initDist }, initialParameters{ initParams }, initialDomDistribution{ initDomDist }, @@ -220,6 +222,7 @@ SpeciesTrait* createTestEmigSpTrait(const set& genePositions, const bool& i sex_t::NA, genePositions, ExpressionType::ADDITIVE, + genePositions, DistributionType::UNIFORM, distParams, DistributionType::NONE, // no dominance @@ -247,6 +250,7 @@ SpeciesTrait* createTestGenLoadTrait(const set& genePositions, const bool& sex_t::NA, genePositions, ExpressionType::MULTIPLICATIVE, + genePositions, DistributionType::NONE, distParams, DistributionType::NONE, // initialise dominance to zero @@ -274,6 +278,7 @@ SpeciesTrait* createTestNeutralSpTrait(const float& maxAlleleVal, const set sex_t::NA, genePositions, ExpressionType::NOTEXPR, + genePositions, // Sample initial values from uniform(0, max) DistributionType::UNIFORM, distParams, DistributionType::NONE, // No dominance diff --git a/SpeciesTrait.h b/SpeciesTrait.h index c866dd4..d143199 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -20,6 +20,7 @@ class SpeciesTrait { const sex_t& sex, const set& pos, const ExpressionType& expr, + const set& initialPositions, const DistributionType& initDist, const map initParams, const DistributionType& initDomDist, @@ -43,6 +44,7 @@ class SpeciesTrait { float getMutationRate() const { return mutationRate; } short getPloidy() const { return ploidy; } set& getGenePositions() { return genePositions; } // returning by reference, make sure receiver is const + set getInitPositions() const { return initPositions; } int getPositionsSize() const { return static_cast(genePositions.size()); } bool isInherited() const { return inherited; } @@ -79,6 +81,7 @@ class SpeciesTrait { // Positions in the genome of all genes (loci) pertaining to this trait // The genome itself is not modelled explicitly set genePositions; + set initPositions; ExpressionType expressionType; DistributionType initialDistribution; From e81684322e390e0c19b8a502603e8537f47d8c34 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 29 Apr 2025 14:37:03 +0100 Subject: [PATCH 309/332] initial individuals do not suffer genetic load --- Population.cpp | 8 ++------ SubCommunity.cpp | 4 +--- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/Population.cpp b/Population.cpp index 22abf98..f758a75 100644 --- a/Population.cpp +++ b/Population.cpp @@ -181,12 +181,8 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) if (pSpecies->getNTraits() > 0) { newInd->setUpGenes(pSpecies, resol); } - // Resolve genetic load - if (!newInd->isViable()) delete newInd; - else { - inds.push_back(newInd); - nInds[stg][newInd->getSex()]++; - } + inds.push_back(newInd); + nInds[stg][newInd->getSex()]++; } } } diff --git a/SubCommunity.cpp b/SubCommunity.cpp index e9e8e28..04694c4 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -142,9 +142,7 @@ void SubCommunity::initialInd(Landscape* pLandscape, Species* pSpecies, pInd->setUpGenes(pSpecies, land.resol); } - // Resolve genetic load - if (!pInd->isViable()) delete pInd; - else popns[0]->recruit(pInd); + popns[0]->recruit(pInd); } // Create a new population, and return its address From b7f2d603a8fe44998ed8ff249cb1a57eaf2e3044 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Wed, 7 May 2025 09:20:07 +0200 Subject: [PATCH 310/332] added debug output for translocations --- Management.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/Management.cpp b/Management.cpp index bb87620..8336098 100644 --- a/Management.cpp +++ b/Management.cpp @@ -98,6 +98,9 @@ void Management::translocate(int yr ){ #if RS_RCPP Rcpp::Rcout << "Start translocation events in year " << yr << endl; +#endif +#ifndef NDEBUG + cout << "Start translocation events in year " << yr << endl; #endif landParams ppLand = pLandscape->getLandParams(); auto it = nb.find(yr); // the number of translocation events is determined by the number of elements of the maps at year yr @@ -112,6 +115,9 @@ void Management::translocate(int yr for (int e = 0; e < it->second.size(); e++) { #if RS_RCPP Rcpp::Rcout << "Translocation event " << e << " in year " << yr << endl; +#endif +#ifndef NDEBUG + cout << "Translocation event " << e << " in year " << yr << endl; #endif // find the source patch Patch* s_patch; @@ -121,6 +127,10 @@ void Management::translocate(int yr #if RS_RCPP Rcpp::Rcout << "Source patch exist." << endl; #endif +#ifndef NDEBUG + cout << "Source patch exist." << endl; +#endif + s_patch = pLandscape->findPatch(source_it->second[e].x); if (s_patch != 0) { // test if population in patch is not zero @@ -129,12 +139,18 @@ void Management::translocate(int yr } else { #if RS_RCPP Rcpp::Rcout << "Population does not exist in source patch or is 0! skipping translocation event." << endl; +#endif +#ifndef NDEBUG + cout << "Population does not exist in source patch or is 0! skipping translocation event." << endl; #endif return; } } else { #if RS_RCPP Rcpp::Rcout << "Source patch was found but NULL! skipping translocation event." << endl; // not sure if this ever happens +#endif +#ifndef NDEBUG + cout << "Source patch was found but NULL! skipping translocation event." << endl; // not sure if this ever happens #endif return; } @@ -142,6 +158,9 @@ void Management::translocate(int yr } else{ #if RS_RCPP Rcpp::Rcout << "Source patch was not found in landscape! skipping translocation event." << endl; +#endif +#ifndef NDEBUG + cout << "Source patch was not found in landscape! skipping translocation event." << endl; #endif return; } @@ -151,6 +170,9 @@ void Management::translocate(int yr if (pCell != 0) { #if RS_RCPP Rcpp::Rcout << "Source cell was found" << endl; +#endif +#ifndef NDEBUG + cout << "Source cell was found" << endl; #endif intptr s_ppatch = pCell->getPatch(); if (s_ppatch != 0) { @@ -161,6 +183,9 @@ void Management::translocate(int yr } else { #if RS_RCPP Rcpp::Rcout << "Population does not exist in source cell or is 0! skipping translocation event." << endl; +#endif +#ifndef NDEBUG + cout << "Population does not exist in source cell or is 0! skipping translocation event." << endl; #endif return; } @@ -168,11 +193,18 @@ void Management::translocate(int yr #if RS_RCPP Rcpp::Rcout << "Source cell does not exist! skipping translocation event." << endl; #endif +#ifndef NDEBUG + cout << "Source cell does not exist! skipping translocation event." << endl; +#endif + return; } } else { #if RS_RCPP Rcpp::Rcout << "Cell does not belong to landscape! skipping translocation event." << endl; +#endif +#ifndef NDEBUG + cout << "Cell does not belong to landscape! skipping translocation event." << endl; #endif return; } @@ -184,11 +216,17 @@ void Management::translocate(int yr if(pLandscape->existsPatch(target_it->second[e].x)){ #if RS_RCPP Rcpp::Rcout << "Target patch exist." << endl; +#endif +#ifndef NDEBUG + cout << "Target patch exist." << endl; #endif t_patch = pLandscape->findPatch(target_it->second[e].x); } else{ #if RS_RCPP Rcpp::Rcout << "Target patch was not found in landscape! skipping translocation event." << endl; +#endif +#ifndef NDEBUG + cout << "Target patch was not found in landscape! skipping translocation event." << endl; #endif return; } @@ -198,6 +236,9 @@ void Management::translocate(int yr if (pCell != 0) { #if RS_RCPP Rcpp::Rcout << "Target cell was found" << endl; +#endif +#ifndef NDEBUG + cout << "Target cell was found" << endl; #endif intptr t_ppatch = pCell->getPatch(); if (t_ppatch != 0) { @@ -205,12 +246,18 @@ void Management::translocate(int yr } else { #if RS_RCPP Rcpp::Rcout << "Target cell does not exist! skipping translocation event." << endl; +#endif +#ifndef NDEBUG + cout << "Target cell does not exist! skipping translocation event." << endl; #endif return; } } else { #if RS_RCPP Rcpp::Rcout << "Target cell does not belong to landscape! skipping translocation event." << endl; +#endif +#ifndef NDEBUG + cout << "Target cell does not belong to landscape! skipping translocation event." << endl; #endif return; } @@ -241,6 +288,9 @@ void Management::translocate(int yr if (t_pPop == 0) { // translocated individual is the first in a previously uninhabited patch #if RS_RCPP Rcpp::Rcout << "Population does not exist in target patch. Creating new population." << endl; +#endif +#ifndef NDEBUG + cout << "Population does not exist in target patch. Creating new population." << endl; #endif // create a new population in the corresponding sub-community SubCommunity* pSubComm = (SubCommunity*)t_patch->getSubComm(); @@ -266,8 +316,11 @@ void Management::translocate(int yr } #if RS_RCPP Rcpp::Rcout << "Successfully translocated " << translocated << " out of " << nb_it->second[e] << " individuals in translocation event " << e <<"." << endl; +#endif +#ifndef NDEBUG + cout << "Successfully translocated " << translocated << " out of " << nb_it->second[e] << " individuals in translocation event " << e <<"." << endl; #endif // remove pointers to sampled individuals s_pPop->clean(); } -}; \ No newline at end of file +}; From d8e5256a0665169d4a3f0248f191965e5906c2c2 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 12 Jun 2025 12:14:14 +0200 Subject: [PATCH 311/332] patchnums not used anywhere so dropped them --- Landscape.cpp | 25 ------------------------- Landscape.h | 5 ----- 2 files changed, 30 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index 3f09123..d7822ff 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -300,7 +300,6 @@ Landscape::~Landscape() { if (initcells[i] != NULL) delete initcells[i]; initcells.clear(); - patchnums.clear(); habCodes.clear(); landchanges.clear(); patchchanges.clear(); @@ -317,7 +316,6 @@ void Landscape::resetLand(void) { int npatches = (int)patches.size(); for (int i = 0; i < npatches; i++) if (patches[i] != NULL) delete patches[i]; patches.clear(); - patchnums.clear(); if (cells != 0) { for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { @@ -513,18 +511,6 @@ void Landscape::setCellArray(void) { } } -void Landscape::addPatchNum(int p) { - int npatches = (int)patchnums.size(); - bool addpatch = true; - for (int i = 0; i < npatches; i++) { - if (p == patchnums[i]) { - addpatch = false; i = npatches + 1; - } - } - if (addpatch) patchnums.push_back(p); -} - - //--------------------------------------------------------------------------- /* Create an artificial landscape (random or fractal), which can be either binary (habitat index 0 is the matrix, 1 is suitable habitat) @@ -541,7 +527,6 @@ void Landscape::generatePatches() int patchnum = 0; // initial patch number for cell-based landscape // create patch 0 - the matrix patch (even if there is no matrix) - patchnums.push_back(patchnum); newPatch(patchnum++); // as landscape generator returns cells in a random sequence, first set up all cells @@ -570,7 +555,6 @@ void Landscape::generatePatches() pCell = findCell(x, y); if (continuous) { if (iter->value > 0.0) { // habitat - patchnums.push_back(patchnum); pPatch = newPatch(patchnum++); addCellToPatch(pCell, pPatch, iter->value); } @@ -583,7 +567,6 @@ void Landscape::generatePatches() addCellToPatch(pCell, patches[0]); } else { // habitat - patchnums.push_back(patchnum); pPatch = newPatch(patchnum++); addCellToPatch(pCell, pPatch); pCell->changeHabIndex(0, 1); @@ -602,7 +585,6 @@ void Landscape::generatePatches() pCell = findCell(x, y); hab = pCell->getHabIndex(0); } while (hab > 0); - patchnums.push_back(patchnum); pPatch = newPatch(patchnum++); pCell = findCell(x, y); addCellToPatch(pCell, pPatch); @@ -656,7 +638,6 @@ void Landscape::allocatePatches(Species* pSpecies) // create the matrix patch patches.push_back(new Patch(0, 0)); Patch* matrixPatch = patches[0]; - patchnums.push_back(0); int patchnum = 1; switch (rasterType) { @@ -672,7 +653,6 @@ void Landscape::allocatePatches(Species* pSpecies) habK += pSpecies->getHabK(pCell->getHabIndex(i)); } if (habK > 0.0) { // cell is suitable - create a patch for it - patchnums.push_back(patchnum); pPatch = newPatch(patchnum++); addCellToPatch(pCell, pPatch); } @@ -696,7 +676,6 @@ void Landscape::allocatePatches(Species* pSpecies) habK += pSpecies->getHabK(i) * pCell->getHabitat(i) / 100.0f; } if (habK > 0.0) { // cell is suitable - create a patch for it - patchnums.push_back(patchnum); pPatch = newPatch(patchnum++); addCellToPatch(pCell, pPatch); } @@ -720,7 +699,6 @@ void Landscape::allocatePatches(Species* pSpecies) habK += pSpecies->getHabK(0) * pCell->getHabitat(i) / 100.0f; } if (habK > 0.0) { // cell is suitable (at some time) - create a patch for it - patchnums.push_back(patchnum); pPatch = newPatch(patchnum++); addCellToPatch(pCell, pPatch); } @@ -1294,7 +1272,6 @@ int Landscape::readLandChange(int filenum, bool costs) else { patchChgMatrix[y][x][2] = p; if (p > 0 && !existsPatch(p)) { - addPatchNum(p); newPatch(pchseq++, p); } } @@ -1435,7 +1412,6 @@ int Landscape::readLandChange(int filenum, bool costs) else { patchChgMatrix[y][x][2] = p; if (p > 0 && !existsPatch(p)) { - addPatchNum(p); newPatch(pchseq++, p); } } @@ -2212,7 +2188,6 @@ else { // couldn't read from hfile // addNewCellToPatch(findPatch(p),x,y,hfloat); } else { - addPatchNum(p); pPatch = newPatch(seq++, p); addNewCellToPatch(pPatch, x, y, hfloat); } diff --git a/Landscape.h b/Landscape.h index e2f2cf9..2ea41cb 100644 --- a/Landscape.h +++ b/Landscape.h @@ -230,8 +230,6 @@ class Landscape { // functions to handle patches and cells void setCellArray(void); - void addPatchNum(int); - std::vector getPatchNums() const { return patchnums; } void generatePatches(); // create an artificial landscape void allocatePatches(Species*); // create patches for a cell-based landscape Patch* newPatch( @@ -489,9 +487,6 @@ class Landscape { // list of patches in the landscape - can be in any sequence std::vector patches; - // list of patch numbers in the landscape - std::vector patchnums; - // list of habitat codes std::vector habCodes; From e0e40bc806e030af3155eb9e2bc75877ad6a75e4 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 12 Jun 2025 14:07:23 +0200 Subject: [PATCH 312/332] ensure patch heterogeneity is written in the correct order --- Community.cpp | 87 +++++++++++++++++++++++++++++++++------------------ Community.h | 4 +-- Landscape.cpp | 10 +++++- Landscape.h | 1 + 4 files changed, 69 insertions(+), 33 deletions(-) diff --git a/Community.cpp b/Community.cpp index 3455a6f..dab4a41 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1596,14 +1596,17 @@ bool Community::openNeutralOutputFile(Species* pSpecies, int landNr) bool Community::openPerLocusFstFile(Species* pSpecies, Landscape* pLandscape, const int landNr, const int rep) { - set patchList = pSpecies->getSamplePatches(); - if (patchList.size() == 0) { - // list of patches is not known yet and may change every generation, - // e.g. for randomOccupied sampling option - // instead, header patch numbers range from 1 to nb of sampled patches - for (int i = 0; i < pSpecies->getNbPatchesToSample(); i++) { - patchList.emplace(i + 1); - } + set patchList; + string samplingOpt = paramsSim->getSim().patchSamplingOption; + if (samplingOpt == "list" + || samplingOpt == "random" + || (samplingOpt == "all" && !pLandscape->getLandParams().dynamic) + ) // list of patches always the same + patchList = pSpecies->getSamplePatches(); + else { // random_occupied or all with dynamic landscape + // then sampled patches may change every year, + // so produce an entry for all patches + patchList = pLandscape->getPatchNbs(); } if (landNr == -999) { // close the file @@ -1687,10 +1690,10 @@ void Community::writeNeutralOutputFile(int rep, int yr, int gen, bool outWeirCoc << pNeutralStatistics->getFisWC() << "\t" << pNeutralStatistics->getFitWC() << "\t"; } - else outwcfstat << "N/A" << "\t" << "N/A" << "\t" << "N/A" << "\t"; + else outwcfstat << "NA" << "\t" << "NA" << "\t" << "NA" << "\t"; if (outWeirHill) outwcfstat << pNeutralStatistics->getWeightedFst() << "\t"; - else outwcfstat << "N/A" << "\t"; + else outwcfstat << "NA" << "\t"; outwcfstat << pNeutralStatistics->getMeanNbAllPerLocus() << "\t" << pNeutralStatistics->getMeanNbAllPerLocusPerPatch() << "\t" @@ -1705,8 +1708,13 @@ void Community::writeNeutralOutputFile(int rep, int yr, int gen, bool outWeirCoc // Write per locus FST results file // ---------------------------------------------------------------------------------------- -void Community::writePerLocusFstatFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList) +void Community::writePerLocusFstatFile(Species* pSpecies, const int yr, const int gen, const int nLoci, set const& patchList) { + string samplingOpt = paramsSim->getSim().patchSamplingOption; + bool samplingFixed = samplingOpt == "list" + || samplingOpt == "random" + || (samplingOpt == "all" && !pLandscape->getLandParams().dynamic); + const set positions = pSpecies->getSpTrait(NEUTRAL)->getGenePositions(); int thisLocus = 0; @@ -1720,33 +1728,52 @@ void Community::writePerLocusFstatFile(Species* pSpecies, const int yr, const in << pNeutralStatistics->getPerLocusFit(thisLocus) << "\t" << pNeutralStatistics->getPerLocusHo(thisLocus); - for (int patchId : patchList) { - const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); - int popSize = 0; - int het = 0; - if (pPop != 0) { - popSize = pPop->sampleSize(); - if (popSize == 0) { - outperlocusfstat << "\t" << "N/A"; + if (samplingFixed) { // then safe to output sampled patches in order + for (int patchId : patchList) { + float het = getPatchHet(pSpecies, patchId, thisLocus); + if (het < 0) // patch empty + outperlocusfstat << "\t" << "NA"; + else outperlocusfstat << "\t" << het; + } + } + else { // sampling may change between generations, must produce output for all patches in Landscape + for (auto patchId : pLandscape->getPatchNbs()) { + if (patchList.contains(patchId)) { + float het = getPatchHet(pSpecies, patchId, thisLocus); + if (het < 0) // patch empty + outperlocusfstat << "\t" << "NA"; + else outperlocusfstat << "\t" << het; } - else { - for (int a = 0; a < nAlleles; ++a) { - het += static_cast(pPop->getHeteroTally(thisLocus, a)); - } - outperlocusfstat << "\t" - << het / (2.0 * popSize); + else { // patch not sampled + outperlocusfstat << "\t" << "NA"; } } - else { - outperlocusfstat << "\t" << "N/A"; - } } ++thisLocus; outperlocusfstat << endl; } } +float Community::getPatchHet(Species* pSpecies, int patchId, int whichLocus) const { + const auto patch = pLandscape->findPatch(patchId); + const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + int nAlleles = pSpecies->getSpTrait(NEUTRAL)->getNbNeutralAlleles(); + int popSize = 0; + int het = 0; + if (pPop != 0) { + popSize = pPop->sampleSize(); + if (popSize == 0) return -1.0; + else { + for (int a = 0; a < nAlleles; ++a) { + het += static_cast(pPop->getHeteroTally(whichLocus, a)); + } + het /= (2.0 * popSize); + return het; + } + } + else return -1.0; +} + // ---------------------------------------------------------------------------------------- // Write pairwise FST results file @@ -1821,7 +1848,7 @@ void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, writeNeutralOutputFile(rep, yr, gen, outWeirCockerham, outWeirHill); if (outWeirCockerham) { - writePerLocusFstatFile(pSpecies, yr, gen, maxNbNeutralAlleles, nLoci, patchList); + writePerLocusFstatFile(pSpecies, yr, gen, nLoci, patchList); } if (outWeirHill) { writePairwiseFstFile(pSpecies, yr, gen, maxNbNeutralAlleles, nLoci, patchList); diff --git a/Community.h b/Community.h index c93e4ae..28586cc 100644 --- a/Community.h +++ b/Community.h @@ -201,9 +201,9 @@ class Community { //file writers void writeNeutralOutputFile(int rep, int yr, int gen, bool outWeirCockerham, bool outWeirHill); - void writePerLocusFstatFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList); + void writePerLocusFstatFile(Species* pSpecies, const int yr, const int gen, const int nLoci, set const& patchList); void writePairwiseFstFile(Species* pSpecies, const int yr, const int gen, const int nAlleles, const int nLoci, set const& patchList); - + float getPatchHet(Species* pSpecies, int patchId, int whichLocus) const; private: Landscape* pLandscape; int indIx; // index used to apply initial individuals diff --git a/Landscape.cpp b/Landscape.cpp index d7822ff..afbd5aa 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -836,6 +836,14 @@ Patch* Landscape::findPatch(int num) { return 0; } + +set Landscape::getPatchNbs() const { + set patchNbs; + for (auto& p : patches) + patchNbs.emplace(p->getPatchNum()); + return patchNbs; +} + set Landscape::samplePatches(const string& samplingOption, int nbToSample, Species* pSpecies) { vector sampledPatches; @@ -860,7 +868,7 @@ set Landscape::samplePatches(const string& samplingOption, int nbToSample, nbToSample, rng); } else { - throw logic_error("Sampling option should be random, rnadom_occupied or all when sampling patches."); + throw logic_error("Sampling option should be random, random_occupied or all when sampling patches."); } set patchIds; diff --git a/Landscape.h b/Landscape.h index 2ea41cb..4a2e70f 100644 --- a/Landscape.h +++ b/Landscape.h @@ -288,6 +288,7 @@ class Landscape { Patch* findPatch( int // Patch id no. ); + set getPatchNbs() const; set samplePatches(const string& samplingOption, int nbToSample, Species* pSpecies); int checkTotalCover(void); void resetPatchPopns(void); From dc2d3501058ed437f54c5dbef7ae841955133b59 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 19 Jun 2025 15:15:33 +0100 Subject: [PATCH 313/332] cleanup readLandscape --- Landscape.cpp | 652 ++++++++++++++++++++++++++------------------------ 1 file changed, 333 insertions(+), 319 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index afbd5aa..b4d6971 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -1750,362 +1750,369 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string #else string header; #endif - int h, seq, p, habnodata; - int pchnodata = 0; + int habCode, seq, patchCode, noDataHabCode; + int noDataPatch = 0; int ncols, nrows; - float hfloat, pfloat; + float habFloat, patchFloat; Patch* pPatch; simParams sim = paramsSim->getSim(); if (fileNum < 0) return 19; #if RS_RCPP - wifstream hfile; // habitat file input stream - wifstream pfile; // patch file input stream + wifstream ifsHabMap; // habitat file input stream + wifstream ifsPatchMap; // patch file input stream #else - ifstream hfile; // habitat file input stream - ifstream pfile; // patch file input stream + ifstream ifsHabMap; // habitat file input stream + ifstream ifsPatchMap; // patch file input stream #endif initParams init = paramsInit->getInit(); - // open habitat file and optionally also patch file + // Open habitat file and optionally also patch file #if RS_RCPP - hfile.open(pathHabFile, std::ios::binary); + ifsHabMap.open(habfile, std::ios::binary); if (landraster.utf) { // apply BOM-sensitive UTF-16 facet - hfile.imbue(std::locale(hfile.getloc(), new std::codecvt_utf16)); + ifsHabMap.imbue(std::locale(ifsHabMap.getloc(), new std::codecvt_utf16)); } #else - hfile.open(habfile.c_str()); + ifsHabMap.open(habfile.c_str()); #endif - if (!hfile.is_open()) return 11; + + if (!ifsHabMap.is_open()) return 11; + if (fileNum == 0) { if (patchModel) { #if RS_RCPP - pfile.open(pathPatchFile, std::ios::binary); + ifsPatchMap.open(pchfile, std::ios::binary); if (patchraster.utf) { // apply BOM-sensitive UTF-16 facet - pfile.imbue(std::locale(pfile.getloc(), new std::codecvt_utf16)); + ifsPatchMap.imbue(std::locale(ifsPatchMap.getloc(), new std::codecvt_utf16)); } #else - pfile.open(pchfile.c_str()); + ifsPatchMap.open(pchfile.c_str()); #endif - if (!pfile.is_open()) { - hfile.close(); hfile.clear(); + if (!ifsPatchMap.is_open()) { + ifsHabMap.close(); + ifsHabMap.clear(); return 12; } } } -// read landscape data from header records of habitat file -// NB headers of all files have already been compared -double tmpresol; -hfile >> header >> ncols >> header >> nrows >> header >> minEast >> header >> minNorth - >> header >> tmpresol >> header >> habnodata; -resol = (int) tmpresol; + // read landscape data from header records of habitat file + // NB headers of all files have already been compared + ifsHabMap >> header >> ncols + >> header >> nrows + >> header >> minEast + >> header >> minNorth + >> header >> resol + >> header >> noDataHabCode; #if RS_RCPP - if (!hfile.good()) { + if (!ifsHabMap.good()) { // corrupt file stream - StreamErrorR(pathHabFile); - hfile.close(); - hfile.clear(); + StreamErrorR(habfile); + ifsHabMap.close(); + ifsHabMap.clear(); if (patchModel) { - pfile.close(); - pfile.clear(); + ifsPatchMap.close(); + ifsPatchMap.clear(); } return 131; } #endif - dimX = ncols; - dimY = nrows; - minX = maxY = 0; + dimX = ncols; + dimY = nrows; + minX = maxY = 0; maxX = dimX - 1; maxY = dimY - 1; - if (fileNum == 0) { - // set initialisation limits to landscape limits + if (fileNum == 0) { // First map layer + + // Set initialisation limits to landscape limits init.minSeedX = init.minSeedY = 0; - init.maxSeedX = maxX; + init.maxSeedX = maxX; init.maxSeedY = maxY; paramsInit->setInit(init); - } - if (fileNum == 0) { if (patchModel) { - for (int i = 0; i < 5; i++) - pfile >> header >> pfloat; - pfile >> header >> pchnodata; + for (int i = 0; i < 5; i++) + ifsPatchMap >> header >> patchFloat; + ifsPatchMap >> header >> noDataPatch; } + #if RS_RCPP - if (!pfile.good()) { + if (!ifsPatchMap.good()) { // corrupt file stream - StreamErrorR(pathPatchFile); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); + StreamErrorR(pchfile); + ifsHabMap.close(); + ifsHabMap.clear(); + ifsPatchMap.close(); + ifsPatchMap.clear(); return 135; } #endif setCellArray(); } - // set up bad float values to ensure that valid values are read - float badhfloat = -9.0; if (habnodata == -9) badhfloat = -99.0; - float badpfloat = -9.0; if (pchnodata == -9) badpfloat = -99.0; + float badHabFloat = -9.0; + if (noDataHabCode == -9) badHabFloat = -99.0; + float badPatchFloat = -9.0; + if (noDataPatch == -9) badPatchFloat = -99.0; seq = 0; // initial sequential patch landscape - p = 0; // initial patch number for cell-based landscape - // create patch 0 - the matrix patch (even if there is no matrix) - if (fileNum == 0) newPatch(seq++, p++); + patchCode = 0; // initial patch number for cell-based landscape + + // Create the matrix patch (even if there is no matrix) + if (fileNum == 0) { + newPatch(seq, patchCode); + seq++; + patchCode++; + } switch (rasterType) { - case 0: // raster with habitat codes - 100% habitat each cell + case 0: // Raster with habitat codes - 100% habitat each cell if (fileNum > 0) return 19; // error condition - should not occur + for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { - hfloat = badhfloat; -#if RS_RCPP - if (hfile >> hfloat) { -#else - hfile >> hfloat; -#endif - h = (int)hfloat; - if (patchModel) { - pfloat = badpfloat; -#if RS_RCPP - if (pfile >> pfloat) { -#else - pfile >> pfloat; -#endif - p = (int)pfloat; + + habFloat = badHabFloat; #if RS_RCPP - } else { // corrupt file stream -#if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; -#endif - StreamErrorR(pathPatchFile); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 132; + if (ifsHabMap >> habFloat) { + habCode = (int)habFloat; + if (patchModel) { + patchFloat = badPatchFloat; + if (ifsPatchMap >> patchFloat) { + patchCode = (int)patchFloat; + } + else { // corrupt file stream +#if !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR(pchfile); + ifsHabMap.close(); + ifsHabMap.clear(); + ifsPatchMap.close(); + ifsPatchMap.clear(); + return 132; + } } -#endif } -#if RS_RCPP - } else { // corrupt file stream -#if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; + else { // corrupt file stream +#if !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - StreamErrorR(pathHabFile); - hfile.close(); - hfile.clear(); + StreamErrorR(habfile); + ifsHabMap.close(); + ifsHabMap.clear(); if (patchModel) { - pfile.close(); - pfile.clear(); - } + ifsPatchMap.close(); + ifsPatchMap.clear(); + } return 135; } +#else + // Read habitat code in this cell + ifsHabMap >> habFloat; + habCode = static_cast(habFloat); + if (patchModel) { + // Read patch code in this cell + patchFloat = badPatchFloat; + ifsPatchMap >> patchFloat; + patchCode = static_cast(patchFloat); + } #endif - if (h == habnodata) - addNewCellToLand(x, y, -1); // add cell only to landscape - else { - - // THERE IS AN ANOMALY HERE - CURRENTLY HABITAT 0 IS OK FOR GUI VERSION BUT - // NOT ALLOWED FOR BATCH VERSION (HABITATS MUST BE 1...n) - // SHOULD WE MAKE THE TWO VERSIONS AGREE? ... - - if (h < 0 || (sim.batchMode && (h < 1 || h > nHabMax))) { - // invalid habitat code + if (habCode == noDataHabCode) { + // No-data cell + addNewCellToLand(x, y, -1); // x, y is a null cell + } + else if (habCode < 0 || (sim.batchMode && (habCode < 1 || habCode > nHabMax))) { + // Invalid habitat code #if RS_RCPP && !R_CMD - Rcpp::Rcout << "Found invalid habitat code." << std::endl; + Rcpp::Rcout << "Found invalid habitat code." << std::endl; #endif - hfile.close(); hfile.clear(); - if (patchModel) { - pfile.close(); pfile.clear(); - } - return 13; + ifsHabMap.close(); + ifsHabMap.clear(); + if (patchModel) { + ifsPatchMap.close(); + ifsPatchMap.clear(); } - else { - addHabCode(h); - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code + return 13; + } + else { // Valid habitat code + addHabCode(habCode); + if (patchModel) { + if (patchCode < 0 || patchCode == noDataPatch) { // invalid patch code #if RS_RCPP && !R_CMD - if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; - else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; + if (patchCode == noDataPatch) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; #endif - hfile.close(); hfile.clear(); - pfile.close(); pfile.clear(); - return 14; - } - if (p == 0) { // cell is in the matrix - addNewCellToPatch(0, x, y, h); - } - else { - if (existsPatch(p)) { - pPatch = findPatch(p); - addNewCellToPatch(pPatch, x, y, h); - // addNewCellToPatch(findPatch(p),x,y,h); - } - else { - pPatch = newPatch(seq++, p); - addNewCellToPatch(pPatch, x, y, h); - } - } - } - else { // cell-based model - // add cell to landscape (patches created later) - addNewCellToLand(x, y, h); + ifsHabMap.close(); + ifsHabMap.clear(); + ifsPatchMap.close(); + ifsPatchMap.clear(); + return 14; } + // Does the patch already exists? + pPatch = patchCode == 0 ? nullptr : ( // matrix cell + existsPatch(patchCode) ? + findPatch(patchCode) : + newPatch(seq++, patchCode) + ); + addNewCellToPatch(pPatch, x, y, habCode); + } + else { // cell-based model + // add cell to landscape (patches created later) + addNewCellToLand(x, y, habCode); } } - } - } + + } // for x + } // for y + #if RS_RCPP -hfile >> hfloat; -if (!hfile.eof()) EOFerrorR(pathHabFile); -if (patchModel) -{ - pfile >> pfloat; - if (!pfile.eof()) EOFerrorR(pathPatchFile); -} + ifsHabMap >> habFloat; + if (!ifsHabMap.eof()) EOFerrorR(habfile); + if (patchModel) { + ifsPatchMap >> patchFloat; + if (!ifsPatchMap.eof()) EOFerrorR(pchfile); + } #endif break; case 1: // multiple % cover for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { - hfloat = badhfloat; + + habFloat = badHabFloat; #if RS_RCPP - if (hfile >> hfloat) { + if (ifsHabMap >> habFloat) { + habCode = static_cast(habFloat); + if (fileNum == 0) { // first habitat cover layer + if (patchModel) { + patchFloat = badPatchFloat; + if (ifsPatchMap >> patchFloat) { + patchCode = static_cast(patchFloat); + } + else { + // corrupt file stream +#if !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR(pchfile); + ifsHabMap.close(); + ifsHabMap.clear(); + ifsPatchMap.close(); + ifsPatchMap.clear(); + return 135; + } + } #else - hfile >> hfloat; -#endif - h = (int)hfloat; + ifsHabMap >> habFloat; + habCode = static_cast(habFloat); + if (fileNum == 0) { // first habitat cover layer if (patchModel) { - pfloat = badpfloat; -#if RS_RCPP - if (pfile >> pfloat) { -#else - pfile >> pfloat; -#endif - p = (int)pfloat; -#if RS_RCPP + patchFloat = badPatchFloat; + ifsPatchMap >> patchFloat; + patchCode = static_cast(patchFloat); } - else { - // corrupt file stream -#if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - StreamErrorR(pathPatchFile); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 135; - } -#endif - } //end if patchmodel - - if (h == habnodata) { + if (habCode == noDataHabCode) { addNewCellToLand(x, y, -1); // add cell only to landscape } - else { - if (hfloat < 0.0 || hfloat > 100.0) { // invalid cover score + else if (habFloat < 0.0 || habFloat > 100.0) { // invalid cover score #if RS_RCPP && !R_CMD - Rcpp::Rcout << "Found invalid habitat cover score." << std::endl; + Rcpp::Rcout << "Found invalid habitat cover score." << std::endl; #endif - hfile.close(); hfile.clear(); - if (patchModel) { - pfile.close(); pfile.clear(); - } - return 17; + ifsHabMap.close(); + ifsHabMap.clear(); + if (patchModel) { + ifsPatchMap.close(); + ifsPatchMap.clear(); } - else { - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code + return 17; + } + else { + if (patchModel) { + if (patchCode < 0 || patchCode == noDataPatch) { // invalid patch code #if RS_RCPP && !R_CMD - if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; - else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; + if (patchCode == noDataPatch) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; #endif - hfile.close(); hfile.clear(); - pfile.close(); pfile.clear(); - return 14; - } - if (p == 0) { // cell is in the matrix - addNewCellToPatch(0, x, y, hfloat); - } - else { - if (existsPatch(p)) { - pPatch = findPatch(p); - addNewCellToPatch(pPatch, x, y, hfloat); - // addNewCellToPatch(findPatch(p),x,y,hfloat); - } - else { - pPatch = newPatch(seq++, p); - addNewCellToPatch(pPatch, x, y, hfloat); - } - } - } - else { // cell-based model - // add cell to landscape (patches created later) - addNewCellToLand(x, y, hfloat); + ifsHabMap.close(); + ifsHabMap.clear(); + ifsPatchMap.close(); + ifsPatchMap.clear(); + return 14; } + + pPatch = patchCode == 0 ? nullptr : ( // matrix cell + existsPatch(patchCode) ? + findPatch(patchCode) : + newPatch(seq++, patchCode) + ); + addNewCellToPatch(pPatch, x, y, habFloat); + } + else { // cell-based model + // add cell to landscape (patches created later) + addNewCellToLand(x, y, habFloat); } } } else { // additional habitat cover layers - if (h != habnodata) { - if (hfloat < 0.0 || hfloat > 100.0) { // invalid cover score + if (habCode != noDataHabCode) { + if (habFloat < 0.0 || habFloat > 100.0) { // invalid cover score #if RS_RCPP && !R_CMD - Rcpp::Rcout << "Found invalid habitat cover score." << std::endl; + Rcpp::Rcout << "Found invalid habitat cover score." << std::endl; #endif - hfile.close(); hfile.clear(); + ifsHabMap.close(); + ifsHabMap.clear(); if (patchModel) { - pfile.close(); pfile.clear(); + ifsPatchMap.close(); + ifsPatchMap.clear(); } return 17; } else { - cells[y][x]->setHabitat(hfloat); + cells[y][x]->setHabitat(habFloat); } - } // end of h != habnodata + } } #if RS_RCPP - } -else { // couldn't read from hfile - // corrupt file stream + else { // not ifsHabMap >> habFloat + // corrupt file stream #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; -#endif - StreamErrorR(pathHabFile); - hfile.close(); - hfile.clear(); - if (patchModel) { - pfile.close(); - pfile.clear(); - } - return 133; -} + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - + StreamErrorR(habfile); + ifsHabMap.close(); + ifsHabMap.clear(); + if (patchModel) { + ifsPatchMap.close(); + ifsPatchMap.clear(); } + return 133; } +#endif + + } // for x + } // for y + habIndexed = true; // habitats are already numbered 1...n in correct order + #if RS_RCPP - hfile >> hfloat; - if (!hfile.eof()) EOFerrorR(pathHabFile); - if (patchModel) - { - pfile >> pfloat; - if (!pfile.eof()) EOFerrorR(pathPatchFile); - } + ifsHabMap >> habFloat; + if (!ifsHabMap.eof()) EOFerrorR(habfile); + if (patchModel) { + ifsPatchMap >> patchFloat; + if (!ifsPatchMap.eof()) EOFerrorR(pchfile); + } #endif break; @@ -2113,110 +2120,112 @@ else { // couldn't read from hfile if (fileNum > 0) return 19; // error condition - should not occur for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { - hfloat = badhfloat; -#if RS_RCPP - if (hfile >> hfloat) { -#else - hfile >> hfloat; -#endif - h = (int)hfloat; + + habFloat = badHabFloat; #if RS_RCPP - } - else { - // corrupt file stream -#if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; + if (ifsHabMap >> habFloat) { + habCode = static_cast(habFloat); + + } + else { + // corrupt file stream +#if !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - StreamErrorR(pathHabFile); - hfile.close(); - hfile.clear(); + StreamErrorR(habfile); + ifsHabMap.close(); + ifsHabMap.clear(); + if (patchModel) { + ifsPatchMap.close(); + ifsPatchMap.clear(); + } + return 134; + } if (patchModel) { - pfile.close(); - pfile.clear(); - } - return 134; - } -#endif - if (patchModel) { - pfloat = badpfloat; -#if RS_RCPP - if (pfile >> pfloat) { -#else - pfile >> pfloat; -#endif - p = (int)pfloat; -#if RS_RCPP - } - else { - // corrupt file stream + patchFloat = badPatchFloat; + if (ifsPatchMap >> patchFloat) { + patchCode = static_cast(patchFloat); + } + else { + // corrupt file stream #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; -#endif - StreamErrorR(pathPatchFile); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 135; - } + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif + StreamErrorR(pchfile); + ifsHabMap.close(); + ifsHabMap.clear(); + ifsPatchMap.close(); + ifsPatchMap.clear(); + return 135; + } + } +#else + ifsHabMap >> habFloat; + habCode = static_cast(habFloat); + if (patchModel) { + patchFloat = badPatchFloat; + ifsPatchMap >> patchFloat; + patchCode = static_cast(patchFloat); } - if (h == habnodata) { +#endif + if (habCode == noDataHabCode) { addNewCellToLand(x, y, -1); // add cell only to landscape } - else { - if (hfloat < 0.0 || hfloat > 100.0) { // invalid quality score + else if (habFloat < 0.0 || habFloat > 100.0) { // invalid quality score #if RS_RCPP && !R_CMD - Rcpp::Rcout << "Found invalid habitat quality score." << std::endl; + Rcpp::Rcout << "Found invalid habitat quality score." << std::endl; #endif - hfile.close(); hfile.clear(); - if (patchModel) { - pfile.close(); pfile.clear(); - } - return 17; + ifsHabMap.close(); + ifsHabMap.clear(); + if (patchModel) { + ifsPatchMap.close(); + ifsPatchMap.clear(); } - else { - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code + return 17; + } + else { + if (patchModel) { + if (patchCode < 0 || patchCode == noDataPatch) { // invalid patch code #if RS_RCPP && !R_CMD - if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; - else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; + if (patchCode == noDataPatch) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; #endif - hfile.close(); hfile.clear(); - pfile.close(); pfile.clear(); - return 14; - } - if (p == 0) { // cell is in the matrix - addNewCellToPatch(0, x, y, hfloat); + ifsHabMap.close(); + ifsHabMap.clear(); + ifsPatchMap.close(); + ifsPatchMap.clear(); + return 14; + } + if (patchCode == 0) { // cell is in the matrix + addNewCellToPatch(0, x, y, habFloat); } else { - if (existsPatch(p)) { - pPatch = findPatch(p); - addNewCellToPatch(pPatch, x, y, hfloat); - // addNewCellToPatch(findPatch(p),x,y,hfloat); + if (existsPatch(patchCode)) { + pPatch = findPatch(patchCode); } else { - pPatch = newPatch(seq++, p); - addNewCellToPatch(pPatch, x, y, hfloat); + pPatch = newPatch(seq++, patchCode); } + addNewCellToPatch(pPatch, x, y, habFloat); } - } - else { // cell-based model - // add cell to landscape (patches created later) - addNewCellToLand(x, y, hfloat); - } + } + else { // cell-based model + // add cell to landscape (patches created later) + addNewCellToLand(x, y, habFloat); } } - } - } + + } // for x + } // for y + #if RS_RCPP - hfile >> hfloat; - if (!hfile.eof()) EOFerrorR(pathHabFile); - if (patchModel) - { - pfile >> pfloat; - if (!pfile.eof()) EOFerrorR(pathPatchFile); - } + ifsHabMap >> habFloat; + if (!ifsHabMap.eof()) EOFerrorR(habfile); + if (patchModel) + { + ifsPatchMap >> patchFloat; + if (!ifsPatchMap.eof()) EOFerrorR(pchfile); + } #endif break; @@ -2224,8 +2233,14 @@ else { // couldn't read from hfile break; } // end switch(rasterType) - if (hfile.is_open()) { hfile.close(); hfile.clear(); } - if (pfile.is_open()) { pfile.close(); pfile.clear(); } + if (ifsHabMap.is_open()) { + ifsHabMap.close(); + ifsHabMap.clear(); + } + if (ifsPatchMap.is_open()) { + ifsPatchMap.close(); + ifsPatchMap.clear(); + } if (sim.batchMode) { if (costfile != "NULL") { @@ -2235,7 +2250,6 @@ else { // couldn't read from hfile } return 0; - } //--------------------------------------------------------------------------- From 114c9094aba849e5b4c1f0563e54fde222cec0e4 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 17 Jul 2025 16:38:46 +0100 Subject: [PATCH 314/332] bug in calculation of Ho: heterogeneity shouldn't be an integer --- Community.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Community.cpp b/Community.cpp index dab4a41..8eb0b77 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1754,12 +1754,14 @@ void Community::writePerLocusFstatFile(Species* pSpecies, const int yr, const in } } +// Calculate the observed heterozygosity (Ho) for a patch +// = number of heterozygous individuals at this locus / nb individuals in patch float Community::getPatchHet(Species* pSpecies, int patchId, int whichLocus) const { const auto patch = pLandscape->findPatch(patchId); const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); int nAlleles = pSpecies->getSpTrait(NEUTRAL)->getNbNeutralAlleles(); int popSize = 0; - int het = 0; + float het = 0; if (pPop != 0) { popSize = pPop->sampleSize(); if (popSize == 0) return -1.0; @@ -1767,7 +1769,7 @@ float Community::getPatchHet(Species* pSpecies, int patchId, int whichLocus) con for (int a = 0; a < nAlleles; ++a) { het += static_cast(pPop->getHeteroTally(whichLocus, a)); } - het /= (2.0 * popSize); + het /= popSize; return het; } } From f350ce737df2a8937faf659d17d2583075dbb310 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 22 Jul 2025 11:53:35 +0100 Subject: [PATCH 315/332] fixing git merge mistakes --- Community.h | 4 +--- Individual.cpp | 55 ++++++++++++++++++++++++------------------------ Model.cpp | 15 ++----------- Patch.cpp | 2 +- Patch.h | 1 + Population.cpp | 6 +++--- SubCommunity.cpp | 12 ++++++++++- SubCommunity.h | 26 ++++++++++++++--------- 8 files changed, 62 insertions(+), 59 deletions(-) diff --git a/Community.h b/Community.h index ddf157a..2e6bc5e 100644 --- a/Community.h +++ b/Community.h @@ -166,9 +166,7 @@ class Community { // Open occupancy file, write header record and set up occupancy array bool outOccupancyStartLandscape(); void outOccupancy(void); - void outOccSuit( - bool // TRUE if occupancy graph is to be viewed on screen - ); + void outOccSuit(); bool outTraitsFinishLandscape(); // Close traits file bool outTraitsStartLandscape( // Open traits file and write header record Species*, // pointer to Species diff --git a/Individual.cpp b/Individual.cpp index 72b6a8b..c4e3870 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -108,7 +108,7 @@ TraitFactory Individual::traitFactory = TraitFactory(); // Individual constructor Individual::Individual(Species* pSpecies, Cell* pCell, Patch* pPatch, short stg, short a, short repInt, float probmale, bool movt, short moveType): - memory(pSpecies->getSMSTraits().memSize) + memory(pSpecies->getSpSMSTraits().memSize) { indId = indCounter; indCounter++; // unique identifier for each individual geneticFitness = 1.0; @@ -828,10 +828,11 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, const bool loopsteps++; } while (loopsteps < 1000 && // keep drawing if out of bounds of landscape or same cell - ((!absorbing && (newX < land.minX || newX > land.maxX - || newY < land.minY || newY > land.maxY)) + ((!absorbing + && (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY)) || (!usefullkernel && newX == loc.x && newY == loc.y)) ); + if (loopsteps < 1000) { if (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY) { // beyond absorbing boundary @@ -856,6 +857,7 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, const bool } } } + } else { // exceeded 1000 attempts pPatch = nullptr; patch = 0; @@ -993,10 +995,8 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, dispersing = 0; } else { - // WOULD IT BE MORE EFFICIENT FOR smsMove TO RETURN A POINTER TO THE NEW CELL? ... pPatch = pCurrCell->getPatch(); - } if (sim.saveVisits && pPatch != pNatalPatch) { pCurrCell->incrVisits(); } @@ -1176,23 +1176,23 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, // first check if costs have already been calculated { #ifdef _OPENMP - const std::unique_lock lock = pCurrCell->lockCost(); + const std::unique_lock lock = pCurrCell->lockCost(); #endif - hab = pCurrCell->getEffCosts(); - if (hab.cell[0][0] < 0.0) { // costs have not already been calculated - hab = getHabMatrix(pLand, pSpecies, current.x, current.y, movt.pr, movt.prMethod, - landIx, absorbing); - pCurrCell->setEffCosts(hab); - } - else { // they have already been calculated - no action required + hab = pCurrCell->getEffCosts(); + if (hab.cell[0][0] < 0.0) { // costs have not already been calculated + hab = getHabMatrix(pLand, pSpecies, current.x, current.y, movt.pr, movt.prMethod, + landIx, absorbing); + pCurrCell->setEffCosts(hab); + } + else { // they have already been calculated - no action required - } + } } // determine weighted effective cost for the 8 neighbours // multiply directional persistence, goal bias and habitat habitat-dependent weights - for (y2 = 2; y2 > -1; y2--) { - for (x2 = 0; x2 < 3; x2++) { + for (int y2 = 2; y2 > -1; y2--) { + for (int x2 = 0; x2 < 3; x2++) { if (x2 == 1 && y2 == 1) nbr.cell[x2][y2] = 0.0; else { if (x2 == 1 || y2 == 1) //not diagonal @@ -1204,8 +1204,8 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, } // determine reciprocal of effective cost for the 8 neighbours - for (y2 = 2; y2 > -1; y2--) { - for (x2 = 0; x2 < 3; x2++) { + for (int y2 = 2; y2 > -1; y2--) { + for (int x2 = 0; x2 < 3; x2++) { if (nbr.cell[x2][y2] > 0.0) nbr.cell[x2][y2] = 1.0f / nbr.cell[x2][y2]; } } @@ -1214,8 +1214,8 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, // to have zero probability // increment total for re-scaling to sum to unity - for (y2 = 2; y2 > -1; y2--) { - for (x2 = 0; x2 < 3; x2++) { + for (int y2 = 2; y2 > -1; y2--) { + for (int x2 = 0; x2 < 3; x2++) { if (!absorbing) { if ((current.y + y2 - 1) < land.minY || (current.y + y2 - 1) > land.maxY || (current.x + x2 - 1) < land.minX || (current.x + x2 - 1) > land.maxX) @@ -1232,8 +1232,8 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, // scale effective costs as probabilities summing to 1 if (sum_nbrs > 0.0) { // should always be the case, but safest to check... - for (y2 = 2; y2 > -1; y2--) { - for (x2 = 0; x2 < 3; x2++) { + for (int y2 = 2; y2 > -1; y2--) { + for (int x2 = 0; x2 < 3; x2++) { nbr.cell[x2][y2] = nbr.cell[x2][y2] / (float)sum_nbrs; } } @@ -1243,8 +1243,8 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, double cumulative[9]; int j = 0; cumulative[0] = nbr.cell[0][0]; - for (y2 = 0; y2 < 3; y2++) { - for (x2 = 0; x2 < 3; x2++) { + for (int y2 = 0; y2 < 3; y2++) { + for (int x2 = 0; x2 < 3; x2++) { if (j != 0) cumulative[j] = cumulative[j - 1] + nbr.cell[x2][y2]; j++; } @@ -1260,8 +1260,8 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, do { double rnd = pRandom->Random(); j = 0; - for (y2 = 0; y2 < 3; y2++) { - for (x2 = 0; x2 < 3; x2++) { + for (int y2 = 0; y2 < 3; y2++) { + for (int x2 = 0; x2 < 3; x2++) { if (rnd < cumulative[j]) { newX = current.x + x2 - 1; newY = current.y + y2 - 1; @@ -1673,8 +1673,7 @@ double cauchy(double location, double scale) { //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -#if RSDEBUG - +#ifndef NDEBUG void testIndividual() { diff --git a/Model.cpp b/Model.cpp index 8b71256..ba19f30 100644 --- a/Model.cpp +++ b/Model.cpp @@ -458,21 +458,10 @@ int RunModel(Landscape* pLandscape, int seqsim) // output Individuals if (sim.outInds && yr >= sim.outStartInd && yr % sim.outIntInd == 0) - pComm->outInds(rep, yr, gen, -1); - - // survival part 1 - if (dem.stageStruct) { - pComm->survival(1, 0, 1); - } - else { // non-structured population - pComm->survival(1, 0, 1); - } -#if RSDEBUG - DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed survival part 1" << endl; -#endif + pComm->outIndividuals(rep, yr, gen); // Resolve survival and devlpt - pComm->survival(1, 0, 1); + pComm->survival1(); } // end of the generation loop diff --git a/Patch.cpp b/Patch.cpp index 19d53bf..83dcb0d 100644 --- a/Patch.cpp +++ b/Patch.cpp @@ -312,7 +312,7 @@ int Patch::getPossSettlers(Species* pSpecies, int sex) { } bool Patch::speciesIsPresent(Species* pSpecies) { - const auto pPop = this->getPopn((intptr)pSpecies); + const auto pPop = this->getPopn(pSpecies); return pPop != 0; } diff --git a/Patch.h b/Patch.h index 1f7852e..df65b62 100644 --- a/Patch.h +++ b/Patch.h @@ -153,6 +153,7 @@ class Patch { bool // TRUE if there is a gradient in carrying capacity across the Landscape ); float getK(void); + bool speciesIsPresent(Species* pSpecies); private: int patchSeqNum;// sequential patch number - patch 0 is reserved for the inter-patch matrix diff --git a/Population.cpp b/Population.cpp index 56c4ffe..22c302a 100644 --- a/Population.cpp +++ b/Population.cpp @@ -176,7 +176,7 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) } else age = stg; - Individual* newInd = new Individual(pCell, pPatch, stg, age, sstruct.repInterval, + Individual* newInd = new Individual(pSpecies, pCell, pPatch, stg, age, sstruct.repInterval, probmale, trfr.usesMovtProc, trfr.moveType); if (pSpecies->getNTraits() > 0) { @@ -655,7 +655,7 @@ void Population::reproduction(const float localK, const float envval, const int for (int j = 0; j < njuvs; j++) { Individual* newJuv; - newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.usesMovtProc, trfr.moveType); + newJuv = new Individual(pSpecies, pCell, pPatch, 0, 0, 0, dem.propMales, trfr.usesMovtProc, trfr.moveType); if (pSpecies->getNTraits() > 0) { newJuv->inheritTraits(pSpecies, inds[i], resol); @@ -733,7 +733,7 @@ void Population::reproduction(const float localK, const float envval, const int for (int j = 0; j < njuvs; j++) { Individual* newJuv; - newJuv = new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.usesMovtProc, trfr.moveType); + newJuv = new Individual(pSpecies, pCell, pPatch, 0, 0, 0, dem.propMales, trfr.usesMovtProc, trfr.moveType); if (pSpecies->getNTraits() > 0) { newJuv->inheritTraits(pSpecies, inds[i], father, resol); diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 28ea16f..d53ccb9 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -134,7 +134,7 @@ void SubCommunity::initialInd(Landscape* pLandscape, Species* pSpecies, else { if (iind.sex == 1) probmale = 1.0; else probmale = 0.0; } - pInd = new Individual(pSpecies, pCell, pPatch, stg, age, repInt, probmale, trfr.moveModel, trfr.moveType); + pInd = new Individual(pSpecies, pCell, pPatch, stg, age, repInt, probmale, trfr.usesMovtProc, trfr.moveType); if (pSpecies->getNTraits() > 0) { // individual variation - set up genetics @@ -436,6 +436,16 @@ void SubCommunity::survival1() } } +void SubCommunity::survival(short part, short option0, short option1 +) { + if (part == 0) { + return survival0(option0, option1); + } + else { + return survival1(); + } +} + void SubCommunity::ageIncrement(void) { int npops = (int)popns.size(); for (int i = 0; i < npops; i++) { // all populations diff --git a/SubCommunity.h b/SubCommunity.h index 1284905..9b3a88f 100644 --- a/SubCommunity.h +++ b/SubCommunity.h @@ -123,22 +123,20 @@ class SubCommunity { Landscape*, // pointer to Landscape bool // TRUE to increment connectivity totals ); + + void survival0(short option0, short option1); + void survival1(); + void survival( - short, // part: 0 = determine survival & development, + short, // part: 0 = determine survival & development, // 1 = apply survival changes to the population short, // option0: 0 = stage 0 (juveniles) only ) // 1 = all stages ) used by part 0 only // 2 = stage 1 and above (all non-juvs) ) short // option1: 0 - development only (when survival is annual) - // 1 - development and survival - ) { - if (part == 0) { - return survival0(option0, option1); - } - else { - return survival1(); - } - } + // 1 - development and survival + ); + void ageIncrement(void); // Find the population of a given species in a given patch @@ -189,6 +187,14 @@ class SubCommunity { Species*, // pointer to Species int // Landscape number ); + + + // Close traits file + bool outTraitsFinishLandscape(); + + // Open traits file and write header record + bool outTraitsStartLandscape(Landscape* pLandscape, Species* pSpecies, int landNr); + traitsums outTraits( // Write records to traits file and return aggregated sums Landscape*, // pointer to Landscape int, // replicate From 091ebe44bfba503fc6d5ddd0a5f1a15b68887723 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 22 Jul 2025 12:21:32 +0100 Subject: [PATCH 316/332] resolving more merge mistakes --- Community.cpp | 10 +++++----- Individual.cpp | 3 --- NeutralStatsManager.cpp | 24 ++++++++++++------------ Patch.cpp | 4 ++-- RSrandom.cpp | 36 +++++++++++++++++++++++++----------- RSrandom.h | 1 + 6 files changed, 45 insertions(+), 33 deletions(-) diff --git a/Community.cpp b/Community.cpp index add7590..06830c1 100644 --- a/Community.cpp +++ b/Community.cpp @@ -325,7 +325,7 @@ void Community::addManuallySelected(void) { if (pCell != 0) { // not no-data cell pPatch = pCell->getPatch(); if (pPatch != nullptr) { - pSubcomm = pPatch->getSubComm(); + pSubComm = pPatch->getSubComm(); if (pSubComm != nullptr) { pSubComm->setInitial(true); } @@ -1553,7 +1553,7 @@ void Community::outputGeneValues(const int& year, const int& gen, Species* pSpec if (patch == 0) { throw runtime_error("Sampled patch does not exist"); } - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + const auto pPop = patch->getPopn(pSpecies); if (pPop != 0) { pPop->outputGeneValues(ofsGenes, year, gen); } @@ -1575,7 +1575,7 @@ void Community::sampleIndividuals(Species* pSpecies) { if (patch == 0) { throw runtime_error("Can't sample individuals: patch" + to_string(patchId) + "doesn't exist."); } - auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + auto pPop = patch->getPopn(pSpecies); if (pPop != 0) { pPop->sampleIndsWithoutReplacement(nbIndsToSample, stagesToSampleFrom); } @@ -1783,7 +1783,7 @@ void Community::writePerLocusFstatFile(Species* pSpecies, const int yr, const in // = number of heterozygous individuals at this locus / nb individuals in patch float Community::getPatchHet(Species* pSpecies, int patchId, int whichLocus) const { const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + const auto pPop = patch->getPopn(pSpecies); int nAlleles = pSpecies->getSpTrait(NEUTRAL)->getNbNeutralAlleles(); int popSize = 0; float het = 0; @@ -1850,7 +1850,7 @@ void Community::outNeutralGenetics(Species* pSpecies, int rep, int yr, int gen, if (patch == 0) { throw runtime_error("Sampled patch does not exist"); } - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + const auto pPop = patch->getPopn(pSpecies); if (pPop != 0) { // empty patches do not contribute nInds += pPop->sampleSize(); nbPops++; diff --git a/Individual.cpp b/Individual.cpp index c4e3870..93f03a4 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -726,8 +726,6 @@ void Individual::moveto(Cell* newCell) { // Returns 1 if still dispersing (including having found a potential patch), otherwise 0 int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, const bool absorbing) { - intptr patch; - intptr patch; int patchNum = 0; int newX = 0, newY = 0; int dispersing = 1; @@ -860,7 +858,6 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, const bool } else { // exceeded 1000 attempts pPatch = nullptr; - patch = 0; patchNum = -1; } } while (!absorbing && patchNum < 0 && loopsteps < 1000); // in a no-data region diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index 7ae03ee..14e216d 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -61,7 +61,7 @@ void NeutralStatsManager::updateAllNeutralTables(Species* pSpecies, Landscape* p // Update counts for each population for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + const auto pPop = patch->getPopn(pSpecies); if (pPop != 0) { // Update this population's NEUTRAL counts tables pPop->updatePopNeutralTables(); @@ -121,7 +121,7 @@ void NeutralStatsManager::calcAllelicDiversityMetrics(set const& patchList, // Compute mean nb alleles per locus per patch for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + const auto pPop = patch->getPopn(pSpecies); if (pPop != 0) { if (pPop->sampleSize() > 0) { nbPops++; @@ -152,7 +152,7 @@ void NeutralStatsManager::calcAllelicDiversityMetrics(set const& patchList, if (nbPops > 0) { for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + const auto pPop = patch->getPopn(pSpecies); if (pPop != 0) { for (i = 0; i < nLoci; ++i) for (j = 0; j < nAlleles; ++j) @@ -181,7 +181,7 @@ void NeutralStatsManager::calculateHo(set const& patchList, const int nbInd if (nbInds != 0 && pSpecies->isDiploid()) { for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + const auto pPop = patch->getPopn(pSpecies); if (pPop != 0) nbHetero += pPop->countHeterozygoteLoci(); } ho = static_cast(nbHetero) / (nbInds * nbrLoci); @@ -201,7 +201,7 @@ void NeutralStatsManager::calculateHs(set const& patchList, const int nbrLo for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + const auto pPop = patch->getPopn(pSpecies); if (pPop->sampleSize() > 0) { nPatches++; hs += pPop->computeHs(); @@ -246,7 +246,7 @@ void NeutralStatsManager::calculatePerLocusHo(set const& patchList, const i if (pSpecies->isDiploid()) { for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + const auto pPop = patch->getPopn(pSpecies); if (pPop != 0) { if (pPop->sampleSize() > 0) { nbHeterosInPop = pPop->countNbHeterozygotesEachLocus(); @@ -282,7 +282,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + const auto pPop = patch->getPopn(pSpecies); if (pPop != 0) { int popSampleSize = pPop->sampleSize(); // n_i if (popSampleSize > 0) { @@ -324,7 +324,7 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int pBar = commNeutralCountTables[l].getFrequency(u); for (int patchId : patchList) { const auto patch = pLandscape->findPatch(patchId); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + const auto pPop = patch->getPopn(pSpecies); if (pPop != 0) { var = pPop->getAlleleFrequency(l, u) - pBar; var *= var; @@ -411,7 +411,7 @@ void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, con // Calculate weight (n_ic) terms for (int i = 0; i < nPatches; ++i) { const auto patch = pLandscape->findPatch(patchVect[i]); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + const auto pPop = patch->getPopn(pSpecies); if (pPop != 0) { popSizes[i] = pPop->sampleSize(); } // else popSizes[i] remain default init value 0, safe @@ -432,7 +432,7 @@ void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, con for (int i = 0; i < nPatches; ++i) { if (popSizes[i] == 0) continue; const auto patch = pLandscape->findPatch(patchVect[i]); - const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); + const auto pPop = patch->getPopn(pSpecies); for (int l = 0; l < nLoci; ++l) { for (int u = 0; u < nAlleles; ++u) { @@ -471,12 +471,12 @@ void NeutralStatsManager::calcPairwiseWeightedFst(set const& patchList, con for (int i = 0; i < nPatches - 1; ++i) { // nPatches-1 bc bottom row not filled if (popSizes[i] == 0) continue; const auto patch = pLandscape->findPatch(patchVect[i]); - const auto pPopI = (Population*)patch->getPopn((intptr)pSpecies); + const auto pPopI = patch->getPopn(pSpecies); for (int j = i + 1; j < nPatches; ++j) { // fill only upper half of matrix if (popSizes[j] == 0) continue; const auto patch = pLandscape->findPatch(patchVect[j]); - const auto pPopJ = (Population*)patch->getPopn((intptr)pSpecies); + const auto pPopJ = patch->getPopn(pSpecies); pi = pPopI->getAlleleFrequency(l, u); pj = pPopJ->getAlleleFrequency(l, u); diff --git a/Patch.cpp b/Patch.cpp index 83dcb0d..a29f99f 100644 --- a/Patch.cpp +++ b/Patch.cpp @@ -263,7 +263,7 @@ void Patch::setSubComm(SubCommunity* sc) } // Get pointer to corresponding Sub-community -SubCommunity *Patch::getSubComm(void) +SubCommunity* Patch::getSubComm(void) { return subCommPtr; } #ifdef _OPENMP @@ -277,7 +277,7 @@ void Patch::addPopn(patchPopn pop) { } // Return pointer to the Population of the specified Species -Population *Patch::getPopn(Species *sp) +Population* Patch::getPopn(Species *sp) { int npops = (int)popns.size(); for (int i = 0; i < npops; i++) { diff --git a/RSrandom.cpp b/RSrandom.cpp index b356956..3ae7b1a 100644 --- a/RSrandom.cpp +++ b/RSrandom.cpp @@ -85,10 +85,11 @@ RSrandom::RSrandom() { gens.reserve(nb_generators); for (int i = 0; i < nb_generators; i++) gens.emplace_back(RS_random_seed + i); -#else // _OPENMP +#else gens.reserve(1); gens.emplace_back(RS_random_seed); #endif // _OPENMP + // Set up standard uniform distribution pRandom01 = new uniform_real_distribution(0.0, 1.0); // Set up standard normal distribution @@ -116,7 +117,7 @@ double RSrandom::Random() { // return random number between 0 and 1 #ifdef _OPENMP return pRandom01->operator()(gens[omp_get_thread_num() % gens.size()]); -#else // _OPENMP +#else return pRandom01->operator()(gens[0]); #endif // _OPENMP } @@ -129,17 +130,21 @@ int RSrandom::IRandom(int min, int max) { uniform_int_distribution unif(min, max); #ifdef _OPENMP return unif(gens[omp_get_thread_num() % gens.size()]); -#else // _OPENMP +#else return unif(gens[0]); #endif // _OPENMP } float RSrandom::FRandom(float min, float max) { - if (min == max) - return min; + if (min == max) return min; // return random double in the interval min <= x <= max uniform_real_distribution unif(min, max); - return unif(*gen); + +#ifdef _OPENMP + return unif(gens[omp_get_thread_num() % gens.size()]); +#else + return unif(gens[0]); +#endif } int RSrandom::Bernoulli(double p) { @@ -154,13 +159,17 @@ int RSrandom::Bernoulli(double p) { int RSrandom::Binomial(const int& n, const double& p) { binomial_distribution binom(n, p); - return binom(*gen); +#ifdef _OPENMP + return binom(gens[omp_get_thread_num() % gens.size()]); +#else + return binom(gens[0]); +#endif } double RSrandom::Normal(double mean, double sd) { #ifdef _OPENMP return mean + sd * pNormal->operator()(gens[omp_get_thread_num() % gens.size()]); -#else // _OPENMP +#else return mean + sd * pNormal->operator()(gens[0]); #endif // _OPENMP } @@ -169,7 +178,7 @@ int RSrandom::Poisson(double mean) { poisson_distribution poiss(mean); #ifdef _OPENMP return poiss(gens[omp_get_thread_num() % gens.size()]); -#else // _OPENMP +#else return poiss(gens[0]); #endif // _OPENMP } @@ -180,7 +189,7 @@ double RSrandom::Gamma(double shape, double scale) { //scale = mean/shape, shap #ifdef _OPENMP double x = poiss(gens[omp_get_thread_num() % gens.size()]); -#else // _OPENMP +#else double x = gamma(gens[0]); #endif // _OPENMP if (scale < 0) x = -x; @@ -194,7 +203,12 @@ double RSrandom::NegExp(double mean) { } void RSrandom::fixNewSeed(int seed) { - gen->seed(seed); +#ifdef _OPENMP + for (int i = 0; i < omp_get_max_threads(); i++) + gens[i].seed(seed + i); +#else + gens[0].seed(seed); +#endif // _OPENMP } //-------------------------------------------------------------------------------------------------- diff --git a/RSrandom.h b/RSrandom.h index d57a28b..afea808 100644 --- a/RSrandom.h +++ b/RSrandom.h @@ -79,6 +79,7 @@ class RSrandom seed_t getSeed() const { return RS_random_seed; }; private: + seed_t RS_random_seed; std::vector gens; std::uniform_real_distribution<>* pRandom01; std::normal_distribution<>* pNormal; From 5f254337c57157cd2e2404664e0a953c09688dee Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 22 Jul 2025 14:47:18 +0100 Subject: [PATCH 317/332] solved linker issues raised by develop merge --- Community.cpp | 12 ------------ Community.h | 5 ----- Model.cpp | 23 ++++++++++++++++++++++- SubCommunity.cpp | 6 +++++- SubCommunity.h | 5 ----- 5 files changed, 27 insertions(+), 24 deletions(-) diff --git a/Community.cpp b/Community.cpp index 06830c1..5c6ec7b 100644 --- a/Community.cpp +++ b/Community.cpp @@ -575,7 +575,6 @@ void Community::outPop(int rep, int yr, int gen) } - // Close individuals file void Community::outIndsFinishReplicate() { subComms[0]->outIndsFinishReplicate(); @@ -595,17 +594,6 @@ void Community::outIndividuals(int rep, int yr, int gen) { } } -// Close genetics file -void Community::outGenFinishReplicate() { - subComms[0]->outGenFinishReplicate(); -} - -// Open genetics file and write header record -void Community::outGenStartReplicate(int rep, int landNr) { - subComms[0]->outGenStartReplicate(rep, landNr); -} - - // Close range file bool Community::outRangeFinishLandscape() { diff --git a/Community.h b/Community.h index 2e6bc5e..ab847f9 100644 --- a/Community.h +++ b/Community.h @@ -156,11 +156,6 @@ class Community { int, // year int // generation ); - void outGenFinishReplicate(); // Close genetics file - void outGenStartReplicate( // Open genetics file and write header record - int, // replicate - int // Landscape number - ); // Close occupancy file bool outOccupancyFinishLandscape(); // Open occupancy file, write header record and set up occupancy array diff --git a/Model.cpp b/Model.cpp index ba19f30..ff16a67 100644 --- a/Model.cpp +++ b/Model.cpp @@ -124,7 +124,6 @@ int RunModel(Landscape* pLandscape, int seqsim) for (int i = 0; i < npatches; i++) { ppp = pLandscape->getPatchData(i); pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES - pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES } if (sim.patchSamplingOption == "random") { // Then patches must be resampled for new landscape @@ -460,6 +459,28 @@ int RunModel(Landscape* pLandscape, int seqsim) if (sim.outInds && yr >= sim.outStartInd && yr % sim.outIntInd == 0) pComm->outIndividuals(rep, yr, gen); + if ((sim.outputGeneValues || sim.outputWeirCockerham || sim.outputWeirHill) + && yr >= sim.outStartGenetics + && yr % sim.outputGeneticInterval == 0) { + + simParams sim = paramsSim->getSim(); + if (sim.patchSamplingOption != "list" && sim.patchSamplingOption != "random") { + // then patches must be re-sampled every gen + int nbToSample = pSpecies->getNbPatchesToSample(); + auto patchesToSample = pLandscape->samplePatches(sim.patchSamplingOption, nbToSample, pSpecies); + pSpecies->setSamplePatchList(patchesToSample); + } + // otherwise always use the user-specified list (even if patches are empty) + pComm->sampleIndividuals(pSpecies); + + if (sim.outputGeneValues) { + pComm->outputGeneValues(yr, gen, pSpecies); + } + if (sim.outputWeirCockerham || sim.outputWeirHill) { + pComm->outNeutralGenetics(pSpecies, rep, yr, gen, sim.outputWeirCockerham, sim.outputWeirHill); + } + } + // Resolve survival and devlpt pComm->survival1(); diff --git a/SubCommunity.cpp b/SubCommunity.cpp index d53ccb9..befde3e 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -583,7 +583,11 @@ void SubCommunity::outPop(Landscape* pLandscape, int rep, int yr, int gen) // Close individuals file void SubCommunity::outIndsFinishReplicate() { - popns[0]->outIndsFinishReplicate(); + // as all populations have been deleted, set up a dummy one + Population* pPop = new Population(); + pPop->outIndsFinishReplicate(); + delete pPop; + return; } // Open individuals file and write header record diff --git a/SubCommunity.h b/SubCommunity.h index 9b3a88f..8fd13a1 100644 --- a/SubCommunity.h +++ b/SubCommunity.h @@ -177,11 +177,6 @@ class SubCommunity { int, // year int // generation ); - void outGenFinishReplicate(); // Close genetics file - void outGenStartReplicate( // Open genetics file and write header record - int, // replicate - int // Landscape number - ); bool outTraitsHeaders( // Open traits file and write header record Landscape*, // pointer to Landscape Species*, // pointer to Species From 5aea4186b1b226992da792bbc2e49014d9ba4310 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Fri, 25 Jul 2025 10:52:53 +0200 Subject: [PATCH 318/332] Integrated option for file inputs for spatial demographic scaling added new function to read in demographic scaling functions adapted readLandscape() and readLandChange() functions to hand over scaling layer files Still need to update the repo with the new_genetics + develop branch --- Landscape.cpp | 140 ++++++++++++++++++++++++++++++++++++++++++++++++-- Landscape.h | 7 ++- Model.cpp | 4 -- 3 files changed, 141 insertions(+), 10 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index ffd10e2..c602d98 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -1372,7 +1372,7 @@ int Landscape::readLandChange(int filenum, Rcpp::NumericMatrix habfile, Rcpp::Nu #endif #if RS_RCPP && !R_CMD // normal file input -int Landscape::readLandChange(int filenum, bool costs, wifstream& hfile, wifstream& pfile, wifstream& cfile, int habnodata, int pchnodata, int costnodata) +int Landscape::readLandChange(int filenum, bool costs, wifstream& hfile, wifstream& pfile, wifstream& cfile, int habnodata, int pchnodata, int costnodata, vector scalinglayers) #else int Landscape::readLandChange(int filenum, bool costs) #endif @@ -2029,7 +2029,6 @@ void Landscape::clearInitCells(void) { // RS_THREADSAFE and SPATIALDEMOG #if RS_RCPP int Landscape::readLandscape(int fileNum, Rcpp::NumericMatrix habfile, Rcpp::NumericMatrix pchfile, Rcpp::NumericMatrix costfile, Rcpp::NumericVector scalinglayers) { - if (fileNum < 0) return 19; int h,seq,p,ncols,nrows,hc,maxcost = 0; @@ -2204,7 +2203,6 @@ int Landscape::readLandscape(int fileNum, Rcpp::NumericMatrix habfile, Rcpp::Num for (int y = dimY-1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { - hfloat = habfile(dimY-1-y,x); if ( R_IsNA(hfloat) ) { // check for NA addNewCellToLand(x,y,-1); // add cell only to landscape @@ -2325,7 +2323,7 @@ int Landscape::readLandscape(int fileNum, Rcpp::NumericMatrix habfile, Rcpp::Num } #endif -int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string costfile) +int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string costfile, vector scalinglayers) // vector scalinglayers is the vector of filenames for spatial demography of year 1 { // fileNum == 0 for (first) habitat file and optional patch file // fileNum > 0 for subsequent habitat files under the %cover option @@ -2818,6 +2816,12 @@ case 2: // habitat quality if (costfile != "NULL") { int retcode = readCosts(costfile); if (retcode < 0) return 54; + } + if (scalinglayers.size() > 0) { + if (scalinglayers.size() == nDSlayer) { + int retcode = readDemographicScaling(scalinglayers); + if (retcode < 0) return 54; //change number + } } } @@ -2945,6 +2949,134 @@ return maxcost; } + //--------------------------------------------------------------------------- + int Landscape::readDemographicScaling(vector scalinglayers){ + // Create a temporary landscape to store the vectors for each cell + // I bet there is a better way to implement it, but I couldn't think of it for now + // each cell will contain a vector of three floats + std::vector>> landscape(dimY, + std::vector>(dimX, + std::vector(scalinglayers.size(), 0.0f))); //length of string is determined by DSlayer + +#if RS_RCPP + wstring header; +#else + string header; +#endif + + int DSnb = 0; // first position is 0 + int DS; + int DSnodata; + float DSfloat; // float for reading in data from file + +#if RS_RCPP + wifstream DSfile; // DS file input stream +#else + ifstream DSfile; // DS file input stream +#endif + + + + // for each element of scalinglayers + for (const auto& DSlayer : scalinglayers) { //DSlayer is a reference to file string + // open file + DSfile.open(DSlayer.c_str()); + // if file couldn't be opened, return a failure message (and the readLandscape function: close all file connections and exit) + if (!DSfile.is_open()) return -11; // might need to change the code number + + // if it opened + // skip header, but store no data value + for (int i = 0; i < 5; i++) + DSfile >> header >> DSfloat; + DSfile >> header >> DSnodata; // 6th line + +#if RS_RCPP + if (!DSfile.good()) { + // corrupt file stream + StreamErrorR(DSlayer); + DSfile.close(); + DSfile.clear(); + //do I also need to close the habitat, and potentially patchfile? or is this taken care of? + return -181; // need to change the code + } +#endif + + // set badfloat + float badDSfloat = -9.0; if (DSnodata == -9) DSfloat = -99.0; + + // loop over landscape x+y + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + // read in cell value + DSfloat = badDSfloat; // set to bad float value + // do I need to check this value for any inconsistencies? -> better safe than sorry +#if RS_RCPP + if (DSfile >> DSfloat) { +#else + DSfile >> DSfloat; +#endif + // DS = (int)DSfloat; I guess non integer values are totally fine? +#if RS_RCPP + } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR(DSlayer); + DSfile.close(); + DSfile.clear(); + return -134; // need to change number code + } +#endif + // check if the value is a no data value + if (DSfloat == DSnodata) { + // if it is, do I need to do anything? + } + else { + if (DSfloat < 0.0 || DSfloat > 100.0) { // check for negative values or values above 100 +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found invalid demographic scaling score." << std::endl; +#endif + DSfile.close(); DSfile.clear(); + return -17; // need to change code + } + else { + // if the value is ok, + // set the vector value of this cell at this location to the float value read in: + landscape[y][x][DSnb] = DSfloat; // Assignment to specific cell's vector + } + } + } // end x loop + } // end y loop + + // use Rcpp::Rcout to print the landscape at DSnb=0: + // close file connection +#if RS_RCPP + DSfile >> DSfloat; + if (!DSfile.eof()) EOFerrorR(DSlayer); + else { +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "Demographic scaling layer " << DSnb + 1 << " loaded." << endl; +#endif + } +#endif + if (DSfile.is_open()) { DSfile.close(); DSfile.clear(); } + DSnb ++; // increase the reference number and read in next file + }; // end loop over scalinglayers + + // add the cells' vector of DSfloats to the actual landscape using the function addchgDemoScaling + // loop over all cells + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + // extract the vector in landscape at x, y + std::vector localDS = landscape[y][x]; + cells[y][x]->addchgDemoScaling(localDS); // add the vector to the cell + } + } + return 0; // return success code + }; + //--------------------------------------------------------------------------- rasterdata CheckRasterFile(string fname) diff --git a/Landscape.h b/Landscape.h index 179c31e..088546d 100644 --- a/Landscape.h +++ b/Landscape.h @@ -373,7 +373,8 @@ class Landscape{ wifstream&, // cost file stream int, // habnodata int, // pchnodata - int // costnodata + int, // costnodata + vector // vector of demographic scaling layers // TODO: add spatial demography with normal file input ); #else @@ -509,12 +510,14 @@ class Landscape{ // fileNum > 0 for subsequent habitat files under the %cover option string, // habitat file name string, // patch file name - string // cost file name (may be NULL) + string, // cost file name (may be NULL) + vector // demographic scaling layers (may be empty) ); void listPatches(void); int readCosts( string // costs file name ); + int readDemographicScaling(vector ); void resetVisits(void); void outVisits(int,int); // save SMS path visits map to raster text file diff --git a/Model.cpp b/Model.cpp index fb4d67f..5bcbce3 100644 --- a/Model.cpp +++ b/Model.cpp @@ -98,10 +98,6 @@ int RunModel(Landscape* pLandscape, int seqsim) cout << "Running replicate " << rep + 1 << " / " << sim.reps << endl; -#if RS_RCPP && !R_CMD - Rcpp::Rcout << endl << "starting replicate " << rep << endl; -#endif - if (sim.saveVisits && !ppLand.generated) { pLandscape->resetVisits(); } From 8f40ab41c0910ffa333b30e3d21b94856d05871c Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Fri, 12 Sep 2025 08:36:25 +0200 Subject: [PATCH 319/332] BUGFIX in moveStep: number of steps (path->total) was not incremented; --- Individual.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Individual.cpp b/Individual.cpp index 8149b5a..2571572 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -976,6 +976,7 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, } else { // take a step (path->year)++; + (path->total)++; if (pPatch == nullptr || patchNum == 0) { // not in a patch if (path != 0) path->settleStatus = 0; // reset path settlement status (path->out)++; From 4c70c7710e43850283a9a270a53aea8cb79025e4 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Mon, 15 Sep 2025 13:17:34 +0200 Subject: [PATCH 320/332] Unit_test: Changed different initialisation of individuals; pSpecies is also needed --- unit_tests/testPopulation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unit_tests/testPopulation.cpp b/unit_tests/testPopulation.cpp index 3979a30..031e956 100644 --- a/unit_tests/testPopulation.cpp +++ b/unit_tests/testPopulation.cpp @@ -191,7 +191,7 @@ void testPopulation() // Initialise population with Population pop = Population(pSpecies, pPatch, 0, 1); for (int i = 0; i < initialNbInds; i++) { - Individual* pInd = new Individual(pCell, pPatch, 1, 0, 0, 0.5, false, 1); + Individual* pInd = new Individual(pSpecies, pCell, pPatch, 1, 0, 0, 0.5, false, 1); pInd->setUpGenes(pSpecies, 1.0); if (i < initialNbInds * initFreqA) pInd->overrideGenotype(NEUTRAL, genotypeAA); @@ -265,7 +265,7 @@ void testPopulation() // Initialise population with Population pop = Population(pSpecies, pPatch, 0, 1); for (int i = 0; i < initialNbInds; i++) { - Individual* pInd = new Individual(pCell, pPatch, 1, 0, 0, 0.5, false, 1); + Individual* pInd = new Individual(pSpecies, pCell, pPatch, 1, 0, 0, 0.5, false, 1); pInd->setUpGenes(pSpecies, 1.0); if (i < initialNbInds * initFreqA) pInd->overrideGenotype(GENETIC_LOAD1, genotypeAA); From a7cf75ec3d16aa6e7c2b799564f0070dae515ea5 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Mon, 15 Sep 2025 13:53:15 +0200 Subject: [PATCH 321/332] updated Individual() constructor in unit_tests/testIndividual.cpp --- unit_tests/testIndividual.cpp | 64 +++++++++++++++++------------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 5af96c2..1d23228 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -52,7 +52,7 @@ void testTransferKernels() { Patch* init_patch = (Patch*)init_cell->getPatch(); // Create and set up individual - Individual ind1(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + Individual ind1(&sp,init_cell, init_patch, 1, 0, 0, 0.0, false, 0); int isDispersing = ind1.moveKernel(&ls, &sp, false); // After moving, individual should be in the only available cell @@ -64,7 +64,7 @@ void testTransferKernels() { // If no cell within reasonable dispersal reach, individual does not move and dies kern.meanDist1 = 1.0; sp.setSpKernTraits(0, 0, kern, ls_params.resol); - Individual ind2(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual + Individual ind2(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual isDispersing = ind2.moveKernel(&ls, &sp, false); curr_cell = ind2.getCurrCell(); assert(ind2.getStatus() == 6); // RIP in peace @@ -77,12 +77,12 @@ void testTransferKernels() { kern.meanDist2 = 5.0; // easily reaches suitable cell... kern.probKern1 = 1.0; // ... but never used sp.setSpKernTraits(0, 0, kern, ls_params.resol); - Individual ind3(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + Individual ind3(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind3.moveKernel(&ls, &sp, false); assert(ind3.getStatus() == 6); // dead, could not reach destination cell kern.probKern1 = 0.0; // always use second kernel sp.setSpKernTraits(0, 0, kern, ls_params.resol); - Individual ind4(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + Individual ind4(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind4.moveKernel(&ls, &sp, false); assert(ind4.getStatus() == 2); // reset @@ -101,11 +101,11 @@ void testTransferKernels() { kern_m.meanDist1 = 5.0; // male easily reaches suitable cell sp.setSpKernTraits(0, 1, kern_m, ls_params.resol); - Individual ind5(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // female as default + Individual ind5(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // female as default isDispersing = ind5.moveKernel(&ls, &sp, false); assert(ind5.getStatus() == 6); // dead, could not reach destination - Individual ind6(init_cell, init_patch, 1, 0, 0, 1.0, false, 0); // male + Individual ind6(&sp, init_cell, init_patch, 1, 0, 0, 1.0, false, 0); // male assert(ind6.getSex() == 1); isDispersing = ind6.moveKernel(&ls, &sp, false); assert(ind6.getStatus() == 2); @@ -123,11 +123,11 @@ void testTransferKernels() { kern_adult.meanDist1 = 5.0; // adults easily reach suitable cell sp.setSpKernTraits(1, 0, kern_adult, ls_params.resol); - Individual ind7(init_cell, init_patch, 0, 0, 0, 0.0, false, 0); // juvenile + Individual ind7(&sp, init_cell, init_patch, 0, 0, 0, 0.0, false, 0); // juvenile isDispersing = ind7.moveKernel(&ls, &sp, false); assert(ind7.getStatus() == 6); - Individual ind8(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // adult by default + Individual ind8(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // adult by default isDispersing = ind8.moveKernel(&ls, &sp, false); assert(ind8.getStatus() == 2); // reset @@ -159,7 +159,7 @@ void testTransferKernels() { kern.meanDist1 = 10; // overshoots *most* of the time... sp.setSpKernTraits(0, 0, kern, ls_params.resol); - Individual ind9(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual + Individual ind9(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual // Non-absorbing boundaries bool absorbing_boundaries{ false }; @@ -170,7 +170,7 @@ void testTransferKernels() { // Absorbing boundaries absorbing_boundaries = true; - Individual ind10(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual + Individual ind10(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual isDispersing = ind10.moveKernel(&ls, &sp, absorbing_boundaries); curr_cell = ind10.getCurrCell(); assert(ind10.getStatus() == 6); @@ -182,23 +182,23 @@ void testTransferKernels() { sp.setMortParams(mort); trfr.distMort = false; sp.setTrfrRules(trfr); - Individual ind11(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + Individual ind11(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind11.moveKernel(&ls, &sp, false); assert(ind11.getStatus() == 7); // Distance-dependent mortality trfr.distMort = true; sp.setTrfrRules(trfr); mort.mortAlpha = 1000.0; // very steep threshold - mort.mortBeta = 0.5; // very small distance + mort.mortBeta = 0.5; // very small distance sp.setMortParams(mort); kern.meanDist1 = 5; // very likely to go over threshold sp.setSpKernTraits(0, 0, kern, ls_params.resol); - Individual ind12(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + Individual ind12(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind12.moveKernel(&ls, &sp, false); assert(ind12.getStatus() == 7); mort.mortBeta = 30; // very large distance, unlikely to draw sp.setMortParams(mort); - Individual ind13(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + Individual ind13(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind13.moveKernel(&ls, &sp, false); assert(ind13.getStatus() != 7); @@ -271,7 +271,7 @@ void testTransferCRW() { Patch* init_patch = (Patch*)init_cell->getPatch(); // Create and set up individual - Individual ind0(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); + Individual ind0(&sp, init_cell, init_patch, 1, 0, 0, 0.0, true, 2); // Set status assert(ind0.getStatus() == 0); // default status, not emigrating @@ -280,9 +280,9 @@ void testTransferCRW() { assert(ind0.getCurrCell() == init_cell); // not emigrating so didn't move // Per-step mortality - m.stepMort = 1.0; // should die + m.stepMort = 1.0; // should die sp.setSpMovtTraits(m); - Individual ind1(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + Individual ind1(&sp, init_cell, init_patch, 0, 0, 0, 0.0, true, 2); // force set path bc for some reason path gets deallocated upon exiting constructor?? ind1.setStatus(1); isDispersing = ind1.moveStep(&ls, &sp, hab_index, false); @@ -335,7 +335,7 @@ void testTransferCRW() { steps.maxStepsYr = 2; steps.maxSteps = 3; sp.setSteps(0, 0, steps); - Individual ind2(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); + Individual ind2(&sp, init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); ind2.setStatus(1); // dispersing // First step - still in unsuitable cell so still dispersing isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); @@ -354,7 +354,7 @@ void testTransferCRW() { // Step length too long m.stepLength = ls_params.dimX * SQRT2 * 1.5; // overshoots sp.setSpMovtTraits(m); - Individual ind3(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + Individual ind3(&sp, init_cell, init_patch, 0, 0, 0, 0.0, true, 2); ind3.setStatus(1); // dispersing steps.minSteps = 1; steps.maxStepsYr = 1; @@ -367,7 +367,7 @@ void testTransferCRW() { // Adequate step length m.stepLength = (ls_params.dimX - 1) * SQRT2; sp.setSpMovtTraits(m); - Individual ind4(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); + Individual ind4(&sp, init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); ind4.setStatus(1); // dispersing // Initial angle still random but should eventually reach the suitable cell isDispersing = ind4.moveStep(&ls, &sp, hab_index, false); @@ -375,7 +375,7 @@ void testTransferCRW() { assert(ind4.getCurrCell() == final_cell); // If boundaries are absorbing however, most likely to die - Individual ind5(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); + Individual ind5(&sp, init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); ind5.setStatus(1); // dispersing bool absorbing_boundaries = true; isDispersing = ind5.moveStep(&ls, &sp, hab_index, absorbing_boundaries); @@ -405,7 +405,7 @@ void testTransferCRW() { sp.setSpMovtTraits(m); steps.maxStepsYr = steps.maxSteps = ls_params.dimX; sp.setSteps(0, 0, steps); - Individual ind6(cell_vec[0], natalPatch, 0, 0, 0, 0.0, true, 2); + Individual ind6(&sp, cell_vec[0], natalPatch, 0, 0, 0, 0.0, true, 2); const float diag_angle = PI / 4.0; // 45 degrees ind6.setInitAngle(diag_angle); // Individual moves only along diagonal cells @@ -514,7 +514,7 @@ void testGenetics() { for (int i = 0; i < genomeSz; i++) { valMotherAllele = dispTrChild.getAlleleValueAtLocus(0, i); assert(valMotherAllele == (i <= site ? valAlleleA : valAlleleB)); - // don't check other chromosome, empty bc we did not resolve father inheritance + // don't check other chromosome, empty bc we did not resolve father inheritance } } } @@ -577,7 +577,7 @@ void testGenetics() { // Most likely (~96%) to sample a mutation > 1 const float gammaMutShapeParam = 5.0; const float gammaMutScaleParam = 1.0; - // Normal centered on 0 : ~50% of sampling negative dominance coefficient + // Normal centered on 0 : ~50% of sampling negative dominance coefficient const float dominanceMeanParam = 0.0; const float dominanceSdParam = 1.0; @@ -687,7 +687,7 @@ void testIndividual() { // We simulate 100 inheritance + recombination processes and expect that: // 1. freq(A,B have same alleles) >> freq(A,C have same alleles) // 2. 0.65 > freq(C,D have same alleles) > 0.35 despite being adjacent because of chrom. break - // (both freq. have p < 0.001 from a binomial with p 0.5 and 100 trials) + // (both freq. have p < 0.001 from a binomial with p 0.5 and 100 trials) { Patch* pPatch = new Patch(0, 0); Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); @@ -711,7 +711,7 @@ void testIndividual() { const bool isDiploid{ true }; SpeciesTrait* spTr = createTestEmigSpTrait(genePositions, isDiploid); pSpecies->addTrait(TraitType::E_D0, *spTr); - + Individual indMother = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); Individual indFather = Individual(pCell, pPatch, 0, 0, 0, 1.0, false, 0); indMother.setUpGenes(pSpecies, 1.0); @@ -760,7 +760,7 @@ void testIndividual() { set{}, "none", set{}, 0 // no output so no sampling ); emigRules emig; - emig.indVar = true; + emig.indVar = true; emig.sexDep = true; emig.densDep = false; pSpecies->setEmigRules(emig); @@ -826,7 +826,7 @@ void testIndividual() { indMale.setUpGenes(pSpecies, 1.0); indFemale.triggerMutations(pSpecies); indMale.triggerMutations(pSpecies); - + // Male should use male trait, still 1 // Female should use female trait, has mutated emigTraits femaleEmig = indFemale.getIndEmigTraits(); @@ -854,7 +854,7 @@ void testIndividual() { set{}, "none", set{}, 0 // no output so no sampling ); emigRules emig; - emig.indVar = false; + emig.indVar = false; emig.stgDep = false; emig.sexDep = false; emig.densDep = false; pSpecies->setEmigRules(emig); @@ -893,7 +893,7 @@ void testIndividual() { assert(ind.getStatus() == 0); pop.emigration(100.0); - // Individual is using the species-wide emigration prob, + // Individual is using the species-wide emigration prob, // so should be selected to emigrate (status 1) assert(ind.getStatus() == 1); @@ -1228,7 +1228,7 @@ void testIndividual() { ind.overrideGenotype(CRW_STEPCORRELATION, crwCorrGenoType); ind.triggerMutations(pSpecies); // no mutations, but trigger expression - + crwData trfrTr = *(static_cast(ind.getTrfrData())); assert(trfrTr.stepLength >= 0.0); assert(trfrTr.rho <= 1.0); @@ -1352,7 +1352,7 @@ void testIndividual() { assert(trfrTr.alphaDB > 0.0); } } - + } #endif //NDEBUG From fc73cc5f19d63e2e5f5e0932fa3b5ce16e7a918d Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 17 Sep 2025 18:57:01 +0100 Subject: [PATCH 322/332] fix argument errors in unit tests --- Individual.cpp | 41 ------------ unit_tests/testIndividual.cpp | 109 ++++++++++++++++++++------------ unit_tests/testNeutralStats.cpp | 44 ++++++------- unit_tests/testPopulation.cpp | 20 +++--- 4 files changed, 100 insertions(+), 114 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 93f03a4..c59d583 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1672,47 +1672,6 @@ double cauchy(double location, double scale) { //--------------------------------------------------------------------------- #ifndef NDEBUG -void testIndividual() { - - Species* pSpecies = new Species(); - - Patch* pPatch = new Patch(0, 0); - int cell_x = 2; - int cell_y = 5; - int cell_hab = 2; - Cell* pCell = new Cell(cell_x, cell_y, pPatch, cell_hab); - - // Create an individual - short stg = 0; - short age = 0; - short repInt = 0; - float probmale = 0; - bool uses_movt_process = true; - short moveType = 1; - Individual ind(pSpecies, pCell, pPatch, stg, age, repInt, probmale, uses_movt_process, moveType); - - // An individual can move to a neighbouring cell - //ind.moveto(); - - // Gets its sex drawn from pmale - - // Can age or develop - // Reproduces - // depending on whether it is sexual or not - // depending on the stage - // depending on the trait inheritance - - - // Disperses - // Emigrates - // Transfers - // Settles - - // Survives - - // Develops - -} Cell* Individual::getCurrCell() const { return pCurrCell; } diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index aa95d30..f86bc19 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -52,7 +52,7 @@ void testTransferKernels() { Patch* init_patch = (Patch*)init_cell->getPatch(); // Create and set up individual - Individual ind1(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + Individual ind1(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); int isDispersing = ind1.moveKernel(&ls, &sp, false); // After moving, individual should be in the only available cell @@ -64,7 +64,7 @@ void testTransferKernels() { // If no cell within reasonable dispersal reach, individual does not move and dies kern.meanDist1 = 1.0; sp.setSpKernTraits(0, 0, kern, ls_params.resol); - Individual ind2(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual + Individual ind2(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual isDispersing = ind2.moveKernel(&ls, &sp, false); curr_cell = ind2.getCurrCell(); assert(ind2.getStatus() == 6); // RIP in peace @@ -77,12 +77,12 @@ void testTransferKernels() { kern.meanDist2 = 5.0; // easily reaches suitable cell... kern.probKern1 = 1.0; // ... but never used sp.setSpKernTraits(0, 0, kern, ls_params.resol); - Individual ind3(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + Individual ind3(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind3.moveKernel(&ls, &sp, false); assert(ind3.getStatus() == 6); // dead, could not reach destination cell kern.probKern1 = 0.0; // always use second kernel sp.setSpKernTraits(0, 0, kern, ls_params.resol); - Individual ind4(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + Individual ind4(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind4.moveKernel(&ls, &sp, false); assert(ind4.getStatus() == 2); // reset @@ -101,11 +101,11 @@ void testTransferKernels() { kern_m.meanDist1 = 5.0; // male easily reaches suitable cell sp.setSpKernTraits(0, 1, kern_m, ls_params.resol); - Individual ind5(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // female as default + Individual ind5(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // female as default isDispersing = ind5.moveKernel(&ls, &sp, false); assert(ind5.getStatus() == 6); // dead, could not reach destination - Individual ind6(init_cell, init_patch, 1, 0, 0, 1.0, false, 0); // male + Individual ind6(&sp, init_cell, init_patch, 1, 0, 0, 1.0, false, 0); // male assert(ind6.getSex() == 1); isDispersing = ind6.moveKernel(&ls, &sp, false); assert(ind6.getStatus() == 2); @@ -123,11 +123,11 @@ void testTransferKernels() { kern_adult.meanDist1 = 5.0; // adults easily reach suitable cell sp.setSpKernTraits(1, 0, kern_adult, ls_params.resol); - Individual ind7(init_cell, init_patch, 0, 0, 0, 0.0, false, 0); // juvenile + Individual ind7(&sp, init_cell, init_patch, 0, 0, 0, 0.0, false, 0); // juvenile isDispersing = ind7.moveKernel(&ls, &sp, false); assert(ind7.getStatus() == 6); - Individual ind8(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // adult by default + Individual ind8(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // adult by default isDispersing = ind8.moveKernel(&ls, &sp, false); assert(ind8.getStatus() == 2); // reset @@ -159,7 +159,7 @@ void testTransferKernels() { kern.meanDist1 = 10; // overshoots *most* of the time... sp.setSpKernTraits(0, 0, kern, ls_params.resol); - Individual ind9(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual + Individual ind9(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual // Non-absorbing boundaries bool absorbing_boundaries{ false }; @@ -170,7 +170,7 @@ void testTransferKernels() { // Absorbing boundaries absorbing_boundaries = true; - Individual ind10(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual + Individual ind10(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual isDispersing = ind10.moveKernel(&ls, &sp, absorbing_boundaries); curr_cell = ind10.getCurrCell(); assert(ind10.getStatus() == 6); @@ -182,7 +182,7 @@ void testTransferKernels() { sp.setMortParams(mort); trfr.distMort = false; sp.setTrfrRules(trfr); - Individual ind11(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + Individual ind11(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind11.moveKernel(&ls, &sp, false); assert(ind11.getStatus() == 7); // Distance-dependent mortality @@ -193,12 +193,12 @@ void testTransferKernels() { sp.setMortParams(mort); kern.meanDist1 = 5; // very likely to go over threshold sp.setSpKernTraits(0, 0, kern, ls_params.resol); - Individual ind12(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + Individual ind12(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind12.moveKernel(&ls, &sp, false); assert(ind12.getStatus() == 7); mort.mortBeta = 30; // very large distance, unlikely to draw sp.setMortParams(mort); - Individual ind13(init_cell, init_patch, 1, 0, 0, 0.0, false, 0); + Individual ind13(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind13.moveKernel(&ls, &sp, false); assert(ind13.getStatus() != 7); @@ -271,7 +271,7 @@ void testTransferCRW() { Patch* init_patch = (Patch*)init_cell->getPatch(); // Create and set up individual - Individual ind0(init_cell, init_patch, 1, 0, 0, 0.0, true, 2); + Individual ind0(&sp, init_cell, init_patch, 1, 0, 0, 0.0, true, 2); // Set status assert(ind0.getStatus() == 0); // default status, not emigrating @@ -282,7 +282,7 @@ void testTransferCRW() { // Per-step mortality m.stepMort = 1.0; // should die sp.setSpMovtTraits(m); - Individual ind1(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + Individual ind1(&sp, init_cell, init_patch, 0, 0, 0, 0.0, true, 2); // force set path bc for some reason path gets deallocated upon exiting constructor?? ind1.setStatus(1); isDispersing = ind1.moveStep(&ls, &sp, hab_index, false); @@ -335,7 +335,7 @@ void testTransferCRW() { steps.maxStepsYr = 2; steps.maxSteps = 3; sp.setSteps(0, 0, steps); - Individual ind2(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); + Individual ind2(&sp, init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); ind2.setStatus(1); // dispersing // First step - still in unsuitable cell so still dispersing isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); @@ -354,7 +354,7 @@ void testTransferCRW() { // Step length too long m.stepLength = ls_params.dimX * SQRT2 * 1.5; // overshoots sp.setSpMovtTraits(m); - Individual ind3(init_cell, init_patch, 0, 0, 0, 0.0, true, 2); + Individual ind3(&sp, init_cell, init_patch, 0, 0, 0, 0.0, true, 2); ind3.setStatus(1); // dispersing steps.minSteps = 1; steps.maxStepsYr = 1; @@ -367,7 +367,7 @@ void testTransferCRW() { // Adequate step length m.stepLength = (ls_params.dimX - 1) * SQRT2; sp.setSpMovtTraits(m); - Individual ind4(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); + Individual ind4(&sp, init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); ind4.setStatus(1); // dispersing // Initial angle still random but should eventually reach the suitable cell isDispersing = ind4.moveStep(&ls, &sp, hab_index, false); @@ -375,7 +375,7 @@ void testTransferCRW() { assert(ind4.getCurrCell() == final_cell); // If boundaries are absorbing however, most likely to die - Individual ind5(init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); + Individual ind5(&sp, init_cell, natalPatch, 0, 0, 0, 0.0, true, 2); ind5.setStatus(1); // dispersing bool absorbing_boundaries = true; isDispersing = ind5.moveStep(&ls, &sp, hab_index, absorbing_boundaries); @@ -405,7 +405,7 @@ void testTransferCRW() { sp.setSpMovtTraits(m); steps.maxStepsYr = steps.maxSteps = ls_params.dimX; sp.setSteps(0, 0, steps); - Individual ind6(cell_vec[0], natalPatch, 0, 0, 0, 0.0, true, 2); + Individual ind6(&sp, cell_vec[0], natalPatch, 0, 0, 0, 0.0, true, 2); const float diag_angle = PI / 4.0; // 45 degrees ind6.setInitAngle(diag_angle); // Individual moves only along diagonal cells @@ -534,11 +534,15 @@ void testGenetics() { pair{GenParamType::MIN, initialAlleleVal}, pair{GenParamType::MAX, initialAlleleVal} }; + + const set genePositions = createTestGenePositions(genomeSz); + SpeciesTrait* spTr = new SpeciesTrait( TraitType::E_D0, sex_t::NA, - createTestGenePositions(genomeSz), + genePositions, ExpressionType::ADDITIVE, + genePositions, // initial positions (all) DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, not used isInherited, @@ -595,11 +599,14 @@ void testGenetics() { }; const map placeholderParams = mutationParams; + const set genePositions = createTestGenePositions(genomeSz); + SpeciesTrait* spTr = new SpeciesTrait( TraitType::GENETIC_LOAD1, sex_t::NA, - createTestGenePositions(genomeSz), + genePositions, ExpressionType::MULTIPLICATIVE, + genePositions, DistributionType::NONE, placeholderParams, // not used for genetic load DistributionType::NONE, dominanceParams, true, @@ -637,11 +644,14 @@ void testGenetics() { }; const map placeholderParams = mutationParams; + const set genePositions = createTestGenePositions(genomeSz); + SpeciesTrait* spTr = new SpeciesTrait( TraitType::GENETIC_LOAD1, sex_t::NA, - createTestGenePositions(genomeSz), + genePositions, ExpressionType::MULTIPLICATIVE, + genePositions, DistributionType::NONE, placeholderParams, // not used for genetic load DistributionType::NONE, placeholderParams, // doesn't matter for this test true, @@ -690,7 +700,7 @@ void testIndividual() { // (both freq. have p < 0.001 from a binomial with p 0.5 and 100 trials) { Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); const float recombinationRate = 0.01; const int genomeSz = 10; @@ -712,8 +722,8 @@ void testIndividual() { SpeciesTrait* spTr = createTestEmigSpTrait(genePositions, isDiploid); pSpecies->addTrait(TraitType::E_D0, *spTr); - Individual indMother = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); - Individual indFather = Individual(pCell, pPatch, 0, 0, 0, 1.0, false, 0); + Individual indMother = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, false, 0); + Individual indFather = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 1.0, false, 0); indMother.setUpGenes(pSpecies, 1.0); indFather.setUpGenes(pSpecies, 1.0); @@ -724,7 +734,7 @@ void testIndividual() { const int nbTrials = 100; for (int i = 0; i < nbTrials; ++i) { - Individual indChild = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + Individual indChild = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, false, 0); indChild.inheritTraits(pSpecies, &indMother, &indFather, 1.0); bool hasInheritedA0 = haveSameEmigD0Allele(indChild, indMother, posA); @@ -748,7 +758,7 @@ void testIndividual() { /// Emigration probability is 1 initially, but female trait mutates. { Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); // Species-level paramters const int genomeSz = 6; @@ -790,6 +800,7 @@ void testIndividual() { sex_t::MAL, maleGenePositions, ExpressionType::AVERAGE, + maleGenePositions, // Set all initial alleles values to 1 DistributionType::UNIFORM, initParams, DistributionType::NONE, initParams, // no dominance, params are ignored @@ -807,6 +818,7 @@ void testIndividual() { sex_t::FEM, femaleGenePositions, ExpressionType::AVERAGE, + femaleGenePositions, // Set all initial alleles values to 1 DistributionType::UNIFORM, initParams, DistributionType::NONE, initParams, // no dominance, params are ignored @@ -820,8 +832,8 @@ void testIndividual() { pSpecies->addTrait(TraitType::E_D0_F, *spTrF); // Set up male and female individuals, trigger mutations - Individual indFemale = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); - Individual indMale = Individual(pCell, pPatch, 0, 0, 0, 1.0, false, 0); + Individual indFemale = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, false, 0); + Individual indMale = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 1.0, false, 0); indFemale.setUpGenes(pSpecies, 1.0); indMale.setUpGenes(pSpecies, 1.0); indFemale.triggerMutations(pSpecies); @@ -842,7 +854,7 @@ void testIndividual() { float indEmigProb = 0.0; Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); // Species-level paramters const int genomeSz = 1; @@ -873,6 +885,7 @@ void testIndividual() { sex_t::NA, set{ 0 }, // only one locus ExpressionType::AVERAGE, + set{ 0 }, // initial positions DistributionType::UNIFORM, initParams, DistributionType::NONE, initParams, // no dominance, params are ignored true, // isInherited @@ -884,7 +897,7 @@ void testIndividual() { ); pSpecies->addTrait(TraitType::E_D0, *spTr); - Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + Individual ind = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, false, 0); ind.setUpGenes(pSpecies, 1.0); // Create population to trigger emigration selection @@ -913,7 +926,7 @@ void testIndividual() { // Individuals with genetic fitness = 0 are never viable { Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); // Species-level paramters const int genomeSz = 1; @@ -939,6 +952,7 @@ void testIndividual() { sex_t::NA, set{ 0 }, // only one locus ExpressionType::MULTIPLICATIVE, + set{ 0 }, DistributionType::NONE, initParams, DistributionType::UNIFORM, domParams, true, // isInherited @@ -951,7 +965,7 @@ void testIndividual() { pSpecies->addTrait(TraitType::GENETIC_LOAD1, *spTr); - Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + Individual ind = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, false, 0); ind.setUpGenes(pSpecies, 1.0); // By default, all loci are initialised at 0 so individual is viable @@ -968,7 +982,7 @@ void testIndividual() { // A largely dominant allele overrides the expression of its homologue { Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); // Species-level paramters const int genomeSz = 1; @@ -991,6 +1005,7 @@ void testIndividual() { sex_t::NA, set{ 0 }, // only one locus ExpressionType::MULTIPLICATIVE, + set{ 0 }, DistributionType::NONE, distParams, DistributionType::UNIFORM, distParams, true, // isInherited @@ -1002,7 +1017,7 @@ void testIndividual() { ); pSpecies->addTrait(TraitType::GENETIC_LOAD1, *spTr); - Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + Individual ind = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, false, 0); ind.setUpGenes(pSpecies, 1.0); const float valAlleleA = 1.0; // lethal @@ -1032,7 +1047,7 @@ void testIndividual() { const float mutationRate = 0.0; // no mutations Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); // Genome-level settings Species* pSpecies = createDefaultSpecies(); @@ -1072,6 +1087,7 @@ void testIndividual() { sex_t::NA, set{ 0 }, ExpressionType::AVERAGE, + set{ 0 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1086,6 +1102,7 @@ void testIndividual() { sex_t::NA, set{ 1 }, ExpressionType::AVERAGE, + set{ 1 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1100,6 +1117,7 @@ void testIndividual() { sex_t::NA, set{ 2 }, ExpressionType::AVERAGE, + set{ 2 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1114,6 +1132,7 @@ void testIndividual() { sex_t::NA, set{ 3 }, ExpressionType::ADDITIVE, + set{ 3 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1129,7 +1148,7 @@ void testIndividual() { pSpecies->addTrait(TraitType::S_BETA, *trSettBeta); pSpecies->addTrait(TraitType::KERNEL_MEANDIST_1, *trMeanKern); - Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + Individual ind = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, false, 0); ind.setUpGenes(pSpecies, 1.0); // Overwrite genotypes with alleles resulting in invalid phenotypes @@ -1158,7 +1177,7 @@ void testIndividual() { const float mutationRate = 0.0; // no mutations Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); // Genome-level settings Species* pSpecies = createDefaultSpecies(); @@ -1190,6 +1209,7 @@ void testIndividual() { sex_t::NA, set{ 0 }, ExpressionType::ADDITIVE, + set{ 0 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1204,6 +1224,7 @@ void testIndividual() { sex_t::NA, set{ 1 }, ExpressionType::AVERAGE, + set{ 1 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1219,7 +1240,7 @@ void testIndividual() { bool usesMovtProcess = true; short whichMovtProcess = 2; // CRW - Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, usesMovtProcess, whichMovtProcess); + Individual ind = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, usesMovtProcess, whichMovtProcess); ind.setUpGenes(pSpecies, 1.0); // Overwrite genotypes with alleles resulting in invalid phenotypes @@ -1242,7 +1263,7 @@ void testIndividual() { const float mutationRate = 0.0; // no mutations Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); // Genome-level settings Species* pSpecies = createDefaultSpecies(); @@ -1274,6 +1295,7 @@ void testIndividual() { sex_t::NA, set{ 0 }, ExpressionType::ADDITIVE, + set{ 0 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1288,6 +1310,7 @@ void testIndividual() { sex_t::NA, set{ 1 }, ExpressionType::AVERAGE, + set{ 1 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1302,6 +1325,7 @@ void testIndividual() { sex_t::NA, set{ 0 }, ExpressionType::ADDITIVE, + set{ 0 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1316,6 +1340,7 @@ void testIndividual() { sex_t::NA, set{ 1 }, ExpressionType::AVERAGE, + set{ 1 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1333,7 +1358,7 @@ void testIndividual() { bool usesMovtProcess = true; short whichMovtProcess = 1; // SMS - Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, usesMovtProcess, whichMovtProcess); + Individual ind = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, usesMovtProcess, whichMovtProcess); ind.setUpGenes(pSpecies, 1.0); // Overwrite genotypes with alleles resulting in invalid phenotypes diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index b8a63ed..344a20c 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -12,7 +12,7 @@ void testNeutralStats() { const set patchList{ pPatch->getPatchNum() }; const string indSampling = "all"; const set stgToSample = { 1 }; - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); pPatch->addCell(pCell, 0, 0); // Create genetic structure @@ -59,7 +59,7 @@ void testNeutralStats() { const set patchList{ pPatch->getPatchNum() }; const string indSampling = "all"; const set stgToSample = { 1 }; - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); pPatch->addCell(pCell, 0, 0); // Create genetic structure @@ -106,7 +106,7 @@ void testNeutralStats() { const set patchList{ pPatch->getPatchNum() }; const string indSampling = "all"; const set stgToSample = { 1 }; - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); pPatch->addCell(pCell, 0, 0); // Create genetic structure @@ -167,7 +167,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -214,7 +214,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -267,7 +267,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -296,7 +296,7 @@ void testNeutralStats() { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + Individual* pInd = new Individual(pSpecies, cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); pInd->setUpGenes(pSpecies, 1.0); pPop->recruit(pInd); } @@ -341,7 +341,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -415,7 +415,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -445,7 +445,7 @@ void testNeutralStats() { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + Individual* pInd = new Individual(pSpecies, cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); pInd->setUpGenes(pSpecies, 1.0); pInd->overrideGenotype(NEUTRAL, genotypes[p]); pPop->recruit(pInd); @@ -517,7 +517,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -546,7 +546,7 @@ void testNeutralStats() { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + Individual* pInd = new Individual(pSpecies, cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); pInd->setUpGenes(pSpecies, 1.0); pInd->overrideGenotype(NEUTRAL, genotypes[i]); pPop->recruit(pInd); @@ -620,7 +620,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -649,7 +649,7 @@ void testNeutralStats() { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + Individual* pInd = new Individual(pSpecies, cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); pInd->setUpGenes(pSpecies, 1.0); pInd->overrideGenotype(NEUTRAL, genotypeList[p][i]); pPop->recruit(pInd); @@ -716,7 +716,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -745,7 +745,7 @@ void testNeutralStats() { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + Individual* pInd = new Individual(pSpecies, cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); pInd->setUpGenes(pSpecies, 1.0); pInd->overrideGenotype(NEUTRAL, genotypeAB); pPop->recruit(pInd); @@ -827,7 +827,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -856,7 +856,7 @@ void testNeutralStats() { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + Individual* pInd = new Individual(pSpecies, cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); pInd->setUpGenes(pSpecies, 1.0); pInd->overrideGenotype(NEUTRAL, genotypeList[p][i]); pPop->recruit(pInd); @@ -915,7 +915,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -944,7 +944,7 @@ void testNeutralStats() { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + Individual* pInd = new Individual(pSpecies, cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); pInd->setUpGenes(pSpecies, 1.0); pInd->overrideGenotype(NEUTRAL, genotypes[i]); pPop->recruit(pInd); @@ -1001,7 +1001,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -1030,7 +1030,7 @@ void testNeutralStats() { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + Individual* pInd = new Individual(pSpecies, cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); pInd->setUpGenes(pSpecies, 1.0); pInd->overrideGenotype(NEUTRAL, p == 0 ? genotypePop1 : genotypePop2); pPop->recruit(pInd); diff --git a/unit_tests/testPopulation.cpp b/unit_tests/testPopulation.cpp index 3979a30..162ca65 100644 --- a/unit_tests/testPopulation.cpp +++ b/unit_tests/testPopulation.cpp @@ -31,7 +31,7 @@ void testPopulation() for (float mutationRate : mutationRates) { Landscape* pLandscape = new Landscape; Patch* pPatch = pLandscape->newPatch(1); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); pPatch->addCell(pCell, 0, 0); Species* pSpecies = createDefaultSpecies(); @@ -47,6 +47,7 @@ void testPopulation() sex_t::NA, genePositions, ExpressionType::MULTIPLICATIVE, + genePositions, // initial positions (all) DistributionType::NONE, map{}, DistributionType::UNIFORM, domParams, true, // isInherited @@ -92,7 +93,7 @@ void testPopulation() for (float mutationRate : mutationRates) { Landscape* pLandscape = new Landscape; Patch* pPatch = pLandscape->newPatch(1); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); pPatch->addCell(pCell, 0, 0); Species* pSpecies = createDefaultSpecies(); @@ -117,11 +118,12 @@ void testPopulation() sex_t::NA, genePositions, ExpressionType::ADDITIVE, - DistributionType::UNIFORM, initParams, - DistributionType::NONE, map{}, // no dominance + genePositions, // initial positions (all) + DistributionType::UNIFORM, initParams, // initial distribution and params + DistributionType::NONE, map{}, // initial dominance (none) true, // isInherited mutationRate, // mutation rate - DistributionType::UNIFORM, mutParams, + DistributionType::UNIFORM, mutParams, // mutation dist and params DistributionType::NONE, map{}, // no dominance isDiploid ? 2 : 1, false @@ -174,7 +176,7 @@ void testPopulation() Landscape* pLandscape = new Landscape; Patch* pPatch = pLandscape->newPatch(1); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); pPatch->addCell(pCell, 0, 0); Species* pSpecies = new Species(); @@ -191,7 +193,7 @@ void testPopulation() // Initialise population with Population pop = Population(pSpecies, pPatch, 0, 1); for (int i = 0; i < initialNbInds; i++) { - Individual* pInd = new Individual(pCell, pPatch, 1, 0, 0, 0.5, false, 1); + Individual* pInd = new Individual(pSpecies, pCell, pPatch, 1, 0, 0, 0.5, false, 1); pInd->setUpGenes(pSpecies, 1.0); if (i < initialNbInds * initFreqA) pInd->overrideGenotype(NEUTRAL, genotypeAA); @@ -248,7 +250,7 @@ void testPopulation() Landscape* pLandscape = new Landscape; Patch* pPatch = pLandscape->newPatch(1); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); pPatch->addCell(pCell, 0, 0); Species* pSpecies = new Species(); @@ -265,7 +267,7 @@ void testPopulation() // Initialise population with Population pop = Population(pSpecies, pPatch, 0, 1); for (int i = 0; i < initialNbInds; i++) { - Individual* pInd = new Individual(pCell, pPatch, 1, 0, 0, 0.5, false, 1); + Individual* pInd = new Individual(pSpecies, pCell, pPatch, 1, 0, 0, 0.5, false, 1); pInd->setUpGenes(pSpecies, 1.0); if (i < initialNbInds * initFreqA) pInd->overrideGenotype(GENETIC_LOAD1, genotypeAA); From 0b9b20e2310d17839622a99d6cd117d5850f6656 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 18 Sep 2025 11:11:30 +0100 Subject: [PATCH 323/332] bugfix missing increment of total steps --- Individual.cpp | 1 + unit_tests/testIndividual.cpp | 26 ++++++++++++++++---------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index c59d583..5de0c08 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -973,6 +973,7 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, } else { // take a step (path->year)++; + (path->total)++; if (pPatch == nullptr || patchNum == 0) { // not in a patch if (path != 0) path->settleStatus = 0; // reset path settlement status (path->out)++; diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index f86bc19..d1751a7 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -210,6 +210,7 @@ void testTransferKernels() { } void testTransferCRW() { + // Simple 5*5 cell-based landscape layout int lsDim = 5; landParams ls_params = createDefaultLandParams(lsDim); @@ -279,11 +280,14 @@ void testTransferCRW() { assert(ind0.getStatus() == 0); // status didn't change assert(ind0.getCurrCell() == init_cell); // not emigrating so didn't move - // Per-step mortality + //---------------------// + // Test per-step mortality + //---------------------// + m.stepMort = 1.0; // should die sp.setSpMovtTraits(m); Individual ind1(&sp, init_cell, init_patch, 0, 0, 0, 0.0, true, 2); - // force set path bc for some reason path gets deallocated upon exiting constructor?? + // force-set path bc for some reason path gets deallocated upon exiting constructor?? ind1.setStatus(1); isDispersing = ind1.moveStep(&ls, &sp, hab_index, false); // Individual begins in natal patch so mortality is disabled @@ -291,8 +295,8 @@ void testTransferCRW() { // Individual should be in a different patch Cell* first_step_cell = ind1.getCurrCell(); assert(first_step_cell != init_cell); + assert(first_step_cell->getPatch() != init_patch); - assert((Patch*)first_step_cell->getPatch() != init_patch); ind1.setStatus(1); // emigrating again // Individual should die on second step @@ -302,10 +306,12 @@ void testTransferCRW() { m.stepMort = 0.0; // not dying sp.setSpMovtTraits(m); - // Habitat-dep mortality + // Test habitat-depdt mortality // ... - // Step size + //----------------// + // Test step size + //----------------// ls = Landscape(); ls.setLandParams(ls_params, true); @@ -325,9 +331,9 @@ void testTransferCRW() { ls.updateCarryingCapacity(&sp, 0, 0); // Init cell is NOT in natal patch Patch* natalPatch = new Patch(0, 0); - init_patch = (Patch*)init_cell->getPatch(); + init_patch = init_cell->getPatch(); - // Step length too short + // Step length is too short m.stepLength = 0.1; // will not reach final cell m.rho = 0.0; // random angle sp.setSpMovtTraits(m); @@ -340,16 +346,16 @@ void testTransferCRW() { // First step - still in unsuitable cell so still dispersing isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); assert(ind2.getCurrCell() == init_cell); - assert(ind2.getStatus() == 1); + assert(ind2.getStatus() == 1); // still dispersing // Second step - reaching max steps this year, wait next year isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); assert(ind2.getCurrCell() == init_cell); - assert(ind2.getStatus() == 3); + assert(ind2.getStatus() == 3); // waiting for next year ind2.setStatus(1); // dispersing again // Third step - reaching max steps, dies in unsuitable cell isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); assert(ind2.getCurrCell() == init_cell); - assert(ind2.getStatus() == 6); + assert(ind2.getStatus() == 6); // died while dispersing // Step length too long m.stepLength = ls_params.dimX * SQRT2 * 1.5; // overshoots From f01ac875725c947a608118271ddbaca4449fe052 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Tue, 23 Sep 2025 09:20:27 +0200 Subject: [PATCH 324/332] updated unit tests according to RScore/new_genetics --- .gitignore | 1 + unit_tests/testIndividual.cpp | 112 ++++++++++++++++++++------------ unit_tests/testNeutralStats.cpp | 46 ++++++------- unit_tests/testPopulation.cpp | 18 ++--- 4 files changed, 106 insertions(+), 71 deletions(-) diff --git a/.gitignore b/.gitignore index 9bd72d2..c4a4ac5 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ build-Release/ *.workspace *.mk *.tags +/build/ # Hidden source /RangeShiftR/src/.* diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 1d23228..3a50c3d 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -210,6 +210,7 @@ void testTransferKernels() { } void testTransferCRW() { + // Simple 5*5 cell-based landscape layout int lsDim = 5; landParams ls_params = createDefaultLandParams(lsDim); @@ -279,11 +280,14 @@ void testTransferCRW() { assert(ind0.getStatus() == 0); // status didn't change assert(ind0.getCurrCell() == init_cell); // not emigrating so didn't move - // Per-step mortality + //---------------------// + // Test per-step mortality + //---------------------// + m.stepMort = 1.0; // should die sp.setSpMovtTraits(m); Individual ind1(&sp, init_cell, init_patch, 0, 0, 0, 0.0, true, 2); - // force set path bc for some reason path gets deallocated upon exiting constructor?? + // force-set path bc for some reason path gets deallocated upon exiting constructor?? ind1.setStatus(1); isDispersing = ind1.moveStep(&ls, &sp, hab_index, false); // Individual begins in natal patch so mortality is disabled @@ -291,8 +295,8 @@ void testTransferCRW() { // Individual should be in a different patch Cell* first_step_cell = ind1.getCurrCell(); assert(first_step_cell != init_cell); + assert(first_step_cell->getPatch() != init_patch); - assert((Patch*)first_step_cell->getPatch() != init_patch); ind1.setStatus(1); // emigrating again // Individual should die on second step @@ -302,10 +306,12 @@ void testTransferCRW() { m.stepMort = 0.0; // not dying sp.setSpMovtTraits(m); - // Habitat-dep mortality + // Test habitat-depdt mortality // ... - // Step size + //----------------// + // Test step size + //----------------// ls = Landscape(); ls.setLandParams(ls_params, true); @@ -325,9 +331,9 @@ void testTransferCRW() { ls.updateCarryingCapacity(&sp, 0, 0); // Init cell is NOT in natal patch Patch* natalPatch = new Patch(0, 0); - init_patch = (Patch*)init_cell->getPatch(); + init_patch = init_cell->getPatch(); - // Step length too short + // Step length is too short m.stepLength = 0.1; // will not reach final cell m.rho = 0.0; // random angle sp.setSpMovtTraits(m); @@ -340,16 +346,16 @@ void testTransferCRW() { // First step - still in unsuitable cell so still dispersing isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); assert(ind2.getCurrCell() == init_cell); - assert(ind2.getStatus() == 1); + assert(ind2.getStatus() == 1); // still dispersing // Second step - reaching max steps this year, wait next year isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); assert(ind2.getCurrCell() == init_cell); - assert(ind2.getStatus() == 3); + assert(ind2.getStatus() == 3); // waiting for next year ind2.setStatus(1); // dispersing again // Third step - reaching max steps, dies in unsuitable cell isDispersing = ind2.moveStep(&ls, &sp, hab_index, false); assert(ind2.getCurrCell() == init_cell); - assert(ind2.getStatus() == 6); + assert(ind2.getStatus() == 6); // died while dispersing // Step length too long m.stepLength = ls_params.dimX * SQRT2 * 1.5; // overshoots @@ -534,11 +540,15 @@ void testGenetics() { pair{GenParamType::MIN, initialAlleleVal}, pair{GenParamType::MAX, initialAlleleVal} }; + + const set genePositions = createTestGenePositions(genomeSz); + SpeciesTrait* spTr = new SpeciesTrait( TraitType::E_D0, sex_t::NA, - createTestGenePositions(genomeSz), + genePositions, ExpressionType::ADDITIVE, + genePositions, // initial positions (all) DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, not used isInherited, @@ -595,11 +605,14 @@ void testGenetics() { }; const map placeholderParams = mutationParams; + const set genePositions = createTestGenePositions(genomeSz); + SpeciesTrait* spTr = new SpeciesTrait( TraitType::GENETIC_LOAD1, sex_t::NA, - createTestGenePositions(genomeSz), + genePositions, ExpressionType::MULTIPLICATIVE, + genePositions, DistributionType::NONE, placeholderParams, // not used for genetic load DistributionType::NONE, dominanceParams, true, @@ -637,11 +650,14 @@ void testGenetics() { }; const map placeholderParams = mutationParams; + const set genePositions = createTestGenePositions(genomeSz); + SpeciesTrait* spTr = new SpeciesTrait( TraitType::GENETIC_LOAD1, sex_t::NA, - createTestGenePositions(genomeSz), + genePositions, ExpressionType::MULTIPLICATIVE, + genePositions, DistributionType::NONE, placeholderParams, // not used for genetic load DistributionType::NONE, placeholderParams, // doesn't matter for this test true, @@ -690,7 +706,7 @@ void testIndividual() { // (both freq. have p < 0.001 from a binomial with p 0.5 and 100 trials) { Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); const float recombinationRate = 0.01; const int genomeSz = 10; @@ -712,8 +728,8 @@ void testIndividual() { SpeciesTrait* spTr = createTestEmigSpTrait(genePositions, isDiploid); pSpecies->addTrait(TraitType::E_D0, *spTr); - Individual indMother = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); - Individual indFather = Individual(pCell, pPatch, 0, 0, 0, 1.0, false, 0); + Individual indMother = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, false, 0); + Individual indFather = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 1.0, false, 0); indMother.setUpGenes(pSpecies, 1.0); indFather.setUpGenes(pSpecies, 1.0); @@ -724,7 +740,7 @@ void testIndividual() { const int nbTrials = 100; for (int i = 0; i < nbTrials; ++i) { - Individual indChild = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + Individual indChild = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, false, 0); indChild.inheritTraits(pSpecies, &indMother, &indFather, 1.0); bool hasInheritedA0 = haveSameEmigD0Allele(indChild, indMother, posA); @@ -748,7 +764,7 @@ void testIndividual() { /// Emigration probability is 1 initially, but female trait mutates. { Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); // Species-level paramters const int genomeSz = 6; @@ -790,6 +806,7 @@ void testIndividual() { sex_t::MAL, maleGenePositions, ExpressionType::AVERAGE, + maleGenePositions, // Set all initial alleles values to 1 DistributionType::UNIFORM, initParams, DistributionType::NONE, initParams, // no dominance, params are ignored @@ -807,6 +824,7 @@ void testIndividual() { sex_t::FEM, femaleGenePositions, ExpressionType::AVERAGE, + femaleGenePositions, // Set all initial alleles values to 1 DistributionType::UNIFORM, initParams, DistributionType::NONE, initParams, // no dominance, params are ignored @@ -820,8 +838,8 @@ void testIndividual() { pSpecies->addTrait(TraitType::E_D0_F, *spTrF); // Set up male and female individuals, trigger mutations - Individual indFemale = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); - Individual indMale = Individual(pCell, pPatch, 0, 0, 0, 1.0, false, 0); + Individual indFemale = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, false, 0); + Individual indMale = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 1.0, false, 0); indFemale.setUpGenes(pSpecies, 1.0); indMale.setUpGenes(pSpecies, 1.0); indFemale.triggerMutations(pSpecies); @@ -842,7 +860,7 @@ void testIndividual() { float indEmigProb = 0.0; Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); // Species-level paramters const int genomeSz = 1; @@ -873,6 +891,7 @@ void testIndividual() { sex_t::NA, set{ 0 }, // only one locus ExpressionType::AVERAGE, + set{ 0 }, // initial positions DistributionType::UNIFORM, initParams, DistributionType::NONE, initParams, // no dominance, params are ignored true, // isInherited @@ -884,7 +903,7 @@ void testIndividual() { ); pSpecies->addTrait(TraitType::E_D0, *spTr); - Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + Individual ind = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, false, 0); ind.setUpGenes(pSpecies, 1.0); // Create population to trigger emigration selection @@ -913,7 +932,7 @@ void testIndividual() { // Individuals with genetic fitness = 0 are never viable { Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); // Species-level paramters const int genomeSz = 1; @@ -939,18 +958,20 @@ void testIndividual() { sex_t::NA, set{ 0 }, // only one locus ExpressionType::MULTIPLICATIVE, + set{ 0 }, DistributionType::NONE, initParams, - DistributionType::UNIFORM, domParams, // no dominance, params are ignored + DistributionType::UNIFORM, domParams, true, // isInherited 1.0, // will mutate DistributionType::UNIFORM, mutationParams, // lethal mutation - DistributionType::NONE, initParams, + DistributionType::UNIFORM, domParams, 2, // diploid false ); + pSpecies->addTrait(TraitType::GENETIC_LOAD1, *spTr); - Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + Individual ind = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, false, 0); ind.setUpGenes(pSpecies, 1.0); // By default, all loci are initialised at 0 so individual is viable @@ -964,10 +985,10 @@ void testIndividual() { assert(!ind.isViable()); } - // A largely dominant alleles overrides the expression of its homologue + // A largely dominant allele overrides the expression of its homologue { Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); // Species-level paramters const int genomeSz = 1; @@ -979,29 +1000,30 @@ void testIndividual() { set{}, "none", set{}, 0 // no output so no sampling ); - // Create species trait + // Create template species trait const map distParams{ pair{GenParamType::MIN, 0.0}, pair{GenParamType::MAX, 0.0} }; - + // Pretty empty, actual values are set below SpeciesTrait* spTr = new SpeciesTrait( TraitType::GENETIC_LOAD1, sex_t::NA, set{ 0 }, // only one locus ExpressionType::MULTIPLICATIVE, + set{ 0 }, DistributionType::NONE, distParams, - DistributionType::UNIFORM, distParams, // no dominance, params are ignored + DistributionType::UNIFORM, distParams, true, // isInherited 0.0, // no mutation - DistributionType::UNIFORM, distParams, // lethal mutation - DistributionType::NONE, distParams, + DistributionType::UNIFORM, distParams, + DistributionType::UNIFORM, distParams, 2, // diploid false ); pSpecies->addTrait(TraitType::GENETIC_LOAD1, *spTr); - Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + Individual ind = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, false, 0); ind.setUpGenes(pSpecies, 1.0); const float valAlleleA = 1.0; // lethal @@ -1031,7 +1053,7 @@ void testIndividual() { const float mutationRate = 0.0; // no mutations Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); // Genome-level settings Species* pSpecies = createDefaultSpecies(); @@ -1071,6 +1093,7 @@ void testIndividual() { sex_t::NA, set{ 0 }, ExpressionType::AVERAGE, + set{ 0 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1085,6 +1108,7 @@ void testIndividual() { sex_t::NA, set{ 1 }, ExpressionType::AVERAGE, + set{ 1 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1099,6 +1123,7 @@ void testIndividual() { sex_t::NA, set{ 2 }, ExpressionType::AVERAGE, + set{ 2 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1113,6 +1138,7 @@ void testIndividual() { sex_t::NA, set{ 3 }, ExpressionType::ADDITIVE, + set{ 3 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1128,7 +1154,7 @@ void testIndividual() { pSpecies->addTrait(TraitType::S_BETA, *trSettBeta); pSpecies->addTrait(TraitType::KERNEL_MEANDIST_1, *trMeanKern); - Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, false, 0); + Individual ind = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, false, 0); ind.setUpGenes(pSpecies, 1.0); // Overwrite genotypes with alleles resulting in invalid phenotypes @@ -1157,7 +1183,7 @@ void testIndividual() { const float mutationRate = 0.0; // no mutations Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); // Genome-level settings Species* pSpecies = createDefaultSpecies(); @@ -1189,6 +1215,7 @@ void testIndividual() { sex_t::NA, set{ 0 }, ExpressionType::ADDITIVE, + set{ 0 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1203,6 +1230,7 @@ void testIndividual() { sex_t::NA, set{ 1 }, ExpressionType::AVERAGE, + set{ 1 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1218,7 +1246,7 @@ void testIndividual() { bool usesMovtProcess = true; short whichMovtProcess = 2; // CRW - Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, usesMovtProcess, whichMovtProcess); + Individual ind = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, usesMovtProcess, whichMovtProcess); ind.setUpGenes(pSpecies, 1.0); // Overwrite genotypes with alleles resulting in invalid phenotypes @@ -1241,7 +1269,7 @@ void testIndividual() { const float mutationRate = 0.0; // no mutations Patch* pPatch = new Patch(0, 0); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); // Genome-level settings Species* pSpecies = createDefaultSpecies(); @@ -1273,6 +1301,7 @@ void testIndividual() { sex_t::NA, set{ 0 }, ExpressionType::ADDITIVE, + set{ 0 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1287,6 +1316,7 @@ void testIndividual() { sex_t::NA, set{ 1 }, ExpressionType::AVERAGE, + set{ 1 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1301,6 +1331,7 @@ void testIndividual() { sex_t::NA, set{ 0 }, ExpressionType::ADDITIVE, + set{ 0 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1315,6 +1346,7 @@ void testIndividual() { sex_t::NA, set{ 1 }, ExpressionType::AVERAGE, + set{ 1 }, DistributionType::UNIFORM, distParams, DistributionType::NONE, distParams, // no dominance, params are ignored true, // isInherited @@ -1332,7 +1364,7 @@ void testIndividual() { bool usesMovtProcess = true; short whichMovtProcess = 1; // SMS - Individual ind = Individual(pCell, pPatch, 0, 0, 0, 0.0, usesMovtProcess, whichMovtProcess); + Individual ind = Individual(pSpecies, pCell, pPatch, 0, 0, 0, 0.0, usesMovtProcess, whichMovtProcess); ind.setUpGenes(pSpecies, 1.0); // Overwrite genotypes with alleles resulting in invalid phenotypes diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index b8a63ed..3332e9f 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -12,7 +12,7 @@ void testNeutralStats() { const set patchList{ pPatch->getPatchNum() }; const string indSampling = "all"; const set stgToSample = { 1 }; - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); pPatch->addCell(pCell, 0, 0); // Create genetic structure @@ -59,7 +59,7 @@ void testNeutralStats() { const set patchList{ pPatch->getPatchNum() }; const string indSampling = "all"; const set stgToSample = { 1 }; - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); pPatch->addCell(pCell, 0, 0); // Create genetic structure @@ -106,7 +106,7 @@ void testNeutralStats() { const set patchList{ pPatch->getPatchNum() }; const string indSampling = "all"; const set stgToSample = { 1 }; - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); pPatch->addCell(pCell, 0, 0); // Create genetic structure @@ -167,7 +167,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -214,7 +214,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -267,7 +267,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -296,7 +296,7 @@ void testNeutralStats() { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + Individual* pInd = new Individual(pSpecies, cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); pInd->setUpGenes(pSpecies, 1.0); pPop->recruit(pInd); } @@ -341,7 +341,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -415,7 +415,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -445,7 +445,7 @@ void testNeutralStats() { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + Individual* pInd = new Individual(pSpecies, cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); pInd->setUpGenes(pSpecies, 1.0); pInd->overrideGenotype(NEUTRAL, genotypes[p]); pPop->recruit(pInd); @@ -517,7 +517,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -546,7 +546,7 @@ void testNeutralStats() { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + Individual* pInd = new Individual(pSpecies, cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); pInd->setUpGenes(pSpecies, 1.0); pInd->overrideGenotype(NEUTRAL, genotypes[i]); pPop->recruit(pInd); @@ -620,7 +620,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -649,7 +649,7 @@ void testNeutralStats() { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + Individual* pInd = new Individual(pSpecies, cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); pInd->setUpGenes(pSpecies, 1.0); pInd->overrideGenotype(NEUTRAL, genotypeList[p][i]); pPop->recruit(pInd); @@ -716,7 +716,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -745,7 +745,7 @@ void testNeutralStats() { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + Individual* pInd = new Individual(pSpecies, cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); pInd->setUpGenes(pSpecies, 1.0); pInd->overrideGenotype(NEUTRAL, genotypeAB); pPop->recruit(pInd); @@ -827,7 +827,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -856,7 +856,7 @@ void testNeutralStats() { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + Individual* pInd = new Individual(pSpecies, cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); pInd->setUpGenes(pSpecies, 1.0); pInd->overrideGenotype(NEUTRAL, genotypeList[p][i]); pPop->recruit(pInd); @@ -915,7 +915,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -944,7 +944,7 @@ void testNeutralStats() { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + Individual* pInd = new Individual(pSpecies, cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); pInd->setUpGenes(pSpecies, 1.0); pInd->overrideGenotype(NEUTRAL, genotypes[i]); pPop->recruit(pInd); @@ -1001,7 +1001,7 @@ void testNeutralStats() { set patchList; for (int i = 0; i < nbPatches; i++) { patches[i] = pLandscape->newPatch(i); - cells[i] = new Cell(0, 0, (intptr)patches[i], 0); + cells[i] = new Cell(0, 0, patches[i], 0); patches[i]->addCell(cells[i], 0, 0); patchList.insert(patches[i]->getPatchNum()); } @@ -1030,7 +1030,7 @@ void testNeutralStats() { Population* pPop = new Population(pSpecies, patches[p], 0, 1); // create individuals and add to pop for (int i = 0; i < nbIndsPerPop; i++) { - Individual* pInd = new Individual(cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); + Individual* pInd = new Individual(pSpecies, cells[p], patches[p], indStg, 0, 0, 0.0, false, 1); pInd->setUpGenes(pSpecies, 1.0); pInd->overrideGenotype(NEUTRAL, p == 0 ? genotypePop1 : genotypePop2); pPop->recruit(pInd); @@ -1059,4 +1059,4 @@ void testNeutralStats() { } } -#endif // NDEBUG \ No newline at end of file +#endif // NDEBUG diff --git a/unit_tests/testPopulation.cpp b/unit_tests/testPopulation.cpp index 031e956..01283b0 100644 --- a/unit_tests/testPopulation.cpp +++ b/unit_tests/testPopulation.cpp @@ -31,7 +31,7 @@ void testPopulation() for (float mutationRate : mutationRates) { Landscape* pLandscape = new Landscape; Patch* pPatch = pLandscape->newPatch(1); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); pPatch->addCell(pCell, 0, 0); Species* pSpecies = createDefaultSpecies(); @@ -47,6 +47,7 @@ void testPopulation() sex_t::NA, genePositions, ExpressionType::MULTIPLICATIVE, + genePositions, // initial positions (all) DistributionType::NONE, map{}, DistributionType::UNIFORM, domParams, true, // isInherited @@ -92,7 +93,7 @@ void testPopulation() for (float mutationRate : mutationRates) { Landscape* pLandscape = new Landscape; Patch* pPatch = pLandscape->newPatch(1); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); pPatch->addCell(pCell, 0, 0); Species* pSpecies = createDefaultSpecies(); @@ -117,11 +118,12 @@ void testPopulation() sex_t::NA, genePositions, ExpressionType::ADDITIVE, - DistributionType::UNIFORM, initParams, - DistributionType::NONE, map{}, // no dominance + genePositions, // initial positions (all) + DistributionType::UNIFORM, initParams, // initial distribution and params + DistributionType::NONE, map{}, // initial dominance (none) true, // isInherited mutationRate, // mutation rate - DistributionType::UNIFORM, mutParams, + DistributionType::UNIFORM, mutParams, // mutation dist and params DistributionType::NONE, map{}, // no dominance isDiploid ? 2 : 1, false @@ -174,7 +176,7 @@ void testPopulation() Landscape* pLandscape = new Landscape; Patch* pPatch = pLandscape->newPatch(1); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); pPatch->addCell(pCell, 0, 0); Species* pSpecies = new Species(); @@ -248,7 +250,7 @@ void testPopulation() Landscape* pLandscape = new Landscape; Patch* pPatch = pLandscape->newPatch(1); - Cell* pCell = new Cell(0, 0, (intptr)pPatch, 0); + Cell* pCell = new Cell(0, 0, pPatch, 0); pPatch->addCell(pCell, 0, 0); Species* pSpecies = new Species(); @@ -282,4 +284,4 @@ void testPopulation() } } -#endif // NDEBUG \ No newline at end of file +#endif // NDEBUG From f19dbdd1865061590ce55a346fb11a7da34d09dc Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Tue, 23 Sep 2025 13:24:43 +0200 Subject: [PATCH 325/332] adapted unit tests spatial demog. feature requires the reproduction() and survival0() functions to include a localScaling vector + needed global variable nDSLayer --- Individual.cpp | 41 ----------------------------------- Main.cpp | 1 + unit_tests/testPopulation.cpp | 15 ++++++++----- 3 files changed, 11 insertions(+), 46 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 2571572..e765e45 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1676,47 +1676,6 @@ double cauchy(double location, double scale) { //--------------------------------------------------------------------------- #ifndef NDEBUG -void testIndividual() { - - Species* pSpecies = new Species(); - - Patch* pPatch = new Patch(0, 0); - int cell_x = 2; - int cell_y = 5; - int cell_hab = 2; - Cell* pCell = new Cell(cell_x, cell_y, pPatch, cell_hab); - - // Create an individual - short stg = 0; - short age = 0; - short repInt = 0; - float probmale = 0; - bool uses_movt_process = true; - short moveType = 1; - Individual ind(pSpecies, pCell, pPatch, stg, age, repInt, probmale, uses_movt_process, moveType); - - // An individual can move to a neighbouring cell - //ind.moveto(); - - // Gets its sex drawn from pmale - - // Can age or develop - // Reproduces - // depending on whether it is sexual or not - // depending on the stage - // depending on the trait inheritance - - - // Disperses - // Emigrates - // Transfers - // Settles - - // Survives - - // Develops - -} Cell* Individual::getCurrCell() const { return pCurrCell; } diff --git a/Main.cpp b/Main.cpp index f0acdda..d676794 100644 --- a/Main.cpp +++ b/Main.cpp @@ -66,6 +66,7 @@ RSrandom* pRandom; Management* pManagement; // pointer to management routines Species* pSpecies; Community* pComm; +short nDSlayer=gMaxNbLayers; #if LINUX_CLUSTER || RS_RCPP int main(int argc, char* argv[]) diff --git a/unit_tests/testPopulation.cpp b/unit_tests/testPopulation.cpp index 01283b0..8c552ab 100644 --- a/unit_tests/testPopulation.cpp +++ b/unit_tests/testPopulation.cpp @@ -12,6 +12,7 @@ void testPopulation() vector survivingInds; const int initialNbInds = 1000; const float localK = 10000; // not limiting + vector localScaling = {1.0}; // Simple genetic layout const bool isDiploid{ false }; // haploid suffices @@ -60,7 +61,7 @@ void testPopulation() pSpecies->addTrait(TraitType::GENETIC_LOAD, *spTr); Population pop = Population(pSpecies, pPatch, initialNbInds, 1); - pop.reproduction(localK, 1, 1); // juveniles are checked for viability at birth + pop.reproduction(localK, 1, 1, localScaling); // juveniles are checked for viability at birth pop.fledge(); // non-overlapping: adults are replaced with juveniles survivingInds.push_back(pop.getNInds()); } @@ -74,6 +75,7 @@ void testPopulation() vector emigratingInds; const int initialNbInds = 1000; const float localK = 10000; // not limiting + vector localScaling = {1.0}; // Simple genetic layout const bool isDiploid{ false }; // haploid suffices @@ -131,7 +133,7 @@ void testPopulation() pSpecies->addTrait(TraitType::E_D0, *spTr); Population pop = Population(pSpecies, pPatch, initialNbInds, 1); - pop.reproduction(localK, 1, 1); + pop.reproduction(localK, 1, 1, localScaling); pop.fledge(); // replace initial pop with juveniles pop.emigration(localK); // select and flag emigrants int popSize = pop.totalPop(); @@ -153,6 +155,7 @@ void testPopulation() { float mutationRate = 0.0; const float localK = 10000.0; + vector localScaling = {1.0}; const int initialNbInds = localK; const float initFreqA = 0.7; const float exptdFreqA = initFreqA; // Allelic freqs are constant under HW @@ -204,9 +207,9 @@ void testPopulation() // Check allele frequencies conform to HW through generations for (int yr = 0; yr < nbGens; yr++) { - pop.reproduction(localK, 1, 1); + pop.reproduction(localK, 1, 1, localScaling); pop.fledge(); // replace initial pop with juveniles - pop.survival0(localK, 0, 0); // flag juveniles for development + pop.survival0(localK, 0, 0, localScaling); // flag juveniles for development pop.survival1(); // develop to stage 1 (breeders) // Count allele and heterozygote frequencies @@ -234,6 +237,8 @@ void testPopulation() const float hB = 1.0; // fully dominant float mutationRate = 0.0; const float localK = 10000.0; + vector localScaling = {1.0}; + const int initialNbInds = localK; const float tolerance = 0.02; // high tolerance, still a lot of stochasticity const float expectedFreqAA = initFreqA * initFreqA; @@ -277,7 +282,7 @@ void testPopulation() } // Check allele frequencies conform to HW - pop.reproduction(localK, 1, 1); + pop.reproduction(localK, 1, 1, localScaling); pop.fledge(); // replace initial pop with juveniles double obsFreqUnviable = 1 - pop.getNInds() / localK; assert(abs(obsFreqUnviable - expectedFreqAA) < tolerance); From 371e891a1757e00366c7dfd4c6a4d9e39f5a6ff7 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 26 Sep 2025 13:40:16 +0100 Subject: [PATCH 326/332] fix test by shuffling individuals --- Population.cpp | 10 ++-------- Population.h | 1 + unit_tests/testPopulation.cpp | 17 +++++++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Population.cpp b/Population.cpp index 22c302a..69f2fff 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1497,17 +1497,11 @@ void Population::clean(void) int ninds = (int)inds.size(); if (ninds > 0) { inds.erase(std::remove(inds.begin(), inds.end(), (Individual *)NULL), inds.end()); -#if RS_RCPP - shuffle(inds.begin(), inds.end(), pRandom->getRNG()); -#else - -#ifdef NDEBUG +#ifdef RS_RCPP || NDEBUG // do not randomise individuals in DEBUG mode, as the function uses rand() // and therefore the randomisation will differ between identical runs of RS shuffle(inds.begin(), inds.end(), pRandom->getRNG()); -#endif // NDEBUG - -#endif // RS_RCPP +#endif } } diff --git a/Population.h b/Population.h index 1ccaced..cd01d8c 100644 --- a/Population.h +++ b/Population.h @@ -242,6 +242,7 @@ class Population { #ifndef NDEBUG // Testing only void clearInds() { inds.clear(); } // empty inds vector to avoid deallocating individual is used separately in test + void shuffleInds() { shuffle(inds.begin(), inds.end(), pRandom->getRNG()); } #endif // NDEBUG private: diff --git a/unit_tests/testPopulation.cpp b/unit_tests/testPopulation.cpp index 162ca65..ba6b241 100644 --- a/unit_tests/testPopulation.cpp +++ b/unit_tests/testPopulation.cpp @@ -147,33 +147,36 @@ void testPopulation() } // In the absence of evolutionary forces, neutral gene - // frequencies conform to Hardy-Weinberg principle, i.e.: + // frequencies roughly conform to Hardy-Weinberg principle, i.e.: // 1 - Allele frequencies p and q remain constant through generations // 2 - Genotype frequencies conform to fAA = p^2, fAB = 2pq, fBB = q^2 { + const float tolerance = 0.05; // high tolerance, drift does happen + float mutationRate = 0.0; const float localK = 10000.0; const int initialNbInds = localK; - const float initFreqA = 0.7; + const float initFreqA = 0.20; const float exptdFreqA = initFreqA; // Allelic freqs are constant under HW const float exptdFreqB = 1 - exptdFreqA; const float exptdFreqHeteroZ = 2 * exptdFreqA * exptdFreqB; // according to HW - const int nbGens = 10; + const int nbGens = 50; float obsFreqA = 0.0; float obsFreqB = 0.0; float obsFreqHeteroZ = 0.0; - const float tolerance = 0.02; // fairly high tolerance, I expect a bit of drift to act. // Simple genetic layout + // 1 locus with two alleles A and B const bool isDiploid{ true }; // HW only applies to diploids const int genomeSz = 1; const set genePositions = { 0 }; - const float maxAlleleVal = 1; + const float maxAlleleVal = 10; unsigned char alleleA = char(0); unsigned char alleleB = char(1); auto genotypeAA = createTestNeutralGenotype(genomeSz, true, alleleA, alleleA); auto genotypeBB = createTestNeutralGenotype(genomeSz, true, alleleB, alleleB); + // Landscape is a single cell Landscape* pLandscape = new Landscape; Patch* pPatch = pLandscape->newPatch(1); Cell* pCell = new Cell(0, 0, pPatch, 0); @@ -190,7 +193,7 @@ void testPopulation() SpeciesTrait* spTr = createTestNeutralSpTrait(maxAlleleVal, genePositions, isDiploid); pSpecies->addTrait(TraitType::NEUTRAL, *spTr); - // Initialise population with + // Initialise population with initial frequencies for AA and BB Population pop = Population(pSpecies, pPatch, 0, 1); for (int i = 0; i < initialNbInds; i++) { Individual* pInd = new Individual(pSpecies, pCell, pPatch, 1, 0, 0, 0.5, false, 1); @@ -208,6 +211,7 @@ void testPopulation() pop.fledge(); // replace initial pop with juveniles pop.survival0(localK, 0, 0); // flag juveniles for development pop.survival1(); // develop to stage 1 (breeders) + pop.shuffleInds(); // Count allele and heterozygote frequencies pop.sampleIndsWithoutReplacement("all", { 1 }); @@ -220,6 +224,7 @@ void testPopulation() assert(abs(obsFreqA - exptdFreqA) < tolerance); assert(abs(obsFreqB - exptdFreqB) < tolerance); assert(abs(obsFreqHeteroZ - exptdFreqHeteroZ) < tolerance); + // Ideally one should do a statistical test against a random walk here } } From e1204166ecb72928cdfa8570d8fbc067d5808672 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 26 Sep 2025 13:48:55 +0100 Subject: [PATCH 327/332] shuffle individuals before reproduction --- unit_tests/testPopulation.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/unit_tests/testPopulation.cpp b/unit_tests/testPopulation.cpp index ba6b241..78bc90f 100644 --- a/unit_tests/testPopulation.cpp +++ b/unit_tests/testPopulation.cpp @@ -228,10 +228,12 @@ void testPopulation() } } - // Genetic load meets Hardy-Weinberg expectation + // Genetic load meets Hardy-Weinberg expectation on first generation // If a lethal (s = 1) recessive (h = 0) allele starts at freq 0.6, - // then (if no mutations) the prop. of unviable homozygote offspring should be 0.36 + // then (if no mutations) next gen should have 0.6^2 = 0.36 homozygotes dying at birth { + const float tolerance = 0.02; // high tolerance, still a lot of stochasticity + const float initFreqA = 0.6; const float sA = 1.0; // lethal const float hA = 0.0; // fully recessive @@ -240,7 +242,6 @@ void testPopulation() float mutationRate = 0.0; const float localK = 10000.0; const int initialNbInds = localK; - const float tolerance = 0.02; // high tolerance, still a lot of stochasticity const float expectedFreqAA = initFreqA * initFreqA; // Simple genetic layout @@ -282,6 +283,7 @@ void testPopulation() } // Check allele frequencies conform to HW + pop.shuffleInds(); pop.reproduction(localK, 1, 1); pop.fledge(); // replace initial pop with juveniles double obsFreqUnviable = 1 - pop.getNInds() / localK; From d256e689a8e39f4607bf71ab9361c9bf76a6d3a2 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Thu, 13 Nov 2025 10:38:03 +0100 Subject: [PATCH 328/332] reverted one change to see if unit tests are now successful --- Population.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Population.cpp b/Population.cpp index 8562c1c..d03b904 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1533,11 +1533,17 @@ void Population::clean(void) int ninds = (int)inds.size(); if (ninds > 0) { inds.erase(std::remove(inds.begin(), inds.end(), (Individual *)NULL), inds.end()); -#ifdef RS_RCPP || NDEBUG +#if RS_RCPP + shuffle(inds.begin(), inds.end(), pRandom->getRNG()); +#else + +#ifdef NDEBUG // do not randomise individuals in DEBUG mode, as the function uses rand() // and therefore the randomisation will differ between identical runs of RS shuffle(inds.begin(), inds.end(), pRandom->getRNG()); -#endif +#endif // NDEBUG + +#endif // RS_RCPP } } From 81212f073d3a904f9549c5317902c59eeca91a6f Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Fri, 14 Nov 2025 11:57:58 +0100 Subject: [PATCH 329/332] Manually merged changes from new_genetics Several changes were not considered during the last merge, I manually compared and edited the files. Hopefully GitHub Actions now run without issues. --- CMakeLists.txt | 2 + Cell.h | 4 +- Community.cpp | 163 ++++++++++++-- Community.h | 6 +- DispersalTrait.cpp | 4 +- DispersalTrait.h | 8 +- Individual.cpp | 9 +- Individual.h | 2 +- Landscape.cpp | 18 +- Landscape.h | 10 +- Main.cpp | 6 +- Management.cpp | 4 +- Model.cpp | 2 +- Model.h | 4 +- NeutralStatsManager.h | 4 +- NeutralTrait.cpp | 6 +- NeutralTrait.h | 4 +- Parameters.h | 4 +- Population.cpp | 321 +++------------------------ Population.h | 45 +--- RSrandom.cpp | 6 +- RSrandom.h | 4 +- Species.cpp | 14 +- Species.h | 11 +- SpeciesTrait.cpp | 4 +- SpeciesTrait.h | 6 +- SubCommunity.cpp | 380 ++++++++++++++++++++++++++++---- SubCommunity.h | 48 ++-- unit_tests/testIndividual.cpp | 82 ++++--- unit_tests/testNeutralStats.cpp | 4 +- unit_tests/testPopulation.cpp | 74 ++++--- 31 files changed, 733 insertions(+), 526 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8341dc8..af32b49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,8 @@ if(NOT batchmode) # that is, RScore as a standalone set(CMAKE_CXX_STANDARD_REQUIRED True) add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Management.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp "unit_tests/testIndividual.cpp" "unit_tests/testNeutralStats.cpp" "unit_tests/testPopulation.cpp") + # turn on unit tests + add_compile_definitions("UNIT_TESTS") else() # that is, RScore compiled as library within RangeShifter_batch add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticFitnessTrait.cpp Individual.cpp Landscape.cpp Management.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp DispersalTrait.cpp RSrandom.cpp NeutralTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) diff --git a/Cell.h b/Cell.h index bfafcd2..294671e 100644 --- a/Cell.h +++ b/Cell.h @@ -31,9 +31,9 @@ DistCell - Initial species distribution cell For full details of RangeShifter, please see: - Bocedi G., Palmer S.C.F., Pe?er G., Heikkinen R.K., Matsinos Y.G., Watts K. + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial - eco-evolutionary dynamics and species? responses to environmental changes. + eco-evolutionary dynamics and species’ responses to environmental changes. Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 Authors: Greta Bocedi & Steve Palmer, University of Aberdeen diff --git a/Community.cpp b/Community.cpp index d965756..e7f4fb4 100644 --- a/Community.cpp +++ b/Community.cpp @@ -24,6 +24,24 @@ #include "Community.h" +#ifdef _OPENMP +#ifdef __has_include +#if __has_include() +#include +#endif +#endif +#include +#if __cpp_lib_barrier >= 201907L && __cpp_lib_optional >= 201606L +#define HAS_BARRIER_LIB +#include +#include +#else +#include +#include +#endif +#include +#endif // _OPENMP + //--------------------------------------------------------------------------- @@ -389,12 +407,75 @@ void Community::emigration(void) } } -#if RS_RCPP // included also SEASONAL +#ifdef _OPENMP +#ifdef HAS_BARRIER_LIB +typedef std::optional> split_barrier; +#else +class split_barrier { +private: + std::mutex m; + std::condition_variable cv; + int threads_in_section; + int total_threads; + bool may_enter; + bool may_leave; + +public: + split_barrier(): + threads_in_section(0), + may_enter(false), + may_leave(false) + {} + + void emplace(int threads) { + std::lock_guard lock(m); + total_threads = threads; + may_enter = true; + } + + void enter() { + std::unique_lock lock(m); + cv.wait(lock, [this]{return may_enter;}); + if (++threads_in_section == total_threads) { + may_enter = false; + may_leave = true; + lock.unlock(); + cv.notify_all(); + } + } + + void leave() { + std::unique_lock lock(m); + cv.wait(lock, [this]{return may_leave;}); + if (--threads_in_section == 0) { + may_leave = false; + may_enter = true; + lock.unlock(); + cv.notify_all(); + } + } +}; +#endif // HAS_BARRIER_LIB +#endif // _OPENMP + +#if RS_RCPP void Community::dispersal(short landIx, short nextseason) #else void Community::dispersal(short landIx) #endif // RS_RCPP { +#ifdef _OPENMP + std::atomic nbStillDispersing; + split_barrier barrier; +#else + int nbStillDispersing; +#endif // _OPENMP + +#if RSDEBUG + int t0, t1, t2; + t0 = time(0); +#endif + simParams sim = paramsSim->getSim(); int nsubcomms = (int)subComms.size(); @@ -402,33 +483,70 @@ void Community::dispersal(short landIx) SubCommunity* matrix = subComms[0]; // matrix community is always the first #pragma omp parallel { - std::map> inds_map; + std::map> disperserPool; + + // All individuals in the matrix disperse again + // (= unsettled dispersers from previous generation) + matrix->disperseMatrix(disperserPool); + + // Recruit new emigrants #pragma omp for schedule(static,128) nowait - for (int i = 0; i < nsubcomms; i++) { // all populations - subComms[i]->initiateDispersal(inds_map); - } - for (std::pair>& item : inds_map) { - // add to matrix population - matrix->recruitMany(item.second, item.first); - } + for (int i = 0; i < nsubcomms; i++) { + subComms[i]->recruitDispersers(disperserPool); } +#ifdef _OPENMP +#pragma omp single + barrier.emplace(omp_get_num_threads()); +#endif // _OPENMP + - // dispersal is undertaken by all individuals now in the matrix patch - // (even if not physically in the matrix) - int ndispersers = 0; + // do { - #pragma omp parallel for schedule(static) - for (int i = 0; i < nsubcomms; i++) { // all populations +#pragma omp for schedule(guided) + for (int i = 0; i < nsubcomms; i++) { subComms[i]->resetPossSettlers(); } -#if RS_RCPP // included also SEASONAL - ndispersers = matrix->transfer(pLandscape, landIx, nextseason); + int localNbDispersers = matrix->resolveTransfer(disperserPool, pLandscape, landIx); +#pragma omp single nowait + nbStillDispersing = 0; +#pragma omp barrier +#if RS_RCPP + localNbDispersers += matrix->resolveSettlement(disperserPool, pLandscape, nextseason); #else - ndispersers = matrix->transfer(pLandscape, landIx); -#endif // SEASONAL || RS_RCPP - matrix->completeDispersal(pLandscape, sim.outConnect); - } while (ndispersers > 0); + localNbDispersers += matrix->resolveSettlement(disperserPool, pLandscape); +#endif // RS_RCPP + nbStillDispersing += localNbDispersers; + +#ifdef _OPENMP +#ifdef HAS_BARRIER_LIB + std::barrier<>::arrival_token token = barrier->arrive(); +#else + barrier.enter(); +#endif // HAS_BARRIER_LIB +#endif // _OPENMP + + matrix->completeDispersal(disperserPool, pLandscape, sim.outConnect); + +#ifdef _OPENMP +#ifdef HAS_BARRIER_LIB + barrier->wait(std::move(token)); +#else + barrier.leave(); +#endif // HAS_BARRIER_LIB +#endif // _OPENMP + + } while (nbStillDispersing > 0); + + // All unsettled dispersers are stored in matrix until next generation + for (auto & it : disperserPool) { + Species* const& pSpecies = it.first; + vector& inds = it.second; + matrix->recruitMany(inds, pSpecies); + } + } + + } void Community::survival0(short option0, short option1) @@ -732,14 +850,14 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) for (int stg = 1; stg < sstruct.nStages; stg++) { stagepop = 0; for (int i = 0; i < nsubcomms; i++) { // all sub-communities - stagepop += subComms[i]->stagePop(stg); + stagepop += subComms[i]->getNbInds(stg); } outrange << "\t" << stagepop; } // juveniles born in current reproductive season stagepop = 0; for (int i = 0; i < nsubcomms; i++) { // all sub-communities - stagepop += subComms[i]->stagePop(0); + stagepop += subComms[i]->getNbInds(0); } outrange << "\t" << stagepop; } @@ -1495,6 +1613,7 @@ Rcpp::IntegerMatrix Community::addYearToPopList(int rep, int yr) { // TODO: def return pop_map_year; } #endif + bool Community::openOutGenesFile(const bool& isDiploid, const int landNr, const int rep) { if (landNr == -999) { // close the file diff --git a/Community.h b/Community.h index 45b2e6c..5b1d8d7 100644 --- a/Community.h +++ b/Community.h @@ -35,9 +35,9 @@ Optionally, the Community maintains a record of the occupancy of suitable cells or patches during the course of simulation of multiple replicates. For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe?er G., Heikkinen R.K., Matsinos Y.G., Watts K. + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species? responses to environmental changes. + eco-evolutionary dynamics and species’ responses to environmental changes. Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 Authors: Greta Bocedi & Steve Palmer, University of Aberdeen @@ -62,8 +62,6 @@ using namespace std; #include "Species.h" #include "NeutralStatsManager.h" -// #include "Management.h" - //--------------------------------------------------------------------------- struct commStats { int ninds,nnonjuvs,suitable,occupied; diff --git a/DispersalTrait.cpp b/DispersalTrait.cpp index 8f6e7a6..53eb0e3 100644 --- a/DispersalTrait.cpp +++ b/DispersalTrait.cpp @@ -437,7 +437,7 @@ float DispersalTrait::getDomCoefAtLocus(short whichChromosome, int position) con return it->second[whichChromosome]->getDominanceCoef(); } -#ifndef NDEBUG +#ifdef UNIT_TESTS // Create a default set of alleles for testing // @@ -464,4 +464,4 @@ map>> createTestGenotype( } return genotype; } -#endif // NDEBUG \ No newline at end of file +#endif // UNIT_TESTS diff --git a/DispersalTrait.h b/DispersalTrait.h index 7060843..baed08c 100644 --- a/DispersalTrait.h +++ b/DispersalTrait.h @@ -44,7 +44,7 @@ class DispersalTrait : public QuantitativeTrait { float getAlleleValueAtLocus(short chromosome, int i) const override; float getDomCoefAtLocus(short chromosome, int position) const override; -#ifndef NDEBUG // for testing only +#ifdef UNIT_TESTS // for testing only void overwriteGenes(map>> genSeq) { genes = genSeq; } @@ -92,7 +92,7 @@ class DispersalTrait : public QuantitativeTrait { float expressAdditive(); }; -#ifndef NDEBUG +#ifdef UNIT_TESTS // Test utilities map>> createTestGenotype( @@ -102,6 +102,6 @@ map>> createTestGenotype( const float domCoeffA = 1.0, // default for dispersal traits const float domCoeffB = 1.0 ); -#endif // NDEBUG +#endif // UNIT_TESTS -#endif // DISPTRAITH \ No newline at end of file +#endif // DISPTRAITH diff --git a/Individual.cpp b/Individual.cpp index e765e45..7f2c616 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -136,7 +136,7 @@ Individual::Individual(Species* pSpecies, Cell* pCell, Patch* pPatch, short stg, #endif if (moveType == 1) { // SMS // set up location data for SMS - pTrfrData = make_unique(loc, loc); // what about the other parameter? + pTrfrData = make_unique(loc, loc); } if (moveType == 2) { // CRW @@ -789,9 +789,12 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, const bool } else meandist = kern.meanDist1 / (float)land.resol; + // scaled mean may not be less than 1 unless emigration derives from the kernel // (i.e. the 'use full kernel' option is applied) +# ifdef NDEBUG // bypass this requirement for tests if (!usefullkernel && meandist < 1.0) meandist = 1.0; +# endif int loopsteps = 0; // new counter to prevent infinite loop added 14/8/15 do { @@ -1674,7 +1677,7 @@ double cauchy(double location, double scale) { //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -#ifndef NDEBUG +#ifdef UNIT_TESTS Cell* Individual::getCurrCell() const { return pCurrCell; @@ -1741,5 +1744,5 @@ void Individual::overrideGenotype(TraitType whichTrait, const mapgetGenes() = newGenotype; }; -#endif // NDEBUG +#endif // UNIT_TESTS diff --git a/Individual.h b/Individual.h index 7724e05..12e4a69 100644 --- a/Individual.h +++ b/Individual.h @@ -374,7 +374,7 @@ class Individual { const int // year ); #endif -#ifndef NDEBUG +#ifdef UNIT_TESTS // Testing utilities Cell* getCurrCell() const; void setInitAngle(const float angle); diff --git a/Landscape.cpp b/Landscape.cpp index be252f4..099bb2c 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -2378,7 +2378,7 @@ resol = (int) tmpresol; dimX = ncols; dimY = nrows; - minX = maxY = 0; + minX = maxY = 0; // bottom-left / south-west corner maxX = dimX - 1; maxY = dimY - 1; @@ -2437,15 +2437,11 @@ resol = (int) tmpresol; habFloat = badHabFloat; #if RS_RCPP if (ifsHabMap >> habFloat) { - habCode = static_cast(habFloat); - if (patchModel) { + habCode = (int)habFloat; + if (patchModel) { patchFloat = badPatchFloat; -// #if RS_RCPP if (ifsPatchMap >> patchFloat) { -// #else -// ifsPatchMap >> patchFloat; -// #endif - patchCode = static_cast(patchFloat); + patchCode = (int)patchFloat; } else { // corrupt file stream #if !R_CMD @@ -3327,8 +3323,8 @@ void Landscape::outVisits(int rep, int landNr) { //--------------------------------------------------------------------------- -#ifndef NDEBUG -// Debug only: shortcut setup utilities +#ifdef UNIT_TESTS +// Tests only: shortcut setup utilities Landscape createLandscapeFromCells(vector cells, const landParams& lp, Species sp) { // Set up landscape @@ -3364,7 +3360,7 @@ landParams createDefaultLandParams(const int& dim) { void testLandscape() { // test coordinate system... } -#endif // NDEBUG +#endif // UNIT_TESTS //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- diff --git a/Landscape.h b/Landscape.h index b66647f..859fff4 100644 --- a/Landscape.h +++ b/Landscape.h @@ -58,9 +58,9 @@ to be intialised, which are specified by the user in FormSeeding. This option is available in the GUI version only. For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe?er G., Heikkinen R.K., Matsinos Y.G., Watts K. + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species? responses to environmental changes. + eco-evolutionary dynamics and species’ responses to environmental changes. Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 Authors: Greta Bocedi & Steve Palmer, University of Aberdeen @@ -118,7 +118,7 @@ class InitDist{ string // name of species distribution file ); void setDistribution( - int // no. of distribution cells to be initlandOriginialised (0 for all cells) + int // no. of distribution cells to be initialised (0 for all cells) ); void setDistCell( // Set a specified cell (by position in cells vector) int, // index no. of DistCell in cells vector @@ -538,7 +538,7 @@ class Landscape{ int nHab; // no. of habitats int nHabMax; // max. no. of habitats (used for batch input only) int dimX,dimY; // dimensions - int minX,minY; // minimum available X and Y co-ordinates + int minX, minY; // minimum available X and Y co-ordinates, i.e. coordinates of the bottom-right corner int maxX,maxY; // maximum available X and Y co-ordinates float minPct,maxPct; // min and max percentage of habitat in a cell float propSuit; // proportion of suitable cells @@ -595,7 +595,7 @@ extern paramInit *paramsInit; extern paramSim *paramsSim; extern RSrandom *pRandom; -#ifndef NDEBUG +#ifdef UNIT_TESTS landParams createDefaultLandParams(const int& dim); void testLandscape(); #endif diff --git a/Main.cpp b/Main.cpp index d676794..c7804f1 100644 --- a/Main.cpp +++ b/Main.cpp @@ -42,6 +42,7 @@ using namespace std; +#ifdef UNIT_TESTS void testIndividual(); void testNeutralStats(); void testPopulation(); @@ -55,6 +56,7 @@ void run_unit_tests() { testNeutralStats(); cout << endl << "************************" << endl; } +#endif // UNIT_TESTS // Global vars string landFile; @@ -74,8 +76,8 @@ int main(int argc, char* argv[]) int _tmain(int argc, _TCHAR* argv[]) #endif { -#ifdef NDEBUG - cout << "This code is only for running tests and not meant to run in release." << endl; +#ifndef UNIT_TESTS + cout << "This version is only for running unit tests." << endl; return 1; #else diff --git a/Management.cpp b/Management.cpp index 8cd6889..c6c7c53 100644 --- a/Management.cpp +++ b/Management.cpp @@ -135,7 +135,7 @@ void Management::translocate(int yr if (s_patch) { // if it is not a nullpointer // test if population in patch is not zero s_pPop = s_patch->getPopn(pSpecies); // returns the population of the species in that cell - if (s_pPop && s_pPop->getNInds() > 0){ + if (s_pPop && s_pPop->getNbInds() > 0){ } else { #if RS_RCPP Rcpp::Rcout << "Population does not exist in source patch or is 0! skipping translocation event." << endl; @@ -179,7 +179,7 @@ void Management::translocate(int yr s_patch = s_ppatch; // test if population in patch is not zero s_pPop = s_patch->getPopn(pSpecies); // returns the population of the species in that cell - if (s_pPop && s_pPop->getNInds() > 0){ + if (s_pPop && s_pPop->getNbInds() > 0){ } else { #if RS_RCPP Rcpp::Rcout << "Population does not exist in source cell or is 0! skipping translocation event." << endl; diff --git a/Model.cpp b/Model.cpp index ee4d214..ed598f0 100644 --- a/Model.cpp +++ b/Model.cpp @@ -521,7 +521,7 @@ int RunModel(Landscape* pLandscape, int seqsim) } // Resolve survival and devlpt - pComm->survival1(); // why without parsing 0 and 1? + pComm->survival1(); } // end of the generation loop diff --git a/Model.h b/Model.h index 5195f05..6ce2e46 100644 --- a/Model.h +++ b/Model.h @@ -33,9 +33,9 @@ Further functions are declared here, but defined differently in main function of GUI and batch versions. For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe?er G., Heikkinen R.K., Matsinos Y.G., Watts K. + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species? responses to environmental changes. + eco-evolutionary dynamics and species’ responses to environmental changes. Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 Authors: Greta Bocedi & Steve Palmer, University of Aberdeen diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index fac9791..9df4397 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -60,7 +60,9 @@ struct NeutralCountsTable { // Getters int getTally(int whichAllele) { return alleleTallies[whichAllele]; }; double getFrequency(int whichAllele) { return alleleFrequencies[whichAllele]; }; - int getHeteroTally(int whichAllele) { return alleleHeterozygoteTallies[whichAllele]; }; + int getHeteroTally(int whichAllele) { + return alleleHeterozygoteTallies[whichAllele]; + }; // Setters / increments void incrementTally(int whichAllele) { alleleTallies[whichAllele]++; }; diff --git a/NeutralTrait.cpp b/NeutralTrait.cpp index 7b50e92..c9774e1 100644 --- a/NeutralTrait.cpp +++ b/NeutralTrait.cpp @@ -194,7 +194,7 @@ void NeutralTrait::inheritDiploid(const bool& fromMother, mapsecond[whichChromosome]; } -#ifndef NDEBUG // Testing only +#ifdef UNIT_TESTS // Testing only // Create a default set of neutral alleles for testing // @@ -316,4 +316,4 @@ map> createTestNeutralGenotype( return genotype; } -#endif // NDEBUG \ No newline at end of file +#endif // UNIT_TESTS diff --git a/NeutralTrait.h b/NeutralTrait.h index 7cccf46..86976da 100644 --- a/NeutralTrait.h +++ b/NeutralTrait.h @@ -83,7 +83,7 @@ class NeutralTrait : public QuantitativeTrait { }; -#ifndef NDEBUG // for testing purposes only +#ifdef UNIT_TESTS // for testing purposes only map> createTestNeutralGenotype( const int genomeSz, const bool isDiploid, const unsigned char valAlleleA, @@ -91,4 +91,4 @@ map> createTestNeutralGenotype( ); #endif -#endif // NeutralTraitH \ No newline at end of file +#endif // NeutralTraitH diff --git a/Parameters.h b/Parameters.h index fad01c7..f3f78b3 100644 --- a/Parameters.h +++ b/Parameters.h @@ -34,9 +34,9 @@ paramStoch - Environmental stochasticity parameters Also declares some structures and functions used throughout the program. For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe?er G., Heikkinen R.K., Matsinos Y.G., Watts K. + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species? responses to environmental changes. + eco-evolutionary dynamics and species’ responses to environmental changes. Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 Authors: Greta Bocedi & Steve Palmer, University of Aberdeen diff --git a/Population.cpp b/Population.cpp index d03b904..34dbd0f 100644 --- a/Population.cpp +++ b/Population.cpp @@ -302,7 +302,7 @@ traitsums Population::getIndTraitsSums(Species* pSpecies) { return ts; } -int Population::getNInds() { return static_cast(inds.size()); } +//int Population::getNInds() { return static_cast(inds.size()); } // ---------------------------------------------------------------------------------------- // reset allele table @@ -488,25 +488,24 @@ popStats Population::getStats(std::vector localDemoScaling) Species* Population::getSpecies(void) { return pSpecies; } -int Population::totalPop(void) { - int t = 0; - for (int stg = 0; stg < nStages; stg++) { - for (int sex = 0; sex < nSexes; sex++) { - t += nInds[stg][sex]; - } - } - return t; +int Population::getNbInds() const { + return inds.size(); } -int Population::stagePop(int stg) { +int Population::getNbInds(int stg) const { int t = 0; - if (stg < 0 || stg >= nStages) return t; + if (stg < 0 || stg >= nStages) throw runtime_error("Attempt to get nb individuals for stage " + to_string(stg) + ", no such stage."); for (int sex = 0; sex < nSexes; sex++) { t += nInds[stg][sex]; } return t; } +int Population::getNbInds(int stg, int sex) const { + if (stg < 0 || stg >= nStages) throw runtime_error("Attempt to get nb individuals for stage " + to_string(stg) + ", no such stage."); + return nInds[stg][sex]; +} + //--------------------------------------------------------------------------- // Remove all Individuals void Population::extirpate(void) { @@ -616,7 +615,7 @@ void Population::reproduction(const float localK, const float envval, const int } } else // not stage-specific - effect = (float)totalPop(); + effect = (float)getNbInds(); if (localK > 0.0) fec[stg][0] *= exp(-effect / localK); } } @@ -871,7 +870,7 @@ void Population::emigration(float localK) // to avoid division by zero, assume carrying capacity is at least one individual // localK can be zero if there is a moving gradient or stochasticity in K if (localK < 1.0) localK = 1.0; - NK = static_cast(totalPop()) / localK; + NK = static_cast(getNbInds()) / localK; int ninds = static_cast(inds.size()); @@ -939,7 +938,7 @@ void Population::emigration(float localK) else { // non-structured or individual is in emigration stage eparams = inds[i]->getIndEmigTraits(); if (emig.densDep) { // density-dependent - NK = (float)totalPop() / localK; + NK = (float)getNbInds() / localK; pbDisp = eparams.d0 / (1.0 + exp(-(NK - eparams.beta) * eparams.alpha)); } else { // density-independent @@ -1008,6 +1007,15 @@ void Population::allEmigrate(void) { } } +// Remove an Individual from the Population +Individual* Population::extractIndividual(int ix) { + Individual* pInd = inds[ix]; + indStats ind = pInd->getStats(); + inds[ix] = nullptr; + nInds[ind.stage][ind.sex]--; + return pInd; +} + // If an Individual has been identified as an emigrant, remove it from the Population disperser Population::extractDisperser(int ix) { disperser d = disperser(); @@ -1015,7 +1023,7 @@ disperser Population::extractDisperser(int ix) { if (ind.status == 1) { // emigrant d.pInd = inds[ix]; d.yes = true; - inds[ix] = 0; + inds[ix] = nullptr; nInds[ind.stage][ind.sex]--; } else { @@ -1057,283 +1065,16 @@ void Population::recruit(Individual* pInd) { // Add specified individuals to the new/current dispersal group // Add specified individuals to the population -void Population::recruitMany(std::vector& new_inds) { - if (new_inds.empty()) return; - for (Individual* pInd : new_inds) { +void Population::recruitMany(std::vector& recruits) { + if (recruits.empty()) return; + for (Individual* pInd : recruits) { indStats ind = pInd->getStats(); nInds[ind.stage][ind.sex]++; } #ifdef _OPENMP const std::lock_guard lock(inds_mutex); #endif // _OPENMP - inds.insert(inds.end(), new_inds.begin(), new_inds.end()); -} - -//--------------------------------------------------------------------------- - -// Transfer is run for populations in the matrix only -#if RS_RCPP // included also SEASONAL -int Population::transfer(Landscape* pLandscape, short landIx, short nextseason) -#else -int Population::transfer(Landscape* pLandscape, short landIx) -#endif -{ - int ndispersers = 0; - int disperser; - short othersex; - bool mateOK, densdepOK; - int patchnum; - double localK, popsize, settprob; - Patch* pPatch = 0; - Cell* pCell = 0; - indStats ind; - Population* pNewPopn = 0; - locn newloc = locn(); - locn nbrloc = locn(); - - landData ppLand = pLandscape->getLandData(); - short reptype = pSpecies->getRepType(); - transferRules trfr = pSpecies->getTransferRules(); - settleType settletype = pSpecies->getSettle(); - settleRules sett; - settleTraits settDD; - settlePatch settle; - simParams sim = paramsSim->getSim(); - // each individual takes one step - // for dispersal by kernel, this should be the only step taken - int ninds = (int)inds.size(); - #pragma omp parallel for reduction(+:ndispersers) private(disperser, pCell, pPatch) schedule(static,128) - for (int i = 0; i < ninds; i++) { - if (trfr.usesMovtProc) { - - disperser = inds[i]->moveStep(pLandscape, pSpecies, landIx, sim.absorbing); - } - else { - disperser = inds[i]->moveKernel(pLandscape, pSpecies, sim.absorbing); - } - ndispersers += disperser; - if (disperser) { - if (reptype > 0) - { // sexual species - record as potential settler in new patch - if (inds[i]->getStatus() == 2) - { // disperser has found a patch - pCell = inds[i]->getCurrCell(); - pPatch = pCell->getPatch(); - if (pPatch != nullptr) { // not no-data area - pPatch->incrPossSettler(pSpecies, inds[i]->getSex()); - } - } - } - } - } - -// each individual which has reached a potential patch decides whether to settle - #pragma omp parallel for reduction(-:ndispersers) default(none) shared(ninds, settletype, pRandom, trfr, ppLand, pLandscape) private(ind, othersex, sett, pCell, mateOK, densdepOK, settle, pPatch, localK, popsize, pNewPopn, settDD, settprob, newloc, nbrloc, patchnum) schedule(static) - for (int i = 0; i < ninds; i++) { - ind = inds[i]->getStats(); - if (ind.sex == 0) othersex = 1; else othersex = 0; - if (settletype.stgDep) { - if (settletype.sexDep) sett = pSpecies->getSettRules(ind.stage, ind.sex); - else sett = pSpecies->getSettRules(ind.stage, 0); - } - else { - if (settletype.sexDep) sett = pSpecies->getSettRules(0, ind.sex); - else sett = pSpecies->getSettRules(0, 0); - } - if (ind.status == 2) - { // awaiting settlement - pCell = inds[i]->getCurrCell(); - if (pCell == 0) { - // this condition can occur in a patch-based model at the time of a dynamic landscape - // change when there is a range restriction in place, since a patch can straddle the - // range restriction and an individual forced to disperse upon patch removal could - // start its trajectory beyond the boundary of the restrictyed range - such a model is - // not good practice, but the condition must be handled by killing the individual conceerned - ind.status = 6; - } - else { - mateOK = false; - if (sett.findMate) { - // determine whether at least one individual of the opposite sex is present in the - // new population - if (matePresent(pCell, othersex)) mateOK = true; - } - else { // no requirement to find a mate - mateOK = true; - } - densdepOK = false; - settle = inds[i]->getSettPatch(); - if (sett.densDep) - { - pPatch = pCell->getPatch(); - if (pPatch != nullptr) { // not no-data area - if (settle.settleStatus == 0 - || settle.pSettPatch != pPatch) - // note: second condition allows for having moved from one patch to another - // adjacent one - { - // determine whether settlement occurs in the (new) patch - localK = (double)pPatch->getK(); - pNewPopn = pPatch->getPopn(pSpecies); - if (pNewPopn == nullptr) { // population has not been set up in the new patch - popsize = 0.0; - } - else { - popsize = (double)pNewPopn->totalPop(); - } - if (localK > 0.0) { - // make settlement decision - if (settletype.indVar) settDD = inds[i]->getIndSettTraits(); //here I might need to adapt for R pkg - else settDD = pSpecies->getSpSettTraits(ind.stage, ind.sex); - settprob = settDD.s0 / - (1.0 + exp(-(popsize / localK - (double)settDD.beta) * (double)settDD.alpha)); - if (pRandom->Bernoulli(settprob)) { // settlement allowed - densdepOK = true; - settle.settleStatus = 2; - } - else { // settlement procluded - settle.settleStatus = 1; - } - settle.pSettPatch = pPatch; - } - inds[i]->setSettPatch(settle); - } - else { - if (settle.settleStatus == 2) { // previously allowed to settle - densdepOK = true; - } - } - } - } - else { // no density-dependent settlement - densdepOK = true; - settle.settleStatus = 2; - settle.pSettPatch = pPatch; - inds[i]->setSettPatch(settle); - } - - if (mateOK && densdepOK) { // can recruit to patch - ind.status = 4; - ndispersers--; - } - else { // does not recruit - if (trfr.usesMovtProc) { - ind.status = 1; // continue dispersing, unless ... - // ... maximum steps has been exceeded - pathSteps steps = inds[i]->getSteps(); - settleSteps settsteps = pSpecies->getSteps(ind.stage, ind.sex); - if (steps.year >= settsteps.maxStepsYr) { - ind.status = 3; // waits until next year - } - if (steps.total >= settsteps.maxSteps) { - ind.status = 6; // dies - } - } - else { // dispersal kernel - if (sett.wait) { - ind.status = 3; // wait until next dispersal event - } - else { - ind.status = 6; // (dies unless a neighbouring cell is suitable) - } - ndispersers--; - } - } - } - - inds[i]->setStatus(ind.status); - } -#if RS_RCPP - // write each individuals current movement step and status to paths file - if (trfr.usesMovtProc && sim.outPaths) { - if (nextseason >= sim.outStartPaths && nextseason % sim.outIntPaths == 0) { - inds[i]->outMovePath(nextseason); - } - } -#endif - if (!trfr.usesMovtProc && sett.go2nbrLocn && (ind.status == 3 || ind.status == 6)) - { - // for kernel-based transfer only ... - // determine whether recruitment to a neighbouring cell is possible - - pCell = inds[i]->getCurrCell(); - newloc = pCell->getLocn(); - vector nbrlist; - for (int dx = -1; dx < 2; dx++) { - for (int dy = -1; dy < 2; dy++) { - if (dx != 0 || dy != 0) { //cell is not the current cell - nbrloc.x = newloc.x + dx; nbrloc.y = newloc.y + dy; - if (nbrloc.x >= 0 && nbrloc.x <= ppLand.maxX - && nbrloc.y >= 0 && nbrloc.y <= ppLand.maxY) { // within landscape - // add to list of potential neighbouring cells if suitable, etc. - pCell = pLandscape->findCell(nbrloc.x, nbrloc.y); - if (pCell != 0) { // not no-data area - pPatch = pCell->getPatch(); - if (pPatch != nullptr) { // not no-data area - patchnum = pPatch->getPatchNum(); - if (patchnum > 0 && pPatch != inds[i]->getNatalPatch()) - { // not the matrix or natal patch - if (pPatch->getK() > 0.0) - { // suitable - if (sett.findMate) { - if (matePresent(pCell, othersex)) nbrlist.push_back(pCell); - } - else - nbrlist.push_back(pCell); - } - } - } - } - } - } - } - } - int listsize = (int)nbrlist.size(); - if (listsize > 0) { // there is at least one suitable neighbouring cell - if (listsize == 1) { - inds[i]->moveto(nbrlist[0]); - } - else { // select at random from the list - int rrr = pRandom->IRandom(0, listsize - 1); - inds[i]->moveto(nbrlist[rrr]); - } - } - // else list empty - do nothing - individual retains its current location and status - } - } - return ndispersers; -} - -// Determine whether there is a potential mate present in a patch which a potential -// settler has reached -bool Population::matePresent(Cell* pCell, short othersex) -{ - Patch* pPatch; - Population* pNewPopn; - int popsize = 0; - bool matefound = false; - - pPatch = pCell->getPatch(); - if (pPatch != nullptr) { - if (pPatch->getPatchNum() > 0) { // not the matrix patch - if (pPatch->getK() > 0.0) - { // suitable - pNewPopn = pPatch->getPopn(pSpecies); - if (pNewPopn != nullptr) { - // count members of other sex already resident in the patch - for (int stg = 0; stg < nStages; stg++) { - popsize += pNewPopn->nInds[stg][othersex]; - } - } - if (popsize < 1) { - // add any potential settlers of the other sex - popsize += pPatch->getPossSettlers(pSpecies, othersex); - } - } - } - } - if (popsize > 0) matefound = true; - return matefound; + inds.insert(inds.end(), recruits.begin(), recruits.end()); } //--------------------------------------------------------------------------- @@ -1431,7 +1172,7 @@ void Population::survival0(float localK, short option0, short option1, std::vect } } else // not stage-specific - effect = (float)totalPop(); + effect = (float)getNbInds(); if (localK > 0.0) dev[stg][sex] *= exp(-(ddparams.devCoeff * effect) / localK); } // end of if (sstruct.devDens && stg > 0) @@ -1458,7 +1199,7 @@ void Population::survival0(float localK, short option0, short option1, std::vect } } else // not stage-specific - effect = (float)totalPop(); + effect = (float)getNbInds(); if (localK > 0.0) surv[stg][sex] *= exp(-(ddparams.survCoeff * effect) / localK); } // end of if (sstruct.survDens) @@ -1504,7 +1245,7 @@ void Population::survival1(void) if (ind.status > 5 && ind.status != 10) { // doomed to die; status 10 is translocated? if (ind.status != 10) //not going into cold storage -> is there a new status 10 in this new_genetics version?? delete inds[i]; - inds[i] = NULL; + inds[i] = nullptr; nInds[ind.stage][ind.sex]--; } else { @@ -1656,7 +1397,7 @@ void Population::outPopulation(int rep, int yr, int gen, float eps, } } else { // non-structured population - outPop << "\t" << totalPop(); + outPop << "\t" << getNbInds(); if (dem.repType != 0) { // sexual model outPop << "\t" << nInds[1][0] << "\t" << nInds[1][1]; diff --git a/Population.h b/Population.h index 90ffb77..dbf30e1 100644 --- a/Population.h +++ b/Population.h @@ -34,9 +34,9 @@ The matrix Population(s) hold(s) Individuals which are currently in the process of transfer through the matrix. For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe?er G., Heikkinen R.K., Matsinos Y.G., Watts K. + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species? responses to environmental changes. + eco-evolutionary dynamics and species’ responses to environmental changes. Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 Authors: Greta Bocedi & Steve Palmer, University of Aberdeen @@ -128,11 +128,9 @@ class Population { std::vector ); Species* getSpecies(void); - int getNInds(void); - int totalPop(void); - int stagePop( // return no. of Individuals in a specified stage - int // stage - ); + int getNbInds() const; + int getNbInds(int stg) const ; + int getNbInds(int stg, int sex) const; void extirpate(void); // Remove all individuals void reproduction( const float, // local carrying capacity @@ -146,6 +144,10 @@ class Population { float // local carrying capacity ); void allEmigrate(void); // All individuals emigrate after patch destruction + // Remove an individual from the Population + Individual* extractIndividual( + int // index no. to the Individual in the inds vector + ); // If an individual has been identified as an emigrant, remove it from the Population disperser extractDisperser( int // index no. to the Individual in the inds vector @@ -166,30 +168,7 @@ class Population { void recruitMany( // Add specified individuals to the population std::vector& // vector of pointers to Individuals ); -#if RS_RCPP - int transfer( // Executed for the Population(s) in the matrix only - Landscape*, // pointer to Landscape - short, // landscape change index - short // year - ); - // Determine whether there is a potential mate present in a patch which a potential - // settler has reached - bool matePresent( - Cell*, // pointer to the Cell which the potential settler has reached - short // sex of the required mate (0 = female, 1 = male) - ); -#else - int transfer( // Executed for the Population(s) in the matrix only - Landscape*, // pointer to Landscape - short // landscape change index - ); - // Determine whether there is a potential mate present in a patch which a potential - // settler has reached - bool matePresent( - Cell*, // pointer to the Cell which the potential settler has reached - short // sex of the required mate (0 = female, 1 = male) - ); -#endif // RS_RCPP + // Determine survival and development and record in individual's status code // Changes are NOT applied to the Population at this stage void survival0( @@ -277,11 +256,11 @@ class Population { bool getSizeSampledInds( ); -#ifndef NDEBUG +#ifdef UNIT_TESTS // Testing only void clearInds() { inds.clear(); } // empty inds vector to avoid deallocating individual is used separately in test void shuffleInds() { shuffle(inds.begin(), inds.end(), pRandom->getRNG()); } -#endif // NDEBUG +#endif // UNIT_TESTS private: short nStages; diff --git a/RSrandom.cpp b/RSrandom.cpp index 1bc5126..b712f49 100644 --- a/RSrandom.cpp +++ b/RSrandom.cpp @@ -83,7 +83,7 @@ RSrandom::RSrandom() { #ifndef NDEBUG // fixed seed - RS_random_seed = 666; + RS_random_seed = 11011; #else // random seed #if LINUX_CLUSTER @@ -230,7 +230,7 @@ void RSrandom::fixNewSeed(int seed) { //-------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------- -#ifndef NDEBUG +#ifdef UNIT_TESTS #if !RS_RCPP void testRSrandom() { @@ -254,5 +254,5 @@ void RSrandom::fixNewSeed(int seed) { } } #endif -#endif // NDEBUG +#endif // UNIT_TESTS //--------------------------------------------------------------------------- diff --git a/RSrandom.h b/RSrandom.h index afea808..ac4ee31 100644 --- a/RSrandom.h +++ b/RSrandom.h @@ -85,9 +85,9 @@ class RSrandom std::normal_distribution<>* pNormal; }; -#ifndef NDEBUG +#ifdef UNIT_TESTS void testRSrandom(); -#endif // NDEBUG +#endif // UNIT_TESTS //--------------------------------------------------------------------------- diff --git a/Species.cpp b/Species.cpp index c37f572..0b344fb 100644 --- a/Species.cpp +++ b/Species.cpp @@ -874,7 +874,7 @@ void Species::setSamplePatchList(const set& samplePatchList) { //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -#ifndef NDEBUG +#ifdef UNIT_TESTS // For testing purposes only Species* createDefaultSpecies() { @@ -888,6 +888,16 @@ Species* createDefaultSpecies() { return pSpecies; } +// Set kernel parameters, but ignore constraints on values +// Used to test dispersal with values < resolution +void Species::overrideKernels(const short stg, const short sex, + const trfrKernelParams k) +{ + meanDist1[stg][sex] = k.meanDist1; + meanDist2[stg][sex] = k.meanDist2; + probKern1[stg][sex] = k.probKern1; +} + demogrParams createDefaultHaploidDemogrParams() { demogrParams d; d.repType = 0; @@ -912,4 +922,4 @@ demogrParams createDefaultDiploidDemogrParams() { return d; } -#endif // NDEBUG +#endif // UNIT_TESTS diff --git a/Species.h b/Species.h index cae31c6..e214241 100644 --- a/Species.h +++ b/Species.h @@ -438,6 +438,13 @@ class Species { const trfrKernelParams, // structure holding transfer by kernel parameters const int // Landscape resolution ); + +#ifdef UNIT_TESTS + // Testing: set dispersal but ignore resolution + void overrideKernels(const short stg, const short sex, + const trfrKernelParams k); +# endif // UNIT_TESTS + trfrKernelParams getSpKernTraits( // Get transfer by kernel parameters short, // stage short // sex @@ -670,12 +677,12 @@ class Species { //--------------------------------------------------------------------------- -#ifndef NDEBUG +#ifdef UNIT_TESTS // For testing purposes only Species* createDefaultSpecies(); demogrParams createDefaultHaploidDemogrParams(); demogrParams createDefaultDiploidDemogrParams(); -#endif // NDEBUG +#endif // UNIT_TESTS //--------------------------------------------------------------------------- #endif diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index ec7358b..418c222 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -202,7 +202,7 @@ bool SpeciesTrait::isValidTraitVal(const float& val) const { } } -#ifndef NDEBUG // Testing only +#ifdef UNIT_TESTS // Testing only // Create a default set of gene positions ranging from zero to genome size set createTestGenePositions(const int genomeSz) { @@ -296,4 +296,4 @@ SpeciesTrait* createTestNeutralSpTrait(const float& maxAlleleVal, const set return spTr; } -#endif // NDEBUG +#endif // UNIT_TESTS diff --git a/SpeciesTrait.h b/SpeciesTrait.h index d143199..69b1313 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -95,12 +95,12 @@ class SpeciesTrait { map mutationParameters; }; -#ifndef NDEBUG // Testing only +#ifdef UNIT_TESTS // Testing only // Create a default set of gene positions ranging from zero to genome size set createTestGenePositions(const int genomeSz); SpeciesTrait* createTestEmigSpTrait(const set& genePositions, const bool& isDiploid); SpeciesTrait* createTestGenLoadTrait(const set& genePositions, const bool& isDiploid); SpeciesTrait* createTestNeutralSpTrait(const float& maxAlleleVal, const set& genePositions, const bool& isDiploid); -#endif // NDEBUG +#endif // UNIT_TESTS -#endif // SPECIESTRAITH \ No newline at end of file +#endif // SPECIESTRAITH diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 91ba0f8..7a31bb2 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -297,7 +297,7 @@ void SubCommunity::emigration(void) } // Remove emigrants from their natal patch and add to a map of vectors -void SubCommunity::initiateDispersal(std::map> &inds_map) { +void SubCommunity::recruitDispersers(std::map>& disperserPool) { if (subCommNum == 0) return; // no dispersal initiation in the matrix popStats pop; disperser disp; @@ -309,7 +309,7 @@ void SubCommunity::initiateDispersal(std::map for (int j = 0; j < pop.nInds; j++) { disp = popns[i]->extractDisperser(j); if (disp.yes) { // disperser - has already been removed from natal population - inds_map[pSpecies].push_back(disp.pInd); + disperserPool[pSpecies].push_back(disp.pInd); } } // remove pointers to emigrants @@ -317,6 +317,26 @@ void SubCommunity::initiateDispersal(std::map } } +// Add all individuals in the matrix to the disperser pool +void SubCommunity::disperseMatrix(std::map> &inds_map) { + if (subCommNum != 0) return; + popStats pop; + + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { + pop = popns[i]->getStats(pPatch->getDemoScaling()); + Species* pSpecies = popns[i]->getSpecies(); +#pragma omp for schedule(static) + for (int j = 0; j < pop.nInds; j++) { + Individual *pInd = popns[i]->extractIndividual(j); + inds_map[pSpecies].push_back(pInd); + } +#pragma omp single + popns[i]->clean(); + } + +} + // Add an individual into the local population of its species in the patch void SubCommunity::recruit(Individual* pInd, Species* pSpecies) { int npops = (int)popns.size(); @@ -337,56 +357,338 @@ void SubCommunity::recruitMany(std::vector& inds, Species* pSpecies } } -// Transfer through the matrix - run for the matrix sub-community only -#if RS_RCPP -int SubCommunity::transfer(Landscape* pLandscape, short landIx, short nextseason) +// Transfer through the matrix - run for a per-species map of vectors of individuals +int SubCommunity::resolveTransfer(std::map>& dispersingInds, Landscape* pLandscape, short landIx) +{ + int nbStillDispersing = 0; + int disperser; + Patch* pPatch = nullptr; + Cell* pCell = nullptr; + simParams sim = paramsSim->getSim(); + + for (auto & it : dispersingInds) { // all species + + Species* const& pSpecies = it.first; + short reptype = pSpecies->getRepType(); + transferRules trfr = pSpecies->getTransferRules(); + + vector& inds = it.second; + + // each individual takes one step + // for dispersal by kernel, this should be the only step taken + for (auto& pInd : inds) { + if (trfr.usesMovtProc) { + disperser = pInd->moveStep(pLandscape, pSpecies, landIx, sim.absorbing); + } + else { + disperser = pInd->moveKernel(pLandscape, pSpecies, sim.absorbing); + } + nbStillDispersing += disperser; + if (disperser) { + if (reptype > 0) + { // sexual species - record as potential settler in new patch + if (pInd->getStatus() == 2) + { // disperser has found a patch + pCell = pInd->getCurrCell(); + pPatch = pCell->getPatch(); + if (pPatch != nullptr) { // not no-data area + pPatch->incrPossSettler(pSpecies, pInd->getSex()); + } + } + } + } + } + } + return nbStillDispersing; +} + + +// Determine whether there is a potential mate present in a patch which a potential +// settler has reached +bool SubCommunity::matePresent(Species* pSpecies, Cell* pCell, short othersex) +{ + Patch* pPatch; + Population* pNewPopn; + int popsize = 0; + bool matefound = false; + + pPatch = pCell->getPatch(); + if (pPatch != nullptr) { + if (pPatch->getPatchNum() > 0) { // not the matrix patch + if (pPatch->getK() > 0.0) + { // suitable + pNewPopn = pPatch->getPopn(pSpecies); + if (pNewPopn != nullptr) { + const stageParams sstruct = pSpecies->getStageParams(); + // count members of other sex already resident in the patch + for (int stg = 0; stg < sstruct.nStages; stg++) { + popsize += pNewPopn->getNbInds(stg, othersex); + } + } + if (popsize < 1) { + // add any potential settlers of the other sex + popsize += pPatch->getPossSettlers(pSpecies, othersex); + } + } + } + } + if (popsize > 0) matefound = true; + return matefound; +} + +// Transfer is run for populations in the matrix only +#if RS_RCPP // included also SEASONAL +int SubCommunity::resolveSettlement(std::map>& dispersingInds, Landscape* pLandscape, short nextseason) #else -int SubCommunity::transfer(Landscape* pLandscape, short landIx) -#endif // RS_RCPP +int SubCommunity::resolveSettlement(std::map>& dispersingInds, Landscape* pLandscape) +#endif { - int ndispersers = 0; - int npops = (int)popns.size(); - for (int i = 0; i < npops; i++) { // all populations + int nbStillDispersing = 0; + short othersex; + bool mateOK, densdepOK; + int patchnum; + double localK, popsize, settprob; + Patch* pPatch = 0; + Cell* pCell = 0; + indStats ind; + Population* pNewPopn = 0; + locn newloc, nbrloc; + + landData ppLand = pLandscape->getLandData(); + settleRules sett; + settleTraits settDD; + settlePatch settle; + simParams sim = paramsSim->getSim(); + + for (auto& it : dispersingInds) { // all species + Species* const& pSpecies = it.first; + transferRules trfr = pSpecies->getTransferRules(); + settleType settletype = pSpecies->getSettle(); + + vector& inds = it.second; + + // each individual which has reached a potential patch decides whether to settle + for (auto& pInd : inds) { + ind = pInd->getStats(); + if (ind.sex == 0) othersex = 1; else othersex = 0; + if (settletype.stgDep) { + if (settletype.sexDep) sett = pSpecies->getSettRules(ind.stage, ind.sex); + else sett = pSpecies->getSettRules(ind.stage, 0); + } + else { + if (settletype.sexDep) sett = pSpecies->getSettRules(0, ind.sex); + else sett = pSpecies->getSettRules(0, 0); + } + if (ind.status == 2) + { // awaiting settlement + pCell = pInd->getCurrCell(); + if (pCell == 0) { + // this condition can occur in a patch-based model at the time of a dynamic landscape + // change when there is a range restriction in place, since a patch can straddle the + // range restriction and an individual forced to disperse upon patch removal could + // start its trajectory beyond the boundary of the restrictyed range - such a model is + // not good practice, but the condition must be handled by killing the individual conceerned + ind.status = 6; + } + else { + mateOK = false; + if (sett.findMate) { + // determine whether at least one individual of the opposite sex is present in the + // new population + if (matePresent(pSpecies, pCell, othersex)) mateOK = true; + } + else { // no requirement to find a mate + mateOK = true; + } + + densdepOK = false; + settle = pInd->getSettPatch(); + if (sett.densDep) + { + pPatch = pCell->getPatch(); + if (pPatch != nullptr) { // not no-data area + if (settle.settleStatus == 0 + || settle.pSettPatch != pPatch) + // note: second condition allows for having moved from one patch to another + // adjacent one + { + // determine whether settlement occurs in the (new) patch + localK = (double)pPatch->getK(); + pNewPopn = pPatch->getPopn(pSpecies); + if (pNewPopn == nullptr) { // population has not been set up in the new patch + popsize = 0.0; + } + else { + popsize = (double)pNewPopn->getNbInds(); + } + if (localK > 0.0) { + // make settlement decision + if (settletype.indVar) settDD = pInd->getIndSettTraits(); #if RS_RCPP - ndispersers += popns[i]->transfer(pLandscape, landIx, nextseason); + else settDD = pSpecies->getSettTraits(ind.stage, ind.sex); #else - ndispersers += popns[i]->transfer(pLandscape, landIx); + else { + if (settletype.sexDep) { + if (settletype.stgDep) + settDD = pSpecies->getSpSettTraits(ind.stage, ind.sex); + else + settDD = pSpecies->getSpSettTraits(0, ind.sex); + } + else { + if (settletype.stgDep) + settDD = pSpecies->getSpSettTraits(ind.stage, 0); + else + settDD = pSpecies->getSpSettTraits(0, 0); + } + } #endif // RS_RCPP + settprob = settDD.s0 / + (1.0 + exp(-(popsize / localK - (double)settDD.beta) * (double)settDD.alpha)); + if (pRandom->Bernoulli(settprob)) { // settlement allowed + densdepOK = true; + settle.settleStatus = 2; } - return ndispersers; + else { // settlement procluded + settle.settleStatus = 1; + } + settle.pSettPatch = pPatch; + } + pInd->setSettPatch(settle); + } + else { + if (settle.settleStatus == 2) { // previously allowed to settle + densdepOK = true; + } + } + } + } + else { // no density-dependent settlement + densdepOK = true; + settle.settleStatus = 2; + settle.pSettPatch = pPatch; + pInd->setSettPatch(settle); + } + + if (mateOK && densdepOK) { // can recruit to patch + ind.status = 4; + nbStillDispersing--; + } + else { // does not recruit + if (trfr.usesMovtProc) { + ind.status = 1; // continue dispersing, unless ... + // ... maximum steps has been exceeded + pathSteps steps = pInd->getSteps(); + settleSteps settsteps = pSpecies->getSteps(ind.stage, ind.sex); + if (steps.year >= settsteps.maxStepsYr) { + ind.status = 3; // waits until next year + } + if (steps.total >= settsteps.maxSteps) { + ind.status = 6; // dies + } + } + else { // dispersal kernel + if (sett.wait) { + ind.status = 3; // wait until next dispersal event + } + else { + ind.status = 6; // (dies unless a neighbouring cell is suitable) + } + nbStillDispersing--; + } + } + } + + pInd->setStatus(ind.status); + } +#if RS_RCPP + // write each individuals current movement step and status to paths file + if (trfr.moveModel && sim.outPaths) { + if (nextseason >= sim.outStartPaths && nextseason % sim.outIntPaths == 0) { + pInd->outMovePath(nextseason); + } + } +#endif + + if (!trfr.usesMovtProc && sett.go2nbrLocn && (ind.status == 3 || ind.status == 6)) + { + // for kernel-based transfer only ... + // determine whether recruitment to a neighbouring cell is possible + + pCell = pInd->getCurrCell(); + newloc = pCell->getLocn(); + vector nbrlist; + for (int dx = -1; dx < 2; dx++) { + for (int dy = -1; dy < 2; dy++) { + if (dx != 0 || dy != 0) { //cell is not the current cell + nbrloc.x = newloc.x + dx; nbrloc.y = newloc.y + dy; + if (nbrloc.x >= 0 && nbrloc.x <= ppLand.maxX + && nbrloc.y >= 0 && nbrloc.y <= ppLand.maxY) { // within landscape + // add to list of potential neighbouring cells if suitable, etc. + pCell = pLandscape->findCell(nbrloc.x, nbrloc.y); + if (pCell != 0) { // not no-data area + pPatch = pCell->getPatch(); + if (pPatch != nullptr) { // not no-data area + patchnum = pPatch->getPatchNum(); + if (patchnum > 0 && pPatch != pInd->getNatalPatch()) + { // not the matrix or natal patch + if (pPatch->getK() > 0.0) + { // suitable + if (sett.findMate) { + if (matePresent(pSpecies, pCell, othersex)) nbrlist.push_back(pCell); + } + else + nbrlist.push_back(pCell); + } + } + } + } + } + } + } + } + int listsize = (int)nbrlist.size(); + if (listsize > 0) { // there is at least one suitable neighbouring cell + if (listsize == 1) { + pInd->moveto(nbrlist[0]); + } + else { // select at random from the list + int rrr = pRandom->IRandom(0, listsize - 1); + pInd->moveto(nbrlist[rrr]); + } + } + // else list empty - do nothing - individual retains its current location and status + } + + } // loop through inds + + } // loop through disperser map + + return nbStillDispersing; } //--------------------------------------------------------------------------- -// Remove emigrants from patch 0 (matrix) and transfer to sub-community +// Remove emigrants from the vectors map and transfer to sub-community // in which their destination co-ordinates fall -// This function is executed for the matrix patch only -void SubCommunity::completeDispersal(Landscape* pLandscape, bool connect) +void SubCommunity::completeDispersal(std::map>& inds_map, Landscape* pLandscape, bool connect) { - int popsize; - disperser settler; - Species* pSpecies; Population* pPop; Patch* pPrevPatch; Patch* pNewPatch; Cell* pPrevCell; SubCommunity* pSubComm; - int npops = (int)popns.size(); - for (int i = 0; i < npops; i++) { // all populations - pSpecies = popns[i]->getSpecies(); - popsize = popns[i]->getNInds(); - #pragma omp parallel for private(settler, pNewPatch, pPop, pSubComm, pPrevCell, pPrevPatch) - for (int j = 0; j < popsize; j++) { - bool settled; - settler = popns[i]->extractSettler(j); - settled = settler.yes; + for (auto & it : inds_map) { // all species + Species* const& pSpecies = it.first; + vector& inds = it.second; + for (Individual*& pInd : inds) { + indStats ind = pInd->getStats(); + bool settled = ind.status == 4 || ind.status == 5; if (settled) { - // settler - has already been removed from matrix population // find new patch - pNewPatch = settler.pCell->getPatch(); + pNewPatch = pInd->getCurrCell()->getPatch(); // find population within the patch (if there is one) { #ifdef _OPENMP @@ -399,24 +701,24 @@ void SubCommunity::completeDispersal(Landscape* pLandscape, bool connect) pPop = pSubComm->newPopn(pLandscape, pSpecies, pNewPatch, 0); } } - pPop->recruit(settler.pInd); + pPop->recruit(pInd); if (connect) { // increment connectivity totals int newpatch = pNewPatch->getSeqNum(); - pPrevCell = settler.pInd->getPrevCell(); + pPrevCell = pInd->getPrevCell(); pPrevPatch = pPrevCell->getPatch(); if (pPrevPatch != nullptr) { int prevpatch = pPrevPatch->getSeqNum(); pLandscape->incrConnectMatrix(prevpatch, newpatch); } } + pInd = nullptr; } else { // for group dispersal only } } - // remove pointers in the matrix popn to settlers - popns[i]->clean(); + // remove settled individuals + inds.erase(std::remove(inds.begin(), inds.end(), (Individual *)nullptr), inds.end()); } - } //--------------------------------------------------------------------------- @@ -578,7 +880,7 @@ void SubCommunity::outPop(Landscape* pLandscape, int rep, int yr, int gen) popns[i]->outPopulation(rep, yr, gen, eps, land.patchModel, writeEnv, gradK); } else { - if (popns[i]->totalPop() > 0) { + if (popns[i]->getNbInds() > 0) { popns[i]->outPopulation(rep, yr, gen, eps, land.patchModel, writeEnv, gradK); } } @@ -611,11 +913,11 @@ void SubCommunity::outIndividuals(Landscape* pLandscape, int rep, int yr, int ge // Population size of a specified stage -int SubCommunity::stagePop(int stage) { +int SubCommunity::getNbInds(int stage) const { int popsize = 0; int npops = (int)popns.size(); for (int i = 0; i < npops; i++) { // all populations - popsize += popns[i]->stagePop(stage); + popsize += popns[i]->getNbInds(stage); } return popsize; } @@ -769,7 +1071,7 @@ traitsums SubCommunity::outTraits(Landscape* pLandscape, int rep, int yr, int ge for (int iPop = 0; iPop < npops; iPop++) { // all populations - if (pPatch->getK() > 0.0 && popns[iPop]->getNInds() > 0) { + if (pPatch->getK() > 0.0 && popns[iPop]->getNbInds() > 0) { pSpecies = popns[iPop]->getSpecies(); demogrParams dem = pSpecies->getDemogrParams(); emigRules emig = pSpecies->getEmigRules(); diff --git a/SubCommunity.h b/SubCommunity.h index 8fd13a1..da2bd85 100644 --- a/SubCommunity.h +++ b/SubCommunity.h @@ -91,8 +91,13 @@ class SubCommunity { bool // TRUE for a patch-based model, FALSE for a cell-based model ); void emigration(void); + + // Remove emigrants from the matrix subcommunity and add to a map of vectors + void disperseMatrix( + std::map>& + ); // Remove emigrants from their natal patch and add to a map of vectors - void initiateDispersal( + void recruitDispersers( std::map>& ); // Add an individual into the local population of its species in the patch @@ -105,21 +110,38 @@ class SubCommunity { std::vector&, // vector of pointers to Individuals Species* // pointer to Species ); -#if RS_RCPP - int transfer( // Transfer through matrix - run for matrix SubCommunity only - Landscape*, // pointer to Landscape - short, // landscape change index - short // season / year + + // Determine whether there is a potential mate present in a patch which a potential + // settler has reached + static bool matePresent( + Species* pSpecies, + Cell*, // pointer to the Cell which the potential settler has reached + short // sex of the required mate (0 = female, 1 = male) ); -#else - int transfer( // Transfer through matrix - run for matrix SubCommunity only + + static int resolveTransfer( // Executed for a given vector of individuals + std::map>& dispersingInds, Landscape*, // pointer to Landscape short // landscape change index ); + +#if RS_RCPP + static int resolveSettlement( // Executed for a given vector of individuals + std::map>& dispersingInds, + Landscape* pLandscape + short // year + ); +#else + static int resolveSettlement( // Executed for a given vector of individuals + std::map>& dispersingInds, + Landscape* pLandscape + ); #endif // RS_RCPP - // Remove emigrants from patch 0 (matrix) and transfer to SubCommunity in which - // their destination co-ordinates fall (executed for the matrix patch only) - void completeDispersal( + + // Remove emigrants from the vectors map and transfer to SubCommunity in which + // their destination co-ordinates fall + static void completeDispersal( + std::map>&, // per-species map of vectors of individuals Landscape*, // pointer to Landscape bool // TRUE to increment connectivity totals ); @@ -197,9 +219,9 @@ class SubCommunity { int, // generation bool // true if called to summarise data at community level ); - int stagePop( // Population size of a specified stage + int getNbInds( // Population size of a specified stage int // stage - ); + ) const; private: int subCommNum; // SubCommunity number diff --git a/unit_tests/testIndividual.cpp b/unit_tests/testIndividual.cpp index 5a52001..2955609 100644 --- a/unit_tests/testIndividual.cpp +++ b/unit_tests/testIndividual.cpp @@ -1,13 +1,19 @@ -#ifndef NDEBUG +#ifdef UNIT_TESTS #include "../Individual.h" #include "../Population.h" void testTransferKernels() { - // Simple 5*5 cell-based landscape layout - int lsDim = 5; + + // Simple 3*3 cell-based landscape layout + const int lsDim = 3; landParams ls_params = createDefaultLandParams(lsDim); + // Set dispersal distances that are almost guaranteed + // to reach or fail to reach final cell + const float meanDistSuccess = static_cast(ls_params.dimX); // > 99% success + const float meanDistFailure = 0.1; // 0% success + Landscape ls; ls.setLandParams(ls_params, true); @@ -33,10 +39,7 @@ void testTransferKernels() { trfr.twinKern = trfr.distMort = false; sp.setTrfrRules(trfr); sp.setFullKernel(false); - // Transfer traits - trfrKernelParams kern; - kern.meanDist1 = static_cast(ls_params.dimX); // can reach destination cell reasonably often - sp.setSpKernTraits(0, 0, kern, ls_params.resol); + // Transfer mortality params trfrMortParams mort; mort.fixedMort = 0.0; @@ -49,9 +52,12 @@ void testTransferKernels() { // Set up patches ls.allocatePatches(&sp); ls.updateCarryingCapacity(&sp, 0, 0); - Patch* init_patch = (Patch*)init_cell->getPatch(); + Patch* init_patch = init_cell->getPatch(); - // Create and set up individual + // Default distances + trfrKernelParams kern; + kern.meanDist1 = meanDistSuccess; + sp.setSpKernTraits(0, 0, kern, ls_params.resol); Individual ind1(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); int isDispersing = ind1.moveKernel(&ls, &sp, false); @@ -62,8 +68,8 @@ void testTransferKernels() { assert(ind1.getStatus() == 2); // potential settler // If no cell within reasonable dispersal reach, individual does not move and dies - kern.meanDist1 = 1.0; - sp.setSpKernTraits(0, 0, kern, ls_params.resol); + kern.meanDist1 = meanDistFailure; + sp.overrideKernels(0, 0, kern); Individual ind2(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual isDispersing = ind2.moveKernel(&ls, &sp, false); curr_cell = ind2.getCurrCell(); @@ -73,15 +79,15 @@ void testTransferKernels() { // Twin kernels trfr.twinKern = true; sp.setTrfrRules(trfr); - kern.meanDist1 = 1.0; // very unlikely to reach suitable cell - kern.meanDist2 = 5.0; // easily reaches suitable cell... - kern.probKern1 = 1.0; // ... but never used - sp.setSpKernTraits(0, 0, kern, ls_params.resol); + kern.meanDist1 = meanDistFailure; + kern.meanDist2 = meanDistSuccess; + kern.probKern1 = 1.0; // 2nd kernel never used + sp.overrideKernels(0, 0, kern); Individual ind3(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind3.moveKernel(&ls, &sp, false); assert(ind3.getStatus() == 6); // dead, could not reach destination cell - kern.probKern1 = 0.0; // always use second kernel - sp.setSpKernTraits(0, 0, kern, ls_params.resol); + kern.probKern1 = 0.0; // always use 2nd kernel + sp.overrideKernels(0, 0, kern); Individual ind4(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind4.moveKernel(&ls, &sp, false); assert(ind4.getStatus() == 2); @@ -89,17 +95,19 @@ void testTransferKernels() { trfr.twinKern = false; sp.setTrfrRules(trfr); kern.probKern1 = 1.0; - sp.setSpKernTraits(0, 0, kern, ls_params.resol); + sp.overrideKernels(0, 0, kern); // Sex-dependent dispersal distances + // female very unlikely to reach suitable cell + // male easily reaches suitable cell trfr.sexDep = true; sp.setTrfrRules(trfr); trfrKernelParams kern_f = kern; - kern_f.meanDist1 = 1.0; // female very unlikely to reach suitable cell - sp.setSpKernTraits(0, 0, kern_f, ls_params.resol); + kern_f.meanDist1 = meanDistFailure; + sp.overrideKernels(0, 0, kern_f); trfrKernelParams kern_m = kern; - kern_m.meanDist1 = 5.0; // male easily reaches suitable cell - sp.setSpKernTraits(0, 1, kern_m, ls_params.resol); + kern_m.meanDist1 = meanDistSuccess; + sp.overrideKernels(0, 1, kern_m); Individual ind5(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // female as default isDispersing = ind5.moveKernel(&ls, &sp, false); @@ -117,11 +125,11 @@ void testTransferKernels() { trfr.stgDep = true; sp.setTrfrRules(trfr); trfrKernelParams kern_juv = kern; - kern_juv.meanDist1 = 1.0; // juveniles very unlikely to reach suitable cell - sp.setSpKernTraits(0, 0, kern_juv, ls_params.resol); + kern_juv.meanDist1 = meanDistFailure; // juveniles very unlikely to reach suitable cell + sp.overrideKernels(0, 0, kern_juv); trfrKernelParams kern_adult = kern; - kern_adult.meanDist1 = 5.0; // adults easily reach suitable cell - sp.setSpKernTraits(1, 0, kern_adult, ls_params.resol); + kern_adult.meanDist1 = meanDistSuccess; // adults easily reach suitable cell + sp.overrideKernels(1, 0, kern_adult); Individual ind7(&sp, init_cell, init_patch, 0, 0, 0, 0.0, false, 0); // juvenile isDispersing = ind7.moveKernel(&ls, &sp, false); @@ -142,7 +150,11 @@ void testTransferKernels() { -ooo- ----- */ + ls.resetLand(); + ls_params = createDefaultLandParams(5); + ls.setLandParams(ls_params, true); ls.setCellArray(); // reset cells + vector cells; // Set central cell and all adjacent for (int x = ls_params.minX + 1; x < ls_params.maxX; ++x) { @@ -154,10 +166,10 @@ void testTransferKernels() { for (auto c : cells) ls.addCellToLand(c); ls.allocatePatches(&sp); ls.updateCarryingCapacity(&sp, 0, 0); - init_cell = cells[4]; // that is, the center - init_patch = (Patch*)init_cell->getPatch(); + init_cell = cells[4]; // central cell + init_patch = init_cell->getPatch(); - kern.meanDist1 = 10; // overshoots *most* of the time... + kern.meanDist1 = 100; // overshoots *most* of the time... sp.setSpKernTraits(0, 0, kern, ls_params.resol); Individual ind9(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); // reset individual @@ -177,6 +189,7 @@ void testTransferKernels() { assert(curr_cell == 0); // out of the landscape // Dispersal-related mortality + // Fixed mortality mort.fixedMort = 1.0; // Individual *will* die after any step sp.setMortParams(mort); @@ -185,17 +198,20 @@ void testTransferKernels() { Individual ind11(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); isDispersing = ind11.moveKernel(&ls, &sp, false); assert(ind11.getStatus() == 7); + // Distance-dependent mortality trfr.distMort = true; sp.setTrfrRules(trfr); mort.mortAlpha = 1000.0; // very steep threshold - mort.mortBeta = 0.5; // very small distance + mort.mortBeta = 0.001; // very small distance sp.setMortParams(mort); kern.meanDist1 = 5; // very likely to go over threshold + absorbing_boundaries = true; sp.setSpKernTraits(0, 0, kern, ls_params.resol); Individual ind12(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); - isDispersing = ind12.moveKernel(&ls, &sp, false); + isDispersing = ind12.moveKernel(&ls, &sp, absorbing_boundaries); assert(ind12.getStatus() == 7); + mort.mortBeta = 30; // very large distance, unlikely to draw sp.setMortParams(mort); Individual ind13(&sp, init_cell, init_patch, 1, 0, 0, 0.0, false, 0); @@ -269,7 +285,7 @@ void testTransferCRW() { // Set up patches ls.allocatePatches(&sp); ls.updateCarryingCapacity(&sp, 0, 0); - Patch* init_patch = (Patch*)init_cell->getPatch(); + Patch* init_patch = init_cell->getPatch(); // Create and set up individual Individual ind0(&sp, init_cell, init_patch, 1, 0, 0, 0.0, true, 2); @@ -1387,4 +1403,4 @@ void testIndividual() { } -#endif //NDEBUG +#endif // UNIT_TESTS diff --git a/unit_tests/testNeutralStats.cpp b/unit_tests/testNeutralStats.cpp index 3332e9f..3bb396a 100644 --- a/unit_tests/testNeutralStats.cpp +++ b/unit_tests/testNeutralStats.cpp @@ -1,4 +1,4 @@ -#ifndef NDEBUG +#ifdef UNIT_TESTS #include "../Community.h" @@ -1059,4 +1059,4 @@ void testNeutralStats() { } } -#endif // NDEBUG +#endif // UNIT_TESTS diff --git a/unit_tests/testPopulation.cpp b/unit_tests/testPopulation.cpp index 19c5d20..c8dda07 100644 --- a/unit_tests/testPopulation.cpp +++ b/unit_tests/testPopulation.cpp @@ -1,4 +1,4 @@ -#ifndef NDEBUG +#ifdef UNIT_TESTS #include "../Individual.h" #include "../Population.h" @@ -63,7 +63,7 @@ void testPopulation() Population pop = Population(pSpecies, pPatch, initialNbInds, 1); pop.reproduction(localK, 1, 1, localScaling); // juveniles are checked for viability at birth pop.fledge(); // non-overlapping: adults are replaced with juveniles - survivingInds.push_back(pop.getNInds()); + survivingInds.push_back(pop.getNbInds()); } assert(survivingInds[0] > survivingInds[1] && survivingInds[1] > survivingInds[2]); @@ -82,7 +82,7 @@ void testPopulation() const int genomeSz = 1; const set genePositions = { 0 }; - // Wild-types nver emigrate, mutants always do + // Wild-types never emigrate, mutants always do const map initParams{ pair{GenParamType::MIN, 0}, pair{GenParamType::MAX, 0} @@ -136,11 +136,12 @@ void testPopulation() pop.reproduction(localK, 1, 1, localScaling); pop.fledge(); // replace initial pop with juveniles pop.emigration(localK); // select and flag emigrants - int popSize = pop.totalPop(); + int popSize = pop.getNbInds(); for (int i = 0; i < popSize; i++) { pop.extractDisperser(i); // rm emigrants from pop } - int nbEmigrating = popSize - pop.totalPop(); // diff is nb of emigrants + pop.clean(); + int nbEmigrating = popSize - pop.getNbInds(); // diff is nb of emigrants if (mutationRate == 0.0) assert(nbEmigrating == 0); emigratingInds.push_back(nbEmigrating); @@ -148,32 +149,29 @@ void testPopulation() assert(emigratingInds[0] < emigratingInds[1] && emigratingInds[1] < emigratingInds[2]); } - // In the absence of evolutionary forces, neutral gene - // frequencies roughly conform to Hardy-Weinberg principle, i.e.: - // 1 - Allele frequencies p and q remain constant through generations - // 2 - Genotype frequencies conform to fAA = p^2, fAB = 2pq, fBB = q^2 + // In the absence of selection, drift is solely responsible + // for changes in allele frequencies { - const float tolerance = 0.05; // high tolerance, drift does happen + const float tolerance = 0.02; + const float hetzTolerance = 0.05; float mutationRate = 0.0; const float localK = 10000.0; vector localScaling = {1.0}; const int initialNbInds = localK; - const float initFreqA = 0.20; - const float exptdFreqA = initFreqA; // Allelic freqs are constant under HW - const float exptdFreqB = 1 - exptdFreqA; - const float exptdFreqHeteroZ = 2 * exptdFreqA * exptdFreqB; // according to HW + const float initFreqA = 0.30; + const float exptdFreqHeteroZ = 2 * initFreqA * (1 - initFreqA); // according to HW const int nbGens = 50; - float obsFreqA = 0.0; - float obsFreqB = 0.0; - float obsFreqHeteroZ = 0.0; + float obsFreqA = initFreqA; + float obsFreqHeteroZ; + int nbInds = static_cast(localK); // Simple genetic layout // 1 locus with two alleles A and B - const bool isDiploid{ true }; // HW only applies to diploids + const bool isDiploid{ true }; const int genomeSz = 1; const set genePositions = { 0 }; - const float maxAlleleVal = 10; + const float maxAlleleVal = 1; unsigned char alleleA = char(0); unsigned char alleleB = char(1); auto genotypeAA = createTestNeutralGenotype(genomeSz, true, alleleA, alleleA); @@ -208,7 +206,8 @@ void testPopulation() pop.recruit(pInd); } - // Check allele frequencies conform to HW through generations + // Check allele frequencies conform to expectation through generations + float prevGenFreqA; for (int yr = 0; yr < nbGens; yr++) { pop.reproduction(localK, 1, 1, localScaling); pop.fledge(); // replace initial pop with juveniles @@ -216,18 +215,27 @@ void testPopulation() pop.survival1(); // develop to stage 1 (breeders) pop.shuffleInds(); - // Count allele and heterozygote frequencies + // Calculate expected allele frequency change from + // drift and previous generation frequencies + prevGenFreqA = obsFreqA; + float exptdChg = 2 * sqrt(prevGenFreqA * (1 - prevGenFreqA) / 2 * nbInds); + // ^ eq. 6.1 in Conservation and the Genomics of Populations, Allendorf et al. + // 95% CI for the allele frequency change + + // Check allele frequency change match equation pop.sampleIndsWithoutReplacement("all", { 1 }); pop.updatePopNeutralTables(); obsFreqA = pop.getAlleleFrequency(0, alleleA); - obsFreqB = pop.getAlleleFrequency(0, alleleB); - float nbHeteroZ = pop.getHeteroTally(0, alleleA); - int nbInds = pop.getNInds(); - obsFreqHeteroZ = nbHeteroZ / nbInds; - assert(abs(obsFreqA - exptdFreqA) < tolerance); - assert(abs(obsFreqB - exptdFreqB) < tolerance); - assert(abs(obsFreqHeteroZ - exptdFreqHeteroZ) < tolerance); - // Ideally one should do a statistical test against a random walk here + float freqChg = abs(prevGenFreqA - obsFreqA); + assert(abs(freqChg) < tolerance); + + // If population is very large, heterozygosity should be roughly constant, + // i.e. inbreeding is negligible + nbInds = pop.getNbInds(); + // couldn't find a source for exptd change in heterozygosity so + // we assume Hardy-Weinberg equilibrium + obsFreqHeteroZ = static_cast(pop.getHeteroTally(0, alleleA)) / nbInds; + assert(abs(obsFreqHeteroZ - exptdFreqHeteroZ) < hetzTolerance); } } @@ -235,9 +243,9 @@ void testPopulation() // If a lethal (s = 1) recessive (h = 0) allele starts at freq 0.6, // then (if no mutations) next gen should have 0.6^2 = 0.36 homozygotes dying at birth { - const float tolerance = 0.02; // high tolerance, still a lot of stochasticity + const float tolerance = 0.05; // high tolerance, still a lot of stochasticity - const float initFreqA = 0.6; + const float initFreqA = 0.23; const float sA = 1.0; // lethal const float hA = 0.0; // fully recessive const float sB = 0.0; // benign @@ -291,9 +299,9 @@ void testPopulation() pop.shuffleInds(); pop.reproduction(localK, 1, 1, localScaling); pop.fledge(); // replace initial pop with juveniles - double obsFreqUnviable = 1 - pop.getNInds() / localK; + double obsFreqUnviable = 1 - pop.getNbInds() / localK; assert(abs(obsFreqUnviable - expectedFreqAA) < tolerance); } } -#endif // NDEBUG +#endif // UNIT_TESTS From 9516aa10ba128c006ea384274536d808bfb7d6d3 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Mon, 17 Nov 2025 10:57:10 +0100 Subject: [PATCH 330/332] fixing minor bugs for RCPP flag --- SubCommunity.cpp | 4 ++-- SubCommunity.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 7a31bb2..d776406 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -525,7 +525,7 @@ int SubCommunity::resolveSettlement(std::map>& dis // make settlement decision if (settletype.indVar) settDD = pInd->getIndSettTraits(); #if RS_RCPP - else settDD = pSpecies->getSettTraits(ind.stage, ind.sex); + else settDD = pSpecies->getSpSettTraits(ind.stage, ind.sex); #else else { if (settletype.sexDep) { @@ -603,7 +603,7 @@ int SubCommunity::resolveSettlement(std::map>& dis } #if RS_RCPP // write each individuals current movement step and status to paths file - if (trfr.moveModel && sim.outPaths) { + if (trfr.usesMovtProc && sim.outPaths) { if (nextseason >= sim.outStartPaths && nextseason % sim.outIntPaths == 0) { pInd->outMovePath(nextseason); } diff --git a/SubCommunity.h b/SubCommunity.h index da2bd85..096782d 100644 --- a/SubCommunity.h +++ b/SubCommunity.h @@ -128,7 +128,7 @@ class SubCommunity { #if RS_RCPP static int resolveSettlement( // Executed for a given vector of individuals std::map>& dispersingInds, - Landscape* pLandscape + Landscape* pLandscape, short // year ); #else From 8c990d262f23c78af804c2cfce91164c45553d03 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Fri, 21 Nov 2025 09:31:27 +0100 Subject: [PATCH 331/332] bugfix for dynamic landscapes: demographic scale layers were not parsed --- Landscape.cpp | 9 ++++++++- Landscape.h | 7 ++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index 099bb2c..a61a1df 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -1360,7 +1360,7 @@ int Landscape::readLandChange(int filenum, Rcpp::NumericMatrix habfile, Rcpp::Nu #if RS_RCPP && !R_CMD // normal file input int Landscape::readLandChange(int filenum, bool costs, wifstream& hfile, wifstream& pfile, wifstream& cfile, int habnodata, int pchnodata, int costnodata, vector scalinglayers) #else -int Landscape::readLandChange(int filenum, bool costs) +int Landscape::readLandChange(int filenum, bool costs, vector scalinglayers) #endif { @@ -1718,6 +1718,13 @@ int Landscape::readLandChange(int filenum, bool costs) if (hfile.is_open()) { hfile.close(); hfile.clear(); } if (pfile.is_open()) { pfile.close(); pfile.clear(); } if (cfile.is_open()) { cfile.close(); cfile.clear(); } + + // add here the reading of demographic scaling layers + if(scalinglayers.size()>0){ + int retcode = readDemographicScaling(scalinglayers); + if (retcode < 0) return 54; //change number + } + return 0; } diff --git a/Landscape.h b/Landscape.h index 859fff4..da7213b 100644 --- a/Landscape.h +++ b/Landscape.h @@ -199,7 +199,7 @@ struct patchData { }; struct landChange { int chgNb, chgYear; - string pathHabFile, pathPatchFile, pathCostFile; + string pathHabFile, pathPatchFile, pathCostFile, pathSpatDemogFile; }; struct patchChange { int chgnum, x, y, oldpatch, newpatch; @@ -379,8 +379,9 @@ class Landscape{ #else // TODO: add spatial demography for batch version int readLandChange( - int, // change file number - bool // change SMS costs? + int, // change file numbers + bool, // change SMS costs? + vector // vector of demographic scaling layers ); #endif void createPatchChgMatrix(void); From c142584c73f1ea2ae8cf0204b3037fd1d2cb54d0 Mon Sep 17 00:00:00 2001 From: Jette Reeg Date: Thu, 27 Nov 2025 17:00:35 +0100 Subject: [PATCH 332/332] Minor Updates: RangeShifter version in CMakeLists.txt to 3.0.0 Parameter Output File --- CMakeLists.txt | 2 +- Model.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8341dc8..fa07836 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ if(NOT batchmode) # that is, RScore as a standalone cmake_minimum_required(VERSION 3.10) # set the project name and version - project(RScore VERSION 2.1.0) + project(RScore VERSION 3.0.0) # specify the C++ standard set(CMAKE_CXX_STANDARD 20) diff --git a/Model.cpp b/Model.cpp index ee4d214..1db8783 100644 --- a/Model.cpp +++ b/Model.cpp @@ -891,6 +891,7 @@ void OutParameters(Landscape* pLandscape) if (chg.pathCostFile != "none" && chg.pathCostFile != "NULL") { outPar << "Costs : " << chg.pathCostFile << endl; } + } } outPar << endl << "SPECIES DISTRIBUTION LOADED: \t"; @@ -1141,6 +1142,49 @@ void OutParameters(Landscape* pLandscape) else outPar << "not stage-dependent" << endl; } else outPar << "no" << endl; + + if (ppLand.spatialdemog){ + outPar << "SPATIALLY VARYING DEMOGRAPHY:\t in" << endl; + // file names for the spatial layers + + if(pSpecies->getFecSpatial()){ + outPar << "FECUNDITY" << endl; + outPar << "LAYERS:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + if (dem.repType == 2){ + outPar << "stage: " << i << "females: \t" << pSpecies->getFecLayer(i,0) << "\tmales: \t" << pSpecies->getFecLayer(i,1) << endl; + } else{ + outPar << "stage: " << i << pSpecies->getFecLayer(i,0) << endl; + } + } + } + + if(pSpecies->getDevSpatial()){ + outPar << "DEVELOPMENT" << endl; + outPar << "LAYERS:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + if (dem.repType == 2){ + outPar << "stage: " << i << "females: \t" << pSpecies->getDevLayer(i,0) << "\tmales: \t" << pSpecies->getDevLayer(i,1) << endl; + } else{ + outPar << "stage: " << i << pSpecies->getDevLayer(i,0) << endl; + } + } + } + if(pSpecies->getSurvSpatial()){ + outPar << "SURVIVAL" << endl; + outPar << "LAYERS:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + if (dem.repType == 2){ + outPar << "stage: " << i << "females: \t" << pSpecies->getSurvLayer(i,0) << "\tmales: \t" << pSpecies->getSurvLayer(i,1) << endl; + } else{ + outPar << "stage: " << i << pSpecies->getSurvLayer(i,0) << endl; + } + } + } + } + else { + outPar << "SPATIALLY VARYING DEMOGRAPHY:\t no" << endl; + } } // end of if (dem.stageStruct) else { // not stage-strutured outPar << "no" << endl;