Skip to content

Commit 22b5ecf

Browse files
committed
add setPhenotypeForTrait() method to Individual
1 parent 5891bba commit 22b5ecf

8 files changed

Lines changed: 172 additions & 8 deletions

File tree

QtSLiM/help/SLiMHelpClasses.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,9 @@
500500
<p class="p5">+ (void)setOffsetForTrait([Nio&lt;Trait&gt; trait = NULL], [Nif offset = NULL])</p>
501501
<p class="p6">Sets the individual offset(s) for the trait(s) specified by <span class="s1">trait</span>.<span class="Apple-converted-space">  </span>The traits can be specified as <span class="s1">integer</span> indices of traits in the species, or directly as <span class="s1">Trait</span> objects; <span class="s1">NULL</span> represents all of the traits in the species, in the order in which they were defined.</p>
502502
<p class="p6">The parameter <span class="s1">offset</span> must follow one of four patterns.<span class="Apple-converted-space">  </span>In the first pattern, <span class="s1">offset</span> is <span class="s1">NULL</span>; this draws the offset for each of the specified traits from each trait’s individual-offset distribution (defined by each trait’s <span class="s1">individualOffsetMean</span> and <span class="s1">individualOffsetSD</span> properties) in each target individual.<span class="Apple-converted-space">  </span>(Note that individual offsets are automatically drawn from these distributions when an individual is created; this re-draws new offset values.)<span class="Apple-converted-space">  </span>In the second pattern, <span class="s1">offset</span> is a singleton value; this sets the given offset for each of the specified traits in each target individual.<span class="Apple-converted-space">  </span>In the third pattern, <span class="s1">offset</span> is of length equal to the number of specified traits; this sets the offset for each of the specified traits to the corresponding offset value in each target individual.<span class="Apple-converted-space">  </span>In the fourth pattern, <span class="s1">offset</span> is of length equal to the number of specified traits times the number of target individuals; this uses <span class="s1">offset</span> to provide a different offset value for each trait in each individual, using consecutive values from <span class="s1">offset</span> to set the offset for each of the specified traits in one individual before moving to the next individual.</p>
503+
<p class="p5">+ (void)setPhenotypeForTrait(Nio&lt;Trait&gt; trait, numeric phenotype)</p>
504+
<p class="p6">Sets the individual phenotype(s) for the trait(s) specified by <span class="s1">trait</span>.<span class="Apple-converted-space">  </span>The traits can be specified as <span class="s1">integer</span> indices of traits in the species, or directly as <span class="s1">Trait</span> objects; <span class="s1">NULL</span> represents all of the traits in the species, in the order in which they were defined.</p>
505+
<p class="p6">The parameter <span class="s1">phenotype</span> must follow one of three patterns.<span class="Apple-converted-space">  </span>In the first pattern, <span class="s1">phenotype</span> is a singleton value; this sets the given phenotype for each of the specified traits in each target individual.<span class="Apple-converted-space">  </span>In the second pattern, <span class="s1">phenotype</span> is of length equal to the number of specified traits; this sets the phenotype for each of the specified traits to the corresponding phenotype in each target individual.<span class="Apple-converted-space">  </span>In the third pattern, <span class="s1">phenotype</span> is of length equal to the number of specified traits times the number of target individuals; this uses <span class="s1">phenotype</span> to provide a different phenotype for each trait in each individual, using consecutive values from <span class="s1">phenotype</span> to set the phenotype for each of the specified traits in one individual before moving to the next individual.</p>
503506
<p class="p5"><span class="s3">+ (void)setSpatialPosition(float position)</span></p>
504507
<p class="p6"><span class="s3">Sets the spatial position of the individual (as accessed through the </span><span class="s4">spatialPosition</span><span class="s3"> property).<span class="Apple-converted-space">  </span>The length of </span><span class="s4">position</span><span class="s3"> (the number of coordinates in the spatial position of an individual) depends upon the spatial dimensionality declared with </span><span class="s4">initializeSLiMOptions()</span><span class="s3">.<span class="Apple-converted-space">  </span>If the spatial dimensionality is zero (as it is by default), it is an error to call this method.<span class="Apple-converted-space">  </span>The elements of </span><span class="s4">position</span><span class="s3"> are set into the values of the </span><span class="s4">x</span><span class="s3">, </span><span class="s4">y</span><span class="s3">, and </span><span class="s4">z</span><span class="s3"> properties (if those properties are encompassed by the spatial dimensionality of the simulation).<span class="Apple-converted-space">  </span>In other words, if the declared dimensionality is </span><span class="s4">"xy"</span><span class="s3">, calling </span><span class="s4">individual.setSpatialPosition(c(1.0, 0.5))</span><span class="s3"> property is equivalent to </span><span class="s4">individual.x = 1.0; individual.y = 0.5</span><span class="s3">; </span><span class="s4">individual.z</span><span class="s3"> is not set (even if a third value is supplied in </span><span class="s4">position</span><span class="s3">) since it is not encompassed by the simulation’s dimensionality in this example.</span></p>
505508
<p class="p6"><span class="s3">Note that this is an Eidos class method, somewhat unusually, which allows it to work in a special way when called on a vector of individuals.<span class="Apple-converted-space">  </span>When the target vector of individuals is non-singleton, this method can do one of two things.<span class="Apple-converted-space">  </span>If </span><span class="s4">position</span><span class="s3"> contains just a single point (i.e., is equal in length to the spatial dimensionality of the model), the spatial position of all of the target individuals will be set to the given point.<span class="Apple-converted-space">  </span>Alternatively, if </span><span class="s4">position</span><span class="s3"> contains one point per target individual (i.e., is equal in length to the number of individuals multiplied by the spatial dimensionality of the model), the spatial position of each target individual will be set to the corresponding point from </span><span class="s4">position</span><span class="s3"> (where the point data is concatenated, not interleaved, just as it would be returned by accessing the </span><span class="s4">spatialPosition</span><span class="s3"> property on the vector of target individuals).<span class="Apple-converted-space">  </span>Calling this method with a </span><span class="s4">position</span><span class="s3"> vector of any other length is an error.</span></p>

SLiMgui/SLiMHelpClasses.rtf

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4222,6 +4222,33 @@ The parameter
42224222
\f4\fs20 to set the offset for each of the specified traits in one individual before moving to the next individual.\
42234223
\pard\pardeftab720\li720\fi-446\ri720\sb180\sa60\partightenfactor0
42244224

4225+
\f3\fs18 \cf2 +\'a0(void)setPhenotypeForTrait(Nio<Trait>\'a0trait, numeric\'a0phenotype)\
4226+
\pard\pardeftab397\li547\ri720\sb60\sa60\partightenfactor0
4227+
4228+
\f4\fs20 \cf2 Sets the individual phenotype(s) for the trait(s) specified by
4229+
\f3\fs18 trait
4230+
\f4\fs20 . The traits can be specified as
4231+
\f3\fs18 integer
4232+
\f4\fs20 indices of traits in the species, or directly as
4233+
\f3\fs18 Trait
4234+
\f4\fs20 objects;
4235+
\f3\fs18 NULL
4236+
\f4\fs20 represents all of the traits in the species, in the order in which they were defined.\
4237+
The parameter
4238+
\f3\fs18 phenotype
4239+
\f4\fs20 must follow one of three patterns. In the first pattern,
4240+
\f3\fs18 phenotype
4241+
\f4\fs20 is a singleton value; this sets the given phenotype for each of the specified traits in each target individual. In the second pattern,
4242+
\f3\fs18 phenotype
4243+
\f4\fs20 is of length equal to the number of specified traits; this sets the phenotype for each of the specified traits to the corresponding phenotype in each target individual. In the third pattern,
4244+
\f3\fs18 phenotype
4245+
\f4\fs20 is of length equal to the number of specified traits times the number of target individuals; this uses
4246+
\f3\fs18 phenotype
4247+
\f4\fs20 to provide a different phenotype for each trait in each individual, using consecutive values from
4248+
\f3\fs18 phenotype
4249+
\f4\fs20 to set the phenotype for each of the specified traits in one individual before moving to the next individual.\
4250+
\pard\pardeftab720\li720\fi-446\ri720\sb180\sa60\partightenfactor0
4251+
42254252
\f3\fs18 \cf2 \expnd0\expndtw0\kerning0
42264253
+\'a0(void)setSpatialPosition(float\'a0position)\
42274254
\pard\pardeftab720\li547\ri720\sb60\sa60\partightenfactor0

VERSIONS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ multitrait branch:
6767
rename the selectionCoeff property to effect, for both Mutation and Substitution; it changes from float$ to float, and now returns all trait effects; and SLiMgui autofixes this change
6868
remove the old C++ selection_coeff_ and dominance_coeff_ ivars in Mutation and Substitution, and begin the transition over to the new MutationTraitInfo struct
6969
add Individual method -(float)phenotypeForTrait([Nio<Trait> traits = NULL]) to get trait values
70+
add Individual method +(void)setPhenotypeForTrait([Nio<Trait> trait = NULL], [Nif phenotype = NULL]) to set trait values
7071

7172

7273
version 5.1 (Eidos version 4.1):

core/individual.cpp

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4246,6 +4246,7 @@ const std::vector<EidosMethodSignature_CSP> *Individual_Class::Methods(void) con
42464246
methods->emplace_back((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature(gStr_offsetForTrait, kEidosValueMaskFloat))->AddIntObject_ON("trait", gSLiM_Trait_Class, gStaticEidosValueNULL));
42474247
methods->emplace_back((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature(gStr_phenotypeForTrait, kEidosValueMaskFloat))->AddIntObject_ON("trait", gSLiM_Trait_Class, gStaticEidosValueNULL));
42484248
methods->emplace_back((EidosClassMethodSignature *)(new EidosClassMethodSignature(gStr_setOffsetForTrait, kEidosValueMaskVOID))->AddIntObject_ON("trait", gSLiM_Trait_Class, gStaticEidosValueNULL)->AddNumeric_ON("offset", gStaticEidosValueNULL));
4249+
methods->emplace_back((EidosClassMethodSignature *)(new EidosClassMethodSignature(gStr_setPhenotypeForTrait, kEidosValueMaskVOID))->AddIntObject_N("trait", gSLiM_Trait_Class)->AddNumeric("phenotype"));
42494250
methods->emplace_back((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature(gStr_sharedParentCount, kEidosValueMaskInt))->AddObject("individuals", gSLiM_Individual_Class));
42504251
methods->emplace_back(((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature(gStr_sumOfMutationsOfType, kEidosValueMaskFloat | kEidosValueMaskSingleton))->AddIntObject_S("mutType", gSLiM_MutationType_Class))->DeclareAcceleratedImp(Individual::ExecuteMethod_Accelerated_sumOfMutationsOfType));
42514252
methods->emplace_back((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature(gStr_uniqueMutationsOfType, kEidosValueMaskObject, gSLiM_Mutation_Class))->AddIntObject_S("mutType", gSLiM_MutationType_Class)->MarkDeprecated());
@@ -4267,6 +4268,7 @@ EidosValue_SP Individual_Class::ExecuteClassMethod(EidosGlobalStringID p_method_
42674268
switch (p_method_id)
42684269
{
42694270
case gID_setOffsetForTrait: return ExecuteMethod_setOffsetForTrait(p_method_id, p_target, p_arguments, p_interpreter);
4271+
case gID_setPhenotypeForTrait: return ExecuteMethod_setPhenotypeForTrait(p_method_id, p_target, p_arguments, p_interpreter);
42704272
case gID_outputIndividuals: return ExecuteMethod_outputIndividuals(p_method_id, p_target, p_arguments, p_interpreter);
42714273
case gID_outputIndividualsToVCF: return ExecuteMethod_outputIndividualsToVCF(p_method_id, p_target, p_arguments, p_interpreter);
42724274
case gID_readIndividualsFromVCF: return ExecuteMethod_readIndividualsFromVCF(p_method_id, p_target, p_arguments, p_interpreter);
@@ -4426,6 +4428,133 @@ EidosValue_SP Individual_Class::ExecuteMethod_setOffsetForTrait(EidosGlobalStrin
44264428
return gStaticEidosValueVOID;
44274429
}
44284430

4431+
// ********************* + (void)setPhenotypeForTrait([Nio<Trait> trait = NULL], [Nif phenotype = NULL])
4432+
//
4433+
EidosValue_SP Individual_Class::ExecuteMethod_setPhenotypeForTrait(EidosGlobalStringID p_method_id, EidosValue_Object *p_target, const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter) const
4434+
{
4435+
#pragma unused (p_method_id, p_interpreter)
4436+
EidosValue *trait_value = p_arguments[0].get();
4437+
EidosValue *phenotype_value = p_arguments[1].get();
4438+
4439+
int individuals_count = p_target->Count();
4440+
int phenotype_count = phenotype_value->Count();
4441+
4442+
if (individuals_count == 0)
4443+
return gStaticEidosValueVOID;
4444+
4445+
Individual **individuals_buffer = (Individual **)p_target->ObjectData();
4446+
4447+
// SPECIES CONSISTENCY CHECK
4448+
Species *species = Community::SpeciesForIndividuals(p_target);
4449+
4450+
if (!species)
4451+
EIDOS_TERMINATION << "ERROR (Individual_Class::ExecuteMethod_setPhenotypeForTrait): setPhenotypeForTrait() requires that all individuals belong to the same species." << EidosTerminate();
4452+
4453+
// get the trait indices, with bounds-checking
4454+
std::vector<int64_t> trait_indices;
4455+
species->GetTraitIndicesFromEidosValue(trait_indices, trait_value, "setPhenotypeForTrait");
4456+
int trait_count = (int)trait_indices.size();
4457+
4458+
if (phenotype_count == 1)
4459+
{
4460+
// pattern 1: setting a single phenotype value across one or more traits in one or more individuals
4461+
slim_effect_t phenotype = static_cast<slim_effect_t>(phenotype_value->NumericAtIndex_NOCAST(0, nullptr));
4462+
4463+
if (trait_count == 1)
4464+
{
4465+
// optimized case for one trait
4466+
int64_t trait_index = trait_indices[0];
4467+
4468+
for (int individual_index = 0; individual_index < individuals_count; ++individual_index)
4469+
individuals_buffer[individual_index]->trait_info_[trait_index].phenotype_ = phenotype;
4470+
}
4471+
else
4472+
{
4473+
for (int individual_index = 0; individual_index < individuals_count; ++individual_index)
4474+
{
4475+
Individual *ind = individuals_buffer[individual_index];
4476+
4477+
for (int64_t trait_index : trait_indices)
4478+
ind->trait_info_[trait_index].phenotype_ = phenotype;
4479+
}
4480+
}
4481+
}
4482+
else if (phenotype_count == trait_count)
4483+
{
4484+
// pattern 2: setting one phenotype value per trait, in one or more individuals
4485+
int phenotype_index = 0;
4486+
4487+
for (int64_t trait_index : trait_indices)
4488+
{
4489+
slim_effect_t phenotype = static_cast<slim_effect_t>(phenotype_value->NumericAtIndex_NOCAST(phenotype_index++, nullptr));
4490+
4491+
for (int individual_index = 0; individual_index < individuals_count; ++individual_index)
4492+
{
4493+
Individual *ind = individuals_buffer[individual_index];
4494+
4495+
ind->trait_info_[trait_index].phenotype_ = phenotype;
4496+
}
4497+
}
4498+
}
4499+
else if (phenotype_count == trait_count * individuals_count)
4500+
{
4501+
// pattern 3: setting different phenotype values for each trait in each individual; in this case,
4502+
// all phenotypes for the specified traits in a given individual are given consecutively
4503+
if (phenotype_value->Type() == EidosValueType::kValueInt)
4504+
{
4505+
// integer phenotype values
4506+
const int64_t *phenotypes_int = phenotype_value->IntData();
4507+
4508+
if (trait_count == 1)
4509+
{
4510+
// optimized case for one trait
4511+
int64_t trait_index = trait_indices[0];
4512+
4513+
for (int individual_index = 0; individual_index < individuals_count; ++individual_index)
4514+
individuals_buffer[individual_index]->trait_info_[trait_index].phenotype_ = static_cast<slim_effect_t>(*(phenotypes_int++));
4515+
}
4516+
else
4517+
{
4518+
for (int individual_index = 0; individual_index < individuals_count; ++individual_index)
4519+
{
4520+
Individual *ind = individuals_buffer[individual_index];
4521+
4522+
for (int64_t trait_index : trait_indices)
4523+
ind->trait_info_[trait_index].phenotype_ = static_cast<slim_effect_t>(*(phenotypes_int++));
4524+
}
4525+
}
4526+
}
4527+
else
4528+
{
4529+
// float phenotype values
4530+
const double *phenotypes_float = phenotype_value->FloatData();
4531+
4532+
if (trait_count == 1)
4533+
{
4534+
// optimized case for one trait
4535+
int64_t trait_index = trait_indices[0];
4536+
4537+
for (int individual_index = 0; individual_index < individuals_count; ++individual_index)
4538+
individuals_buffer[individual_index]->trait_info_[trait_index].phenotype_ = static_cast<slim_effect_t>(*(phenotypes_float++));
4539+
}
4540+
else
4541+
{
4542+
for (int individual_index = 0; individual_index < individuals_count; ++individual_index)
4543+
{
4544+
Individual *ind = individuals_buffer[individual_index];
4545+
4546+
for (int64_t trait_index : trait_indices)
4547+
ind->trait_info_[trait_index].phenotype_ = static_cast<slim_effect_t>(*(phenotypes_float++));
4548+
}
4549+
}
4550+
}
4551+
}
4552+
else
4553+
EIDOS_TERMINATION << "ERROR (Individual_Class::ExecuteMethod_setPhenotypeForTrait): setPhenotypeForTrait() requires that phenotype be (a) singleton, providing one phenotype for all traits, (b) equal in length to the number of traits in the species, providing one phenotype per trait, or (c) equal in length to the number of traits times the number of target individuals, providing one phenotype per trait per individual." << EidosTerminate();
4554+
4555+
return gStaticEidosValueVOID;
4556+
}
4557+
44294558
// ********************* + (void)outputIndividuals([Ns$ filePath = NULL], [logical$ append=F], [Niso<Chromosome>$ chromosome = NULL], [logical$ spatialPositions = T], [logical$ ages = T], [logical$ ancestralNucleotides = F], [logical$ pedigreeIDs = F], [logical$ objectTags = F])
44304559
//
44314560
EidosValue_SP Individual_Class::ExecuteMethod_outputIndividuals(EidosGlobalStringID p_method_id, EidosValue_Object *p_target, const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter) const

core/individual.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ class Individual_Class : public EidosDictionaryUnretained_Class
423423

424424
virtual EidosValue_SP ExecuteClassMethod(EidosGlobalStringID p_method_id, EidosValue_Object *p_target, const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter) const override;
425425
EidosValue_SP ExecuteMethod_setOffsetForTrait(EidosGlobalStringID p_method_id, EidosValue_Object *p_target, const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter) const;
426+
EidosValue_SP ExecuteMethod_setPhenotypeForTrait(EidosGlobalStringID p_method_id, EidosValue_Object *p_target, const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter) const;
426427
EidosValue_SP ExecuteMethod_outputIndividuals(EidosGlobalStringID p_method_id, EidosValue_Object *p_target, const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter) const;
427428
EidosValue_SP ExecuteMethod_outputIndividualsToVCF(EidosGlobalStringID p_method_id, EidosValue_Object *p_target, const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter) const;
428429
EidosValue_SP ExecuteMethod_readIndividualsFromVCF(EidosGlobalStringID p_method_id, EidosValue_Object *p_target, const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter) const;

core/slim_globals.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,6 +1360,7 @@ const std::string &gStr_haplosomesForChromosomes = EidosRegisteredString("haplos
13601360
const std::string &gStr_offsetForTrait = EidosRegisteredString("offsetForTrait", gID_offsetForTrait);
13611361
const std::string &gStr_phenotypeForTrait = EidosRegisteredString("phenotypeForTrait", gID_phenotypeForTrait);
13621362
const std::string &gStr_setOffsetForTrait = EidosRegisteredString("setOffsetForTrait", gID_setOffsetForTrait);
1363+
const std::string &gStr_setPhenotypeForTrait = EidosRegisteredString("setPhenotypeForTrait", gID_setPhenotypeForTrait);
13631364
const std::string &gStr_relatedness = EidosRegisteredString("relatedness", gID_relatedness);
13641365
const std::string &gStr_sharedParentCount = EidosRegisteredString("sharedParentCount", gID_sharedParentCount);
13651366
const std::string &gStr_mutationsOfType = EidosRegisteredString("mutationsOfType", gID_mutationsOfType);

0 commit comments

Comments
 (0)