Skip to content

Commit df9dd54

Browse files
committed
a bit of cleanup for loggedData()
1 parent f42fb49 commit df9dd54

File tree

5 files changed

+60
-23
lines changed

5 files changed

+60
-23
lines changed

QtSLiM/help/SLiMHelpClasses.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -800,9 +800,9 @@
800800
<p class="p6">Returns the parameters that configure the distribution of effects for the specified trait or traits.<span class="Apple-converted-space">  </span>The traits can be specified as <span class="s1">integer</span> indices or <span class="s1">string</span> names 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.<span class="Apple-converted-space">  </span>The distribution parameters will be of type <span class="s1">string</span> for DES type <span class="s1">"s"</span>, and type <span class="s1">float</span> for all other DES types.</p>
801801
<p class="p5">– (string)effectDistributionTypeForTrait([Niso&lt;Trait&gt; trait = NULL])</p>
802802
<p class="p6">Returns the type of distribution of effects for the specified trait or traits.<span class="Apple-converted-space">  </span>The traits can be specified as <span class="s1">integer</span> indices or <span class="s1">string</span> names 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.<span class="Apple-converted-space">  </span>The distribution type will be one of <span class="s1">"f"</span>, <span class="s1">"g"</span>, <span class="s1">"e"</span>, <span class="s1">"n"</span>, <span class="s1">"p"</span>, <span class="s1">"w"</span>, or <span class="s1">"s"</span> , as discussed in the <span class="s1">MutationType</span> class documentation.</p>
803-
<p class="p5">– (fo&lt;DataFrame&gt;)loggedData(string$ kind, [logical$ id = F], [logical$ mutationTypeID = F], [logical$ chromosomeID = F], [logical$ position = F], [logical$ nucleotideValue = F], [logical$ originTick = F], [logical$ subpopID = F], [logical$ tag = F], [Niso&lt;Trait&gt; trait = NULL], [logical$ effect = F], [logical$ dominance = F], [logical$ hemizygousDominance = F])</p>
804-
<p class="p6">Returns mutation data produced by the mutation type’s logging facility, as configured by <span class="s1">logMutationData()</span>.<span class="Apple-converted-space">  </span>The data returned can be in the form of means across all logged mutations (for <span class="s1">kind="mean"</span>), standard deviations across all logged mutations (for <span class="s1">kind="sd"</span>), or separate values for each mutation (for <span class="s1">kind="values"</span>).<span class="Apple-converted-space">  </span>If logging only of means was enabled (with the <span class="s1">meanOnly=T</span> option to <span class="s1">logMutationData()</span>), only <span class="s1">kind="mean"</span> is allowed, since separate values for each mutation are then not logged.</p>
805-
<p class="p6">The remaining flags control which columns of data should be returned; see <span class="s1">logMutationData()</span> for a summary of the mutation properties they refer to.<span class="Apple-converted-space">  </span>If only one data column is specified by the flags, a vector of values (or a mean or standard deviation) will be returned for that one specified data column.<span class="Apple-converted-space">  </span>If more than one flag is set to <span class="s1">T</span>, a <span class="s1">DataFrame</span> object will be returned with named columns of values (or means, or standard deviations) for each specified data column.<span class="Apple-converted-space">  </span>The <span class="s1">trait</span> property specifies which traits values should be returned for, with respect to the <span class="s1">effect</span>, <span class="s1">dominance</span>, and <span class="s1">hemizygousDominance</span> flags; see <span class="s1">logMutationData()</span> for further description.<span class="Apple-converted-space">  </span>If <i>all</i> of these flags are <span class="s1">F</span> (the default), that is taken to mean that <i>all</i> logged data should be returned; in that case, a vector will be returned if only one column of data was logged, otherwise a <span class="s1">DataFrame</span> object will be returned, the same as when flags are specified explicitly.<span class="Apple-converted-space">  </span>Flags set to <span class="s1">T</span> for data columns that were not actually logged will simply be ignored; similarly, traits specified by <span class="s1">trait</span> that were not actually logged will simply be ignored.<span class="Apple-converted-space">  </span>See the Eidos manual for the <span class="s1">DataFrame</span> class documentation.</p>
803+
<p class="p5">– (ifo&lt;DataFrame&gt;)loggedData(string$ kind, [logical$ id = F], [logical$ mutationTypeID = F], [logical$ chromosomeID = F], [logical$ position = F], [logical$ nucleotideValue = F], [logical$ originTick = F], [logical$ subpopID = F], [logical$ tag = F], [Niso&lt;Trait&gt; trait = NULL], [logical$ effect = F], [logical$ dominance = F], [logical$ hemizygousDominance = F])</p>
804+
<p class="p6">Returns mutation data produced by the mutation type’s logging facility, as configured by <span class="s1">logMutationData()</span>.<span class="Apple-converted-space">  </span>The data returned can be in the form of means across all logged mutations (for <span class="s1">kind="mean"</span>), standard deviations across all logged mutations (for <span class="s1">kind="sd"</span>), or separate values for each mutation (for <span class="s1">kind="values"</span>); <span class="s1">kind="count"</span> is also allowed, and simply returns a singleton <span class="s1">integer</span> providing the number of entries (i.e., the number of mutations) that have been recorded.<span class="Apple-converted-space">  </span>If logging only of means was enabled (with the <span class="s1">meanOnly=T</span> option to <span class="s1">logMutationData()</span>), only <span class="s1">kind="mean"</span> and <span class="s1">kind="count"</span> are allowed, since separate values for each mutation are then not logged.</p>
805+
<p class="p6">The remaining flags control which columns of data should be returned (for <span class="s1">kind</span> options other than <span class="s1">"count"</span>); see <span class="s1">logMutationData()</span> for a summary of the mutation properties they refer to.<span class="Apple-converted-space">  </span>If only one data column is specified by the flags, a vector of values (or a mean or standard deviation) will be returned for that one specified data column.<span class="Apple-converted-space">  </span>If more than one flag is set to <span class="s1">T</span>, a <span class="s1">DataFrame</span> object will be returned with named columns of values (or means, or standard deviations) for each specified data column.<span class="Apple-converted-space">  </span>The <span class="s1">trait</span> property specifies which traits values should be returned for, with respect to the <span class="s1">effect</span>, <span class="s1">dominance</span>, and <span class="s1">hemizygousDominance</span> flags; see <span class="s1">logMutationData()</span> for further description.<span class="Apple-converted-space">  </span>Flags set to <span class="s1">T</span> for data columns that were not actually logged will simply be ignored; similarly, traits specified by <span class="s1">trait</span> that were not actually logged will simply be ignored.<span class="Apple-converted-space">  </span>See the Eidos manual for the <span class="s1">DataFrame</span> class documentation.</p>
806806
<p class="p5">– (void)logMutationData(logical$ enable, [logical$ autogeneratedOnly = T], [logical$ meanOnly = F], [logical$ id = F], [logical$ mutationTypeID = F], [logical$ chromosomeID = F], [logical$ position = F], [logical$ nucleotideValue = F], [logical$ originTick = F], [logical$ subpopID = F], [logical$ tag = F], [Niso&lt;Trait&gt; trait = NULL], [logical$ effect = F], [logical$ dominance = F], [logical$ hemizygousDominance = F])</p>
807807
<p class="p6">Starts or ends logging of data about new mutations belonging to the target mutation type.<span class="Apple-converted-space">  </span>If <span class="s1">autogeneratedOnly</span> is <span class="s1">T</span> (the default), only new mutations generated automatically by SLiM will be logged (including mutations that are substituted in for an auto-generated mutation using a <span class="s1">mutation()</span> callback; that is still considered part of the auto-generation process).<span class="Apple-converted-space">  </span>If <span class="s1">autogeneratedOnly</span> is <span class="s1">F</span>, mutations generated in script, such as with <span class="s1">addNewMutation()</span>, <span class="s1">addNewDrawnMutation()</span>, and reading from files such as VCF, MS, or <span class="s1">.trees</span>, will also be logged.<span class="Apple-converted-space">  </span>The logged information can be obtained later with the <span class="s1">loggedData()</span> method.<span class="Apple-converted-space">  </span>Once logging has been started with <span class="s1">enable=T</span> it cannot be modified, only stopped with <span class="s1">enable=F</span>; and if logging is subsequently resumed with <span class="s1">enable=T</span>, any previously logged data will be discarded.<span class="Apple-converted-space">  </span>(This can be useful if you wish to limit the size of the in-memory data while continuing to log new data: periodically write the accumulated data to a file and then disable and re-enable logging to discard the old data.)</p>
808808
<p class="p6">If <span class="s1">meanOnly</span> is <span class="s1">F</span> (the default), values for each new mutation will be kept separately.<span class="Apple-converted-space">  </span>Beware: the memory usage entailed by this option can be extremely large!<span class="Apple-converted-space">  </span>Alternatively, if <span class="s1">meanOnly</span> is <span class="s1">T</span>, only a running sum, used to compute a mean, will be kept for each type of data; the memory usage for this option will be small and constant, but of course a mean is more useful for some columns of data than others.<span class="Apple-converted-space">  </span>If per-mutation data is desired for any one column, use <span class="s1">meanOnly=F</span>; this option cannot be controlled independently for the various columns of data being logged.</p>

