Skip to content

Commit 2342bca

Browse files
committed
add support for write/read of Individual tags in outputFull()
1 parent c2da82f commit 2342bca

File tree

6 files changed

+290
-37
lines changed

6 files changed

+290
-37
lines changed

QtSLiM/help/SLiMHelpClasses.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -945,12 +945,13 @@
945945
<p class="p6">In SLiM 5 and later, in models with multiple chromosome the output includes the symbol of the chromosome associated with each mutation.</p>
946946
<p class="p6"><span class="s3">In SLiM 3.3 and later, the output format includes the nucleotides associated with any nucleotide-based mutations.</span></p>
947947
<p class="p4">Output is generally done in a <span class="s1">late()</span> event, so that the output reflects the state of the simulation at the end of a tick.</p>
948-
<p class="p3">– (void)outputFull([Ns$ filePath = NULL], [logical$ binary = F], [logical$ append = F], [logical$ spatialPositions = T]<span class="s7">, [logical$ ages = T], [logical$ ancestralNucleotides = T]</span><span class="s5">, [logical$ pedigreeIDs = F]</span>)</p>
948+
<p class="p3">– (void)outputFull([Ns$ filePath = NULL], [logical$ binary = F], [logical$ append = F], [logical$ spatialPositions = T]<span class="s7">, [logical$ ages = T], [logical$ ancestralNucleotides = T]</span><span class="s5">, [logical$ pedigreeIDs = F], [logical$ individualTags = F]</span>)</p>
949949
<p class="p4">Output the state of the entire population.<span class="Apple-converted-space">  </span>If the optional parameter <span class="s1">filePath</span> is <span class="s1">NULL</span> (the default), output will be sent to Eidos’s output stream.<span class="Apple-converted-space">  </span>Otherwise, output will be sent to the filesystem path specified by <span class="s1">filePath</span>, overwriting that file if <span class="s1">append</span> if <span class="s1">F</span>, or appending to the end of it if <span class="s1">append</span> is <span class="s1">T</span><span class="s2">.</span><span class="Apple-converted-space">  </span>When writing to a file, a <span class="s1">logical</span> flag, <span class="s1">binary</span>, may be supplied as well.<span class="Apple-converted-space">  </span>If <span class="s1">binary</span> is <span class="s1">T</span>, the population state will be written as a binary file instead of a text file (binary data cannot be written to the standard output stream).<span class="Apple-converted-space">  </span>The binary file is usually smaller, and in any case will be read much faster than the corresponding text file would be read.<span class="Apple-converted-space">  </span>Binary files are not guaranteed to be portable between platforms; in other words, a binary file written on one machine may not be readable on a different machine (but in practice it usually will be, unless the platforms being used are fairly unusual).<span class="Apple-converted-space">  </span>If <span class="s1">binary</span> is <span class="s1">F</span> (the default), a text file will be written.</p>
950950
<p class="p4">Beginning with SLiM 2.3, the <span class="s1">spatialPositions</span> parameter may be used to control the output of the spatial positions of individuals in species for which continuous space has been enabled using the <span class="s1">dimensionality</span> option of <span class="s1">initializeSLiMOptions()</span><span class="s2">.</span><span class="Apple-converted-space">  </span>If <span class="s1">spatialPositions</span> is <span class="s1">F</span>, the output will not contain spatial positions, and will be identical to the output generated by SLiM 2.1 and later.<span class="Apple-converted-space">  </span>If <span class="s1">spatialPositions</span> is <span class="s1">T</span>, spatial position information will be output if it is available.<span class="Apple-converted-space">  </span>If the species does not have continuous space enabled, the <span class="s1">spatialPositions</span> parameter will be ignored.<span class="Apple-converted-space">  </span>Positional information may be output for all output destinations – the Eidos output stream, a text file, or a binary file.</p>
951951
<p class="p6"><span class="s3">Beginning with SLiM 3.0, the </span><span class="s4">ages</span><span class="s3"> parameter may be used to control the output of the ages of individuals in nonWF simulations.<span class="Apple-converted-space">  </span>If </span><span class="s4">ages</span><span class="s3"> is </span><span class="s4">F</span><span class="s3">, the output will not contain ages, preserving backward compatibility with the output format of SLiM 2.1 and later.<span class="Apple-converted-space">  </span>If </span><span class="s4">ages</span><span class="s3"> is </span><span class="s4">T</span><span class="s3">, ages will be output for nonWF models.<span class="Apple-converted-space">  </span>In WF simulations, the </span><span class="s4">ages</span><span class="s3"> parameter will be ignored.</span></p>
952952
<p class="p6"><span class="s3">Beginning with SLiM 3.3, the </span><span class="s4">ancestralNucleotides</span><span class="s3"> parameter may be used to control the output of the ancestral nucleotide sequence in nucleotide-based models.<span class="Apple-converted-space">  </span>If </span><span class="s4">ancestralNucleotides</span><span class="s3"> is </span><span class="s4">F</span><span class="s3">, the output will not contain ancestral nucleotide information, and so the ancestral sequence will not be restored correctly if the saved file is loaded with </span><span class="s4">readPopulationFile()</span><span class="s3">.<span class="Apple-converted-space">  </span>This option is provided because the ancestral sequence may be quite large, for models with a long chromosome (e.g., 1 GB if the chromosome is 10</span><span class="s20"><sup>9</sup></span><span class="s3"> bases long, when saved in text format, or 0.25 GB when saved in binary format).<span class="Apple-converted-space">  </span>If the model is not nucleotide-based (as enabled with the </span><span class="s4">nucleotideBased</span><span class="s3"> parameter to </span><span class="s4">initializeSLiMOptions()</span><span class="s3">), the </span><span class="s4">ancestralNucleotides</span><span class="s3"> parameter will be ignored.<span class="Apple-converted-space">  </span>Note that in nucleotide-based models the output format will <i>always</i> include the nucleotides associated with any nucleotide-based mutations; the </span><span class="s4">ancestralNucleotides</span><span class="s3"> flag governs only the ancestral sequence.</span></p>
953-
<p class="p6">Beginning with SLiM 3.5, the <span class="s1">pedigreeIDs</span> parameter may be used to request that pedigree IDs be written out (and read in by <span class="s1">readFromPopulationFile()</span>, subsequently).<span class="Apple-converted-space">  </span>This option is turned off (<span class="s1">F</span>) by default, to preserve backward compatibility; if it is turned on (<span class="s1">T</span>), different file version values will be used, and backward compatibility with previous versions of SLiM will be lost.<span class="Apple-converted-space">  </span>This option may only be used if SLiM’s optional pedigree tracking has been enabled with <span class="s1">initializeSLiMOptions(keepPedigrees=T)</span>.</p>
953+
<p class="p6">Beginning with SLiM 3.5, the <span class="s1">pedigreeIDs</span> parameter may be used to request that pedigree IDs be written out (and read in by <span class="s1">readFromPopulationFile()</span>, subsequently).<span class="Apple-converted-space">  </span>This option is turned off (<span class="s1">F</span>) by default, for brevity.<span class="Apple-converted-space">  </span>This option may only be used if SLiM’s optional pedigree tracking has been enabled with <span class="s1">initializeSLiMOptions(keepPedigrees=T)</span>.</p>
954+
<p class="p6">Beginning with SLiM 5.0, the <span class="s1">individualTags</span> parameter may be used to request that tag values for all individuals be written out (and read in by <span class="s1">readFromPopulationFile()</span>, subsequently).<span class="Apple-converted-space">  </span>This option is turned off (<span class="s1">F</span>) by default, for brevity; if it turned on (<span class="s1">T</span>), the values of all tags for all individuals (specifically, the <span class="s1">tag</span>, <span class="s1">tagF</span>, <span class="s1">tagL0</span>, <span class="s1">tagL1</span>, <span class="s1">tagL2</span>, <span class="s1">tagL3</span>, and <span class="s1">tagL4</span> properties) will be written, as described further in section 27.1.1.</p>
954955
<p class="p4">Output is generally done in a <span class="s1">late()</span> event, so that the output reflects the state of the simulation at the end of a tick.</p>
955956
<p class="p3">– (void)outputMutations(object&lt;Mutation&gt; mutations, [Ns$ filePath = NULL], [logical$ append = F])</p>
956957
<p class="p6"><span class="s5">Output all of the given mutations.<span class="Apple-converted-space">  </span>This can be used to output all mutations of a given mutation type, for example.<span class="Apple-converted-space">  </span></span><span class="s3">If the optional parameter </span><span class="s4">filePath</span><span class="s3"> is </span><span class="s4">NULL</span><span class="s3"> (the default), output will be sent to Eidos’s output stream.<span class="Apple-converted-space">  </span>Otherwise, output will be sent to the filesystem path specified by </span><span class="s4">filePath</span><span class="s3">, overwriting that file if </span><span class="s4">append</span><span class="s3"> if </span><span class="s4">F</span><span class="s3">, or appending to the end of it if </span><span class="s4">append</span><span class="s3"> is </span><span class="s4">T</span><span class="s3">.</span></p>

