From 89eaf9de52984349c89011e64e54b7f6f3c2da3e Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Wed, 3 Jul 2024 17:30:46 +0100 Subject: [PATCH] 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