Skip to content

Commit 167ee4a

Browse files
committed
add per-trait effect size and dominance to Substitution
1 parent dbd38a8 commit 167ee4a

8 files changed

Lines changed: 54 additions & 10 deletions

File tree

VERSIONS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ multitrait branch:
5959
make code completion work for the new dynamic properties on Species and Individual generated by initializeTrait()
6060
shift from a single global mutation block into per-species mutation blocks, and make a new C++ class, MutationBlock, to encapsulate this
6161
this is a forced move because we want the mutation block to have a separate buffer of per-trait state for mutations, and the number of traits varies among species
62+
add effect size and dominance coefficient properties to Mutation and Substitution (but not hooked up to the simulation yet)
6263

6364

6465
version 5.1 (Eidos version 4.1):

core/mutation.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ mutation_type_ptr_(p_mutation_type_ptr), position_(p_position), selection_coeff_
7070
Trait *trait = species.Traits()[trait_index];
7171
TraitType traitType = trait->Type();
7272

73-
traitInfoRec->mutation_effect_ = selection_coeff_;
73+
traitInfoRec->effect_size_ = selection_coeff_;
7474
traitInfoRec->dominance_coeff_ = dominance_coeff_;
7575

7676
if (traitType == TraitType::kMultiplicative)
@@ -168,7 +168,7 @@ mutation_type_ptr_(p_mutation_type_ptr), position_(p_position), selection_coeff_
168168
Trait *trait = species.Traits()[trait_index];
169169
TraitType traitType = trait->Type();
170170

171-
traitInfoRec->mutation_effect_ = selection_coeff_;
171+
traitInfoRec->effect_size_ = selection_coeff_;
172172
traitInfoRec->dominance_coeff_ = dominance_coeff_;
173173

174174
if (traitType == TraitType::kMultiplicative)

core/mutation.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ typedef int32_t MutationIndex;
5959
// with a number of records per mutation that is determined when it is constructed.
6060
typedef struct _MutationTraitInfo
6161
{
62-
slim_effect_t mutation_effect_; // selection coefficient (s) or additive effect (a)
62+
slim_effect_t effect_size_; // selection coefficient (s) or additive effect (a)
6363
slim_effect_t dominance_coeff_; // dominance coefficient (h), inherited from MutationType by default
6464

6565
// We cache values used in the fitness calculation code, for speed. These are the final fitness effects of this mutation

core/mutation_type.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ self_symbol_(EidosStringRegistry::GlobalStringIDForString(SLiMEidosScript::IDStr
8787
all_pure_neutral_DFE_ = ((p_dfe_type == DFEType::kFixed) && (p_dfe_parameters[0] == 0.0));
8888

8989
// set up DE entries for all traits
90-
int64_t trait_count = species_.TraitCount();
90+
int trait_count = species_.TraitCount();
9191

92-
for (int64_t trait_index = 0; trait_index < trait_count; trait_index++)
92+
for (int trait_index = 0; trait_index < trait_count; trait_index++)
9393
{
9494
EffectDistributionInfo ed_info;
9595

core/species.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ void Species::GetTraitIndicesFromEidosValue(std::vector<int64_t> &trait_indices,
609609
{
610610
EidosValueType traits_value_type = traits_value->Type();
611611
int traits_value_count = traits_value->Count();
612-
int64_t trait_count = TraitCount();
612+
int trait_count = TraitCount();
613613

614614
switch (traits_value_type)
615615
{
@@ -2825,7 +2825,7 @@ void Species::CreateAndPromulgateMutationBlock(void)
28252825
EIDOS_TERMINATION << "ERROR (Species::CreateAndPromulgateMutationBlock): (internal error) a mutation block has already been allocated." << EidosTerminate();
28262826

28272827
// first we make a new MutationBlock object for ourselves
2828-
mutation_block_ = new MutationBlock(*this, (int)TraitCount());
2828+
mutation_block_ = new MutationBlock(*this, TraitCount());
28292829

28302830
// then we promulgate it to the masses, so that they have it on hand (avoiding the non-local memory access
28312831
// of getting it from us), since it is referred to very actively in many places

core/species.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ class Species : public EidosDictionaryUnretained
448448

449449
// Trait configuration and access
450450
inline __attribute__((always_inline)) const std::vector<Trait *> &Traits(void) { return traits_; }
451-
inline __attribute__((always_inline)) int64_t TraitCount(void) { return (int64_t)traits_.size(); }
451+
inline __attribute__((always_inline)) int TraitCount(void) { return (int)traits_.size(); }
452452
Trait *TraitFromName(const std::string &p_name) const;
453453
inline __attribute__((always_inline)) Trait *TraitFromStringID(EidosGlobalStringID p_string_id) const
454454
{

core/substitution.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "eidos_call_signature.h"
2424
#include "eidos_property_signature.h"
2525
#include "species.h"
26+
#include "mutation_block.h"
2627

2728
#include <iostream>
2829
#include <algorithm>
@@ -40,11 +41,38 @@ Substitution::Substitution(Mutation &p_mutation, slim_tick_t p_fixation_tick) :
4041
{
4142
AddKeysAndValuesFrom(&p_mutation);
4243
// No call to ContentsChanged() here; we know we use Dictionary not DataFrame, and Mutation already vetted the dictionary
44+
45+
// Copy per-trait information over from the mutation object
46+
Species &species = mutation_type_ptr_->species_;
47+
MutationBlock *mutation_block = species.SpeciesMutationBlock();
48+
MutationIndex mut_index = mutation_block->IndexInBlock(&p_mutation);
49+
MutationTraitInfo *mut_trait_info = mutation_block->TraitInfoIndex(mut_index);
50+
int trait_count = species.TraitCount();
51+
52+
trait_info_ = (SubstitutionTraitInfo *)malloc(trait_count * sizeof(SubstitutionTraitInfo));
53+
54+
for (int trait_index = 0; trait_index < trait_count; trait_index++)
55+
{
56+
trait_info_[trait_index].effect_size_ = mut_trait_info[trait_index].effect_size_;
57+
trait_info_[trait_index].dominance_coeff_ = mut_trait_info[trait_index].dominance_coeff_;
58+
}
4359
}
4460

4561
Substitution::Substitution(slim_mutationid_t p_mutation_id, MutationType *p_mutation_type_ptr, slim_chromosome_index_t p_chromosome_index, slim_position_t p_position, slim_effect_t p_selection_coeff, slim_effect_t p_dominance_coeff, slim_objectid_t p_subpop_index, slim_tick_t p_tick, slim_tick_t p_fixation_tick, int8_t p_nucleotide) :
4662
mutation_type_ptr_(p_mutation_type_ptr), position_(p_position), selection_coeff_(static_cast<slim_effect_t>(p_selection_coeff)), dominance_coeff_(static_cast<slim_effect_t>(p_dominance_coeff)), subpop_index_(p_subpop_index), origin_tick_(p_tick), fixation_tick_(p_fixation_tick), chromosome_index_(p_chromosome_index), nucleotide_(p_nucleotide), mutation_id_(p_mutation_id), tag_value_(SLIM_TAG_UNSET_VALUE)
4763
{
64+
// FIXME MULTITRAIT: This code path is hit when loading substitutions from an output file, also needs to initialize the multitrait info; this is just a
65+
// placeholder. The file being read in ought to specify per-trait values, which hasn't happened yet, so there are lots of details to be worked out...
66+
Species &species = mutation_type_ptr_->species_;
67+
int trait_count = species.TraitCount();
68+
69+
trait_info_ = (SubstitutionTraitInfo *)malloc(trait_count * sizeof(SubstitutionTraitInfo));
70+
71+
for (int trait_index = 0; trait_index < trait_count; trait_index++)
72+
{
73+
trait_info_[trait_index].effect_size_ = 0.0;
74+
trait_info_[trait_index].dominance_coeff_ = 0.0;
75+
}
4876
}
4977

5078
void Substitution::PrintForSLiMOutput(std::ostream &p_out) const

core/substitution.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@
3737

3838
extern EidosClass *gSLiM_Substitution_Class;
3939

40+
// This structure contains all of the information about how a substitution influenced a particular trait: in particular, its
41+
// effect size and dominance coefficient. Each substitution keeps this information for each trait in its species, and since
42+
// the number of traits is determined at runtime, the size of this data -- the number of SubstitutionTraitInfo records kept
43+
// by each substitution -- is also determined at runtime. This is parallel to the MutationTraitInfo struct for mutations,
44+
// but keeps less information since it is not used during fitness evaluation. Also unlike Mutation, which keeps all this
45+
// in a block maintained by MutationBlock, we simply make a malloced block for each substitution; substitution is relatively
46+
// rare and substitutions don't go away once created, so there is no need to overcomplicate this design.
47+
typedef struct _SubstitutionTraitInfo
48+
{
49+
slim_effect_t effect_size_; // selection coefficient (s) or additive effect (a)
50+
slim_effect_t dominance_coeff_; // dominance coefficient (h), inherited from MutationType by default
51+
} SubstitutionTraitInfo;
4052

4153
class Substitution : public EidosDictionaryRetained
4254
{
@@ -59,14 +71,17 @@ class Substitution : public EidosDictionaryRetained
5971
const slim_mutationid_t mutation_id_; // a unique id for each mutation, used to track mutations
6072
slim_usertag_t tag_value_; // a user-defined tag value
6173

74+
// Per-trait information
75+
SubstitutionTraitInfo *trait_info_; // OWNED: a malloced block of per-trait information
76+
6277
Substitution(const Substitution&) = delete; // no copying
6378
Substitution& operator=(const Substitution&) = delete; // no copying
6479
Substitution(void) = delete; // no null construction
6580
Substitution(Mutation &p_mutation, slim_tick_t p_fixation_tick); // construct from the mutation that has fixed, and the tick in which it fixed
6681
Substitution(slim_mutationid_t p_mutation_id, MutationType *p_mutation_type_ptr, slim_chromosome_index_t p_chromosome_index, slim_position_t p_position, slim_effect_t p_selection_coeff, slim_effect_t p_dominance_coeff, slim_objectid_t p_subpop_index, slim_tick_t p_tick, slim_tick_t p_fixation_tick, int8_t p_nucleotide);
6782

68-
// a destructor is needed now that we inherit from EidosDictionaryRetained; we want it to be as minimal as possible, though, and inline
69-
inline virtual ~Substitution(void) override { }
83+
// a destructor is needed now that we inherit from EidosDictionaryRetained; we want it to be as minimal as possible, though
84+
inline virtual ~Substitution(void) override { free(trait_info_); trait_info_ = nullptr; }
7085

7186
void PrintForSLiMOutput(std::ostream &p_out) const;
7287
void PrintForSLiMOutput_Tag(std::ostream &p_out) const;

0 commit comments

Comments
 (0)