SLiMgui/SLiMHelpClasses.rtf

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8590,7 +8590,7 @@ In SLiM 3.3 and later, the output format includes the nucleotides associated wit
85908590
\pard\pardeftab397\li720\fi-446\ri720\sb180\sa60\partightenfactor0
85918591

85928592
\f3\fs18 \cf0 \'96\'a0(void)outputFull([Ns$\'a0filePath\'a0=\'a0NULL], [logical$\'a0binary\'a0=\'a0F], [logical$\'a0append\'a0=\'a0F], [logical$\'a0spatialPositions\'a0=\'a0T]\cf2 \expnd0\expndtw0\kerning0
8593-
, [logical$\'a0ages\'a0=\'a0T], [logical$\'a0ancestralNucleotides\'a0=\'a0T]\kerning1\expnd0\expndtw0 , [logical$\'a0pedigreeIDs\'a0=\'a0F]\cf0 )
8593+
, [logical$\'a0ages\'a0=\'a0T], [logical$\'a0ancestralNucleotides\'a0=\'a0T]\kerning1\expnd0\expndtw0 , [logical$\'a0pedigreeIDs\'a0=\'a0F], [logical$\'a0individualTags\'a0=\'a0F]\cf0 )
85948594
\f5 \
85958595
\pard\pardeftab720\li547\ri720\sb60\sa60\partightenfactor0
85968596

@@ -8684,11 +8684,32 @@ Beginning with SLiM 3.3, the
86848684
\f3\fs18 readFromPopulationFile()
86858685
\f4\fs20 , subsequently). This option is turned off (
86868686
\f3\fs18 F
8687-
\f4\fs20 ) by default, to preserve backward compatibility; if it is turned on (
8688-
\f3\fs18 T
8689-
\f4\fs20 ), different file version values will be used, and backward compatibility with previous versions of SLiM will be lost. This option may only be used if SLiM\'92s optional pedigree tracking has been enabled with
8687+
\f4\fs20 ) by default, for brevity. This option may only be used if SLiM\'92s optional pedigree tracking has been enabled with
86908688
\f3\fs18 initializeSLiMOptions(keepPedigrees=T)
86918689
\f4\fs20 .\
8690+
Beginning with SLiM 5.0, the
8691+
\f3\fs18 individualTags
8692+
\f4\fs20 parameter may be used to request that tag values for all individuals be written out (and read in by
8693+
\f3\fs18 readFromPopulationFile()
8694+
\f4\fs20 , subsequently). This option is turned off (
8695+
\f3\fs18 F
8696+
\f4\fs20 ) by default, for brevity; if it turned on (
8697+
\f3\fs18 T
8698+
\f4\fs20 ), the values of all tags for all individuals (specifically, the
8699+
\f3\fs18 tag
8700+
\f4\fs20 ,
8701+
\f3\fs18 tagF
8702+
\f4\fs20 ,
8703+
\f3\fs18 tagL0
8704+
\f4\fs20 ,
8705+
\f3\fs18 tagL1
8706+
\f4\fs20 ,
8707+
\f3\fs18 tagL2
8708+
\f4\fs20 ,
8709+
\f3\fs18 tagL3
8710+
\f4\fs20 , and
8711+
\f3\fs18 tagL4
8712+
\f4\fs20 properties) will be written, as described further in section 27.1.1.\
86928713
\pard\pardeftab543\li547\ri720\sb60\sa60\partightenfactor0
86938714
\cf0 Output is generally done in a
86948715
\f3\fs18 late()