SLiMgui/SLiMHelpClasses.rtf

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7015,7 +7015,7 @@ Also note that dominance coefficients have a quirk: they are stored internally i
70157015
\f4\fs20 class documentation.\
70167016
\pard\pardeftab720\li720\fi-446\ri720\sb180\sa60\partightenfactor0
70177017

7018-
\f3\fs18 \cf2 \'96\'a0(fo<DataFrame>)loggedData(string$\'a0kind, [logical$\'a0id\'a0=\'a0F], [logical$\'a0mutationTypeID\'a0=\'a0F], [logical$\'a0chromosomeID\'a0=\'a0F], [logical$\'a0position\'a0=\'a0F], [logical$\'a0nucleotideValue\'a0=\'a0F], [logical$\'a0originTick\'a0=\'a0F], [logical$\'a0subpopID\'a0=\'a0F], [logical$\'a0tag\'a0=\'a0F], [Niso<Trait>\'a0trait\'a0=\'a0NULL], [logical$\'a0effect\'a0=\'a0F], [logical$\'a0dominance\'a0=\'a0F], [logical$\'a0hemizygousDominance\'a0=\'a0F])\
7018+
\f3\fs18 \cf2 \'96\'a0(ifo<DataFrame>)loggedData(string$\'a0kind, [logical$\'a0id\'a0=\'a0F], [logical$\'a0mutationTypeID\'a0=\'a0F], [logical$\'a0chromosomeID\'a0=\'a0F], [logical$\'a0position\'a0=\'a0F], [logical$\'a0nucleotideValue\'a0=\'a0F], [logical$\'a0originTick\'a0=\'a0F], [logical$\'a0subpopID\'a0=\'a0F], [logical$\'a0tag\'a0=\'a0F], [Niso<Trait>\'a0trait\'a0=\'a0NULL], [logical$\'a0effect\'a0=\'a0F], [logical$\'a0dominance\'a0=\'a0F], [logical$\'a0hemizygousDominance\'a0=\'a0F])\
70197019
\pard\pardeftab720\li547\ri720\sb60\sa60\partightenfactor0
70207020

70217021
\f4\fs20 \cf2 Returns mutation data produced by the mutation type\'92s logging facility, as configured by
@@ -7026,14 +7026,25 @@ Also note that dominance coefficients have a quirk: they are stored internally i
70267026
\f3\fs18 kind="sd"
70277027
\f4\fs20 ), or separate values for each mutation (for
70287028
\f3\fs18 kind="values"
7029-
\f4\fs20 ). If logging only of means was enabled (with the
7029+
\f4\fs20 );
7030+
\f3\fs18 kind="count"
7031+
\f4\fs20 is also allowed, and simply returns a singleton
7032+
\f3\fs18 integer
7033+
\f4\fs20 providing the number of entries (i.e., the number of mutations) that have been recorded. If logging only of means was enabled (with the
70307034
\f3\fs18 meanOnly=T
70317035
\f4\fs20 option to
70327036
\f3\fs18 logMutationData()
70337037
\f4\fs20 ), only
70347038
\f3\fs18 kind="mean"
7035-
\f4\fs20 is allowed, since separate values for each mutation are then not logged.\
7036-
The remaining flags control which columns of data should be returned; see
7039+
\f4\fs20 and
7040+
\f3\fs18 kind="count"
7041+
\f4\fs20 are allowed, since separate values for each mutation are then not logged.\
7042+
\pard\pardeftab720\li547\ri720\sb60\sa60\partightenfactor0
7043+
\cf2 The remaining flags control which columns of data should be returned (for
7044+
\f3\fs18 kind
7045+
\f4\fs20 options other than
7046+
\f3\fs18 "count"
7047+
\f4\fs20 ); see
70377048
\f3\fs18 logMutationData()
70387049
\f4\fs20 for a summary of the mutation properties they refer to. If only one data column is specified by the flags, a vector of values (or a mean or standard deviation) will be returned for that one specified data column. If more than one flag is set to
70397050
\f3\fs18 T
@@ -7049,15 +7060,7 @@ The remaining flags control which columns of data should be returned; see
70497060
\f3\fs18 hemizygousDominance
70507061
\f4\fs20 flags; see
70517062
\f3\fs18 logMutationData()
7052-
\f4\fs20 for further description. If
7053-
\f1\i all
7054-
\f4\i0 of these flags are
7055-
\f3\fs18 F
7056-
\f4\fs20 (the default), that is taken to mean that
7057-
\f1\i all
7058-
\f4\i0 logged data should be returned; in that case, a vector will be returned if only one column of data was logged, otherwise a
7059-
\f3\fs18 DataFrame
7060-
\f4\fs20 object will be returned, the same as when flags are specified explicitly. Flags set to
7063+
\f4\fs20 for further description. Flags set to
70617064
\f3\fs18 T
70627065
\f4\fs20 for data columns that were not actually logged will simply be ignored; similarly, traits specified by
70637066
\f3\fs18 trait
@@ -7094,8 +7097,7 @@ The remaining flags control which columns of data should be returned; see
70947097
\f4\fs20 ; and if logging is subsequently resumed with
70957098
\f3\fs18 enable=T
70967099
\f4\fs20 , any previously logged data will be discarded. (This can be useful if you wish to limit the size of the in-memory data while continuing to log new data: periodically write the accumulated data to a file and then disable and re-enable logging to discard the old data.)\
7097-
\pard\pardeftab720\li547\ri720\sb60\sa60\partightenfactor0
7098-
\cf2 If
7100+
If
70997101
\f3\fs18 meanOnly
71007102
\f4\fs20 is
71017103
\f3\fs18 F

VERSIONS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ multitrait branch:
138138
add a Species demandPhenotype() method, and change the Individual method demandPhenotype() to demandPhenotypeForIndividuals(); the Species method is generally preferred for speed
139139
add data logging capabilities to MutationType for easier assessment of requested vs. realized DFEs, etc.
140140
- (void)logMutationData(logical$ enable, [logical$ autogeneratedOnly = T], [logical$ meanOnly = F], <flags>)
141-
- (fo<DataFrame>)loggedData(string$ kind, <flags>)
141+
- (ifo<DataFrame>)loggedData(string$ kind, <flags>)
142142
policy change: mean(integer(0)) or mean(float(0)) now returns NAN rather than NULL, to match R; I just noticed this, and NAN does seem better
143143

144144

core/mutation_type.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,7 +1053,8 @@ EidosValue_SP MutationType::ExecuteMethod_loggedData(EidosGlobalStringID p_metho
10531053

10541054
// kind
10551055
typedef enum class _KindEnum {
1056-
kMean = 1,
1056+
kCount = 0,
1057+
kMean,
10571058
kSD,
10581059
kValues
10591060
} KindEnum;
@@ -1062,15 +1063,22 @@ EidosValue_SP MutationType::ExecuteMethod_loggedData(EidosGlobalStringID p_metho
10621063
const std::string &kind_str = kind_value_string->StringRefAtIndex_NOCAST(0, nullptr);
10631064
KindEnum kind;
10641065

1065-
if (kind_str == "mean") kind = KindEnum::kMean;
1066+
if (kind_str == "count") kind = KindEnum::kCount;
1067+
else if (kind_str == "mean") kind = KindEnum::kMean;
10661068
else if (kind_str == "sd") kind = KindEnum::kSD;
10671069
else if (kind_str == "values") kind = KindEnum::kValues;
10681070
else
1069-
EIDOS_TERMINATION << "ERROR (MutationType::ExecuteMethod_loggedData): loggedData() requires that kind be 'mean', 'sd', or 'values'." << EidosTerminate(nullptr);
1071+
EIDOS_TERMINATION << "ERROR (MutationType::ExecuteMethod_loggedData): loggedData() requires that kind be 'count', 'mean', 'sd', or 'values'." << EidosTerminate(nullptr);
10701072

10711073
if (log_meanOnly_ && (kind != KindEnum::kMean))
10721074
EIDOS_TERMINATION << "ERROR (MutationType::ExecuteMethod_loggedData): loggedData() can only return means (kind='mean'), since meanOnly=T was set in logMutationData()." << EidosTerminate(nullptr);
10731075

1076+
if (kind == KindEnum::kCount)
1077+
{
1078+
// for "count" the remaining flags are ignored; we just return the singleton count of mutations recorded
1079+
return EidosValue_SP(new EidosValue_Int((int64_t)log_size_));
1080+
}
1081+
10741082
// trait
10751083
std::vector<slim_trait_index_t> trait_indices;
10761084
species_.GetTraitIndicesFromEidosValue(trait_indices, trait_value, "loggedData");
@@ -1138,6 +1146,9 @@ EidosValue_SP MutationType::ExecuteMethod_loggedData(EidosGlobalStringID p_metho
11381146
(int)get_nucleotideValue + (int)get_originTick + (int)get_subpopID + (int)get_tag +
11391147
((int)get_effect) * trait_count + ((int)get_dominance) * trait_count + ((int)get_hemizygousDominance) * trait_count;
11401148

1149+
if (requested_count == 0)
1150+
return gStaticEidosValueNULL;
1151+
11411152
EidosDataFrame *dataframe = nullptr;
11421153
EidosValue_SP result_SP;
11431154

@@ -1613,7 +1624,7 @@ const std::vector<EidosMethodSignature_CSP> *MutationType_Class::Methods(void) c
16131624
methods->emplace_back((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature(gStr_effectDistributionTypeForTrait, kEidosValueMaskString))->AddIntStringObject_ON("trait", gSLiM_Trait_Class, gStaticEidosValueNULL));
16141625
methods->emplace_back((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature(gStr_drawEffectForTrait, kEidosValueMaskFloat))->AddIntStringObject_ON("trait", gSLiM_Trait_Class, gStaticEidosValueNULL)->AddInt_OS("n", gStaticEidosValue_Integer1));
16151626
methods->emplace_back((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature(gStr_setDefaultDominanceForTrait, kEidosValueMaskVOID))->AddIntStringObject_N("trait", gSLiM_Trait_Class)->AddFloat("dominance"));
1616-
methods->emplace_back((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature(gStr_loggedData, kEidosValueMaskFloat | kEidosValueMaskObject, gEidosDataFrame_Class))
1627+
methods->emplace_back((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature(gStr_loggedData, kEidosValueMaskInt | kEidosValueMaskFloat | kEidosValueMaskObject, gEidosDataFrame_Class))
16171628
->AddString_S("kind")
16181629
->AddLogical_OS("id", gStaticEidosValue_LogicalF)
16191630
->AddLogical_OS("mutationTypeID", gStaticEidosValue_LogicalF)

core/slim_test_genetics.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,30 @@ void _RunMutationTypeTests(void)
146146
SLiMAssertScriptStop(gen1_setup + "1 early() { m1.setEffectDistributionForTrait(NULL, 'w', 3.1, 7.5); if (abs(mean(m1.drawEffectForTrait(NULL, 2000)) - 2.910106) < 0.1) stop(); }", __LINE__);
147147
SLiMAssertScriptSuccess(gen1_setup + "1 early() { m1.setEffectDistributionForTrait(NULL, 's', 'rbinom(1, 4, 0.5);'); m1.drawEffectForTrait(); }", __LINE__);
148148
SLiMAssertScriptStop(gen1_setup + "1 early() { m1.setEffectDistributionForTrait(NULL, 's', 'rbinom(1, 4, 0.5);'); if (abs(mean(m1.drawEffectForTrait(NULL, 5000)) - 2.0) < 0.1) stop(); }", __LINE__);
149+
150+
// test mutation date recording with logMutationData() and loggedData()
151+
std::string data_recording =
152+
R"V0G0N(
153+
initialize() {
154+
initializeMutationRate(1e-7);
155+
initializeMutationType("m1", 0.5, "f", 0.0);
156+
m1.logMutationData(T, chromosomeID=T, position=T);
157+
initializeGenomicElementType("g1", m1, 1.0);
158+
initializeGenomicElement(g1, 0, 999999);
159+
initializeRecombinationRate(1e-8);
160+
}
161+
1 early() { sim.addSubpop("p1", 50); }
162+
100 late() {
163+
count = m1.loggedData(kind="count");
164+
pos = m1.loggedData(kind="values", position=T);
165+
df = m1.loggedData(kind="values", chromosomeID=T, position=T);
166+
167+
if ((count == 0) | (count != length(pos)) | (count != df.nrow))
168+
stop("MutationType data recording problem");
169+
}
170+
)V0G0N";
171+
172+
SLiMAssertScriptSuccess(data_recording);
149173
}
150174

151175
#pragma mark GenomicElementType tests

0 commit comments

Comments
 (0)