VERSIONS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ development head (in the master branch):
131131
Species method readFromPopulationFile(): support reading multi-chromosome output, for both text and binary
132132
policy change: readFromPopulationFile() breaks backward compatibility with old file formats, for both text and binary; too much has changed
133133
change file format codes for class Haplosome from GS/GM/GV to HS/HM/HV, matching the rename from Genome to Haplosome
134+
add support for writing/reading Individual tag values in outputFull(), readFromPopulationFile()
134135

135136

136137
version 4.3 (Eidos version 3.3):

core/population.cpp

Lines changed: 77 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7555,10 +7555,6 @@ void Population::CheckMutationRegistry(bool p_check_haplosomes)
75557555
// print all mutations and all haplosomes to a stream
75567556
void Population::PrintAll(std::ostream &p_out, bool p_output_spatial_positions, bool p_output_ages, bool p_output_ancestral_nucs, bool p_output_pedigree_ids, bool p_output_ind_tags) const
75577557
{
7558-
// FIXME MULTICHROM implement output of individual tags!
7559-
if (p_output_ind_tags)
7560-
EIDOS_TERMINATION << "ERROR (Population::PrintAll): (internal error) p_output_ind_tags not yet implemented!." << EidosTerminate();
7561-
75627558
if (child_generation_valid_)
75637559
EIDOS_TERMINATION << "ERROR (Population::PrintAll): (internal error) called with child generation active!." << EidosTerminate();
75647560

@@ -7658,6 +7654,7 @@ void Population::PrintAll(std::ostream &p_out, bool p_output_spatial_positions,
76587654
for (slim_popsize_t i = 0; i < subpop_size; i++) // go through all children
76597655
{
76607656
Individual &individual = *(subpop->parent_individuals_[i]);
7657+
static char double_buf[40];
76617658

76627659
p_out << "p" << subpop_id << ":i" << i; // individual identifier
76637660

@@ -7679,8 +7676,6 @@ void Population::PrintAll(std::ostream &p_out, bool p_output_spatial_positions,
76797676
{
76807677
THREAD_SAFETY_IN_ACTIVE_PARALLEL("Population::PrintAll(): usage of statics");
76817678

7682-
static char double_buf[40];
7683-
76847679
if (spatial_output_count >= 1)
76857680
{
76867681
snprintf(double_buf, 40, "%.*g", EIDOS_DBL_DIGS, individual.spatial_x_); // necessary precision for non-lossiness
@@ -7702,10 +7697,49 @@ void Population::PrintAll(std::ostream &p_out, bool p_output_spatial_positions,
77027697
if (age_output_count)
77037698
p_out << " " << individual.age_;
77047699

7705-
p_out << std::endl;
7706-
77077700
// output individual tags if requested
7708-
// FIXME MULTICHROM implement this
7701+
if (p_output_ind_tags)
7702+
{
7703+
if (individual.tag_value_ == SLIM_TAG_UNSET_VALUE)
7704+
p_out << " ?";
7705+
else
7706+
p_out << ' ' << individual.tag_value_;
7707+
7708+
if (individual.tagF_value_ == SLIM_TAGF_UNSET_VALUE)
7709+
p_out << " ?";
7710+
else
7711+
{
7712+
snprintf(double_buf, 40, "%.*g", EIDOS_DBL_DIGS, individual.tagF_value_); // necessary precision for non-lossiness
7713+
p_out << " " << double_buf;
7714+
}
7715+
7716+
if (individual.tagL0_set_)
7717+
p_out << ' ' << (individual.tagL0_value_ ? 'T' : 'F');
7718+
else
7719+
p_out << " ?";
7720+
7721+
if (individual.tagL1_set_)
7722+
p_out << ' ' << (individual.tagL1_value_ ? 'T' : 'F');
7723+
else
7724+
p_out << " ?";
7725+
7726+
if (individual.tagL2_set_)
7727+
p_out << ' ' << (individual.tagL2_value_ ? 'T' : 'F');
7728+
else
7729+
p_out << " ?";
7730+
7731+
if (individual.tagL3_set_)
7732+
p_out << ' ' << (individual.tagL3_value_ ? 'T' : 'F');
7733+
else
7734+
p_out << " ?";
7735+
7736+
if (individual.tagL4_set_)
7737+
p_out << ' ' << (individual.tagL4_value_ ? 'T' : 'F');
7738+
else
7739+
p_out << " ?";
7740+
}
7741+
7742+
p_out << std::endl;
77097743

77107744
#if DO_MEMORY_CHECKS
77117745
if (eidos_do_memory_checks)
@@ -7872,10 +7906,6 @@ void Population::PrintAll(std::ostream &p_out, bool p_output_spatial_positions,
78727906
// print all mutations and all haplosomes to a stream in binary, for maximum reading speed
78737907
void Population::PrintAllBinary(std::ostream &p_out, bool p_output_spatial_positions, bool p_output_ages, bool p_output_ancestral_nucs, bool p_output_pedigree_ids, bool p_output_ind_tags) const
78747908
{
7875-
// FIXME MULTICHROM implement output of individual tags!
7876-
if (p_output_ind_tags)
7877-
EIDOS_TERMINATION << "ERROR (Population::PrintAllBinary): (internal error) p_output_ind_tags not yet implemented!." << EidosTerminate();
7878-
78797909
if (child_generation_valid_)
78807910
EIDOS_TERMINATION << "ERROR (Population::PrintAllBinary): (internal error) called with child generation active!." << EidosTerminate();
78817911

@@ -8059,7 +8089,40 @@ void Population::PrintAllBinary(std::ostream &p_out, bool p_output_spatial_posit
80598089
}
80608090

80618091
// output individual tags if requested
8062-
// FIXME MULTICHROM implement this
8092+
if (p_output_ind_tags)
8093+
{
8094+
char T_value = 1, F_value = 0, UNDEF_value = 2;
8095+
8096+
// for these two, we just write out undefined-tag values directly; they will read back in
8097+
p_out.write(reinterpret_cast<char *>(&individual.tag_value_), sizeof individual.tag_value_);
8098+
p_out.write(reinterpret_cast<char *>(&individual.tagF_value_), sizeof individual.tagF_value_);
8099+
8100+
// for the logical tags, we write out an undefined-tag value of 2
8101+
if (individual.tagL0_set_)
8102+
p_out.write(individual.tagL0_value_ ? &T_value : &F_value, sizeof T_value);
8103+
else
8104+
p_out.write(&UNDEF_value, sizeof UNDEF_value);
8105+
8106+
if (individual.tagL1_set_)
8107+
p_out.write(individual.tagL1_value_ ? &T_value : &F_value, sizeof T_value);
8108+
else
8109+
p_out.write(&UNDEF_value, sizeof UNDEF_value);
8110+
8111+
if (individual.tagL2_set_)
8112+
p_out.write(individual.tagL2_value_ ? &T_value : &F_value, sizeof T_value);
8113+
else
8114+
p_out.write(&UNDEF_value, sizeof UNDEF_value);
8115+
8116+
if (individual.tagL3_set_)
8117+
p_out.write(individual.tagL3_value_ ? &T_value : &F_value, sizeof T_value);
8118+
else
8119+
p_out.write(&UNDEF_value, sizeof UNDEF_value);
8120+
8121+
if (individual.tagL4_set_)
8122+
p_out.write(individual.tagL4_value_ ? &T_value : &F_value, sizeof T_value);
8123+
else
8124+
p_out.write(&UNDEF_value, sizeof UNDEF_value);
8125+
}
80638126
}
80648127
}
80658128

0 commit comments

Comments
 (0)