Skip to content

Commit 8583ca3

Browse files
committed
more tweaks to rationalize SLiM output formats
1 parent 2342bca commit 8583ca3

File tree

4 files changed

+56
-21
lines changed

4 files changed

+56
-21
lines changed

core/haplosome.cpp

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,7 +1298,7 @@ EidosValue_SP Haplosome::ExecuteMethod_sumOfMutationsOfType(EidosGlobalStringID
12981298
}
12991299

13001300
// print the sample represented by haplosomes, using SLiM's own format
1301-
void Haplosome::PrintHaplosomes_SLiM(std::ostream &p_out, std::vector<Haplosome *> &p_haplosomes, const Chromosome &p_chromosome, slim_objectid_t p_source_subpop_id)
1301+
void Haplosome::PrintHaplosomes_SLiM(std::ostream &p_out, std::vector<Haplosome *> &p_haplosomes, const Chromosome &p_chromosome)
13021302
{
13031303
Mutation *mut_block_ptr = gSLiM_Mutation_Block;
13041304
slim_popsize_t sample_size = (slim_popsize_t)p_haplosomes.size();
@@ -1334,14 +1334,29 @@ void Haplosome::PrintHaplosomes_SLiM(std::ostream &p_out, std::vector<Haplosome
13341334
// print the sample's haplosomes
13351335
p_out << "Haplosomes:" << std::endl;
13361336

1337-
for (slim_popsize_t j = 0; j < sample_size; j++) // go through all individuals
1337+
for (slim_popsize_t j = 0; j < sample_size; j++) // go through all haplosomes
13381338
{
13391339
Haplosome &haplosome = *p_haplosomes[j];
1340+
Individual *individual = haplosome.individual_;
13401341

1341-
if (p_source_subpop_id == -1)
1342-
p_out << "p*:" << j;
1343-
else
1344-
p_out << "p" << p_source_subpop_id << ":" << j;
1342+
if (!individual)
1343+
EIDOS_TERMINATION << "ERROR (Haplosome::PrintHaplosomes_SLiM): (internal error) missing individual for haplosome." << EidosTerminate();
1344+
1345+
slim_popsize_t index = individual->index_;
1346+
1347+
if (index == -1)
1348+
EIDOS_TERMINATION << "ERROR (Haplosome::PrintHaplosomes_SLiM): haplosomes being output must be visible in a subpopulation (i.e., may not belong to new juveniles)." << EidosTerminate();
1349+
1350+
Subpopulation *subpop = individual->subpopulation_;
1351+
1352+
if (!subpop)
1353+
EIDOS_TERMINATION << "ERROR (Haplosome::PrintHaplosomes_SLiM): (internal error) missing subpopulation for individual." << EidosTerminate();
1354+
1355+
// BCH 2/9/2025: For SLiM 5, we now print the subpopulation id and the
1356+
// individual index for the haplosome, telling the user where each
1357+
// haplosome came from; probably not useful, but more useful than before
1358+
p_out << 'p' << subpop->subpopulation_id_;
1359+
p_out << ":i" << index;
13451360

13461361
for (int run_index = 0; run_index < haplosome.mutrun_count_; ++run_index)
13471362
{
@@ -3089,7 +3104,7 @@ EidosValue_SP Haplosome_Class::ExecuteMethod_outputX(EidosGlobalStringID p_metho
30893104

30903105
// Call out to print the actual sample
30913106
if (p_method_id == gID_output)
3092-
Haplosome::PrintHaplosomes_SLiM(output_stream, haplosomes, *chromosome, -1); // -1 represents unknown source subpopulation
3107+
Haplosome::PrintHaplosomes_SLiM(output_stream, haplosomes, *chromosome);
30933108
else if (p_method_id == gID_outputMS)
30943109
Haplosome::PrintHaplosomes_MS(output_stream, haplosomes, *chromosome, filter_monomorphic);
30953110
else if (p_method_id == gID_outputVCF)
@@ -3124,7 +3139,7 @@ EidosValue_SP Haplosome_Class::ExecuteMethod_outputX(EidosGlobalStringID p_metho
31243139

31253140
outfile << " " << outfile_path << std::endl;
31263141

3127-
Haplosome::PrintHaplosomes_SLiM(outfile, haplosomes, *chromosome, -1); // -1 represents unknown source subpopulation
3142+
Haplosome::PrintHaplosomes_SLiM(outfile, haplosomes, *chromosome);
31283143
break;
31293144
case gID_outputMS:
31303145
Haplosome::PrintHaplosomes_MS(outfile, haplosomes, *chromosome, filter_monomorphic);

core/haplosome.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ class Haplosome : public EidosObject
401401
void record_derived_states(Species *p_species) const;
402402

403403
// print the sample represented by haplosomes, using SLiM's own format
404-
static void PrintHaplosomes_SLiM(std::ostream &p_out, std::vector<Haplosome *> &p_haplosomes, const Chromosome &p_chromosome, slim_objectid_t p_source_subpop_id);
404+
static void PrintHaplosomes_SLiM(std::ostream &p_out, std::vector<Haplosome *> &p_haplosomes, const Chromosome &p_chromosome);
405405

406406
// print the sample represented by haplosomes, using "ms" format
407407
static void PrintHaplosomes_MS(std::ostream &p_out, std::vector<Haplosome *> &p_haplosomes, const Chromosome &p_chromosome, bool p_filter_monomorphic);

core/population.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7845,7 +7845,9 @@ void Population::PrintAll(std::ostream &p_out, bool p_output_spatial_positions,
78457845

78467846
// i used to be the haplosome index, now it is the individual index; we will have one or
78477847
// two lines with this individual index, depending on the intrinsic ploidy of the chromosome
7848-
p_out << "p" << subpop_id << ":" << individual_index;
7848+
// since we changed from a haplosome index to an individual index, we now emit an "i",
7849+
// just follow the same convention as the Individuals section
7850+
p_out << "p" << subpop_id << ":i" << individual_index;
78497851

78507852
if (haplosome->IsNull())
78517853
{
@@ -8393,7 +8395,7 @@ void Population::PrintSample_SLiM(std::ostream &p_out, Subpopulation &p_subpop,
83938395
}
83948396

83958397
// print the sample using Haplosome's static member function
8396-
Haplosome::PrintHaplosomes_SLiM(p_out, sample, p_chromosome, p_subpop.subpopulation_id_);
8398+
Haplosome::PrintHaplosomes_SLiM(p_out, sample, p_chromosome);
83978399
}
83988400

83998401
// print sample of p_sample_size haplosomes from subpopulation p_subpop_id, using "ms" format

core/species.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -965,7 +965,11 @@ slim_tick_t Species::_InitializePopulationFromTextFile(const char *p_file, Eidos
965965
std::istringstream iss(line);
966966

967967
iss >> sub; // pX:iY – individual identifier
968-
int pos = static_cast<int>(sub.find_first_of(':'));
968+
std::size_t pos = static_cast<int>(sub.find_first_of(':'));
969+
970+
if (pos == std::string::npos)
971+
EIDOS_TERMINATION << "ERROR (Species::_InitializePopulationFromTextFile): colon missing in individual specifier." << EidosTerminate();
972+
969973
std::string &&subpop_id_string = sub.substr(0, pos);
970974

971975
slim_objectid_t subpop_id = SLiMEidosScript::ExtractIDFromStringWithPrefix(subpop_id_string, 'p', nullptr);
@@ -1369,23 +1373,30 @@ slim_tick_t Species::_InitializePopulationFromTextFile(const char *p_file, Eidos
13691373
std::istringstream iss(line);
13701374

13711375
iss >> sub;
1372-
int pos = static_cast<int>(sub.find_first_of(':'));
1376+
std::size_t pos = static_cast<int>(sub.find_first_of(':'));
1377+
1378+
if (pos == std::string::npos)
1379+
EIDOS_TERMINATION << "ERROR (Species::_InitializePopulationFromTextFile): colon missing in individual specifier." << EidosTerminate();
1380+
13731381
std::string &&subpop_id_string = sub.substr(0, pos);
1382+
13741383
slim_objectid_t subpop_id = SLiMEidosScript::ExtractIDFromStringWithPrefix(subpop_id_string, 'p', nullptr);
1384+
std::string &&individual_index_string = sub.substr(pos + 1, std::string::npos);
1385+
1386+
if (individual_index_string[0] != 'i')
1387+
EIDOS_TERMINATION << "ERROR (Species::_InitializePopulationFromTextFile): reference to individual is malformed." << EidosTerminate();
1388+
1389+
// this used to be the haplosome index, now it is the individual index and we have to figure out the haplosome index
1390+
int64_t individual_index_long = EidosInterpreter::NonnegativeIntegerForString(individual_index_string.c_str() + 1, nullptr);
13751391

13761392
Subpopulation *subpop = SubpopulationWithID(subpop_id);
13771393

13781394
if (!subpop)
13791395
EIDOS_TERMINATION << "ERROR (Species::_InitializePopulationFromTextFile): referenced subpopulation p" << subpop_id << " not defined." << EidosTerminate();
13801396

1381-
sub.erase(0, pos + 1); // remove the subpop_id and the colon
1382-
1383-
// this used to be the haplosome index, now it is the individual index and we have to figure out the haplosome index
1384-
int64_t individual_index_long = EidosInterpreter::NonnegativeIntegerForString(sub, nullptr);
1385-
1386-
if ((individual_index_long < 0) || (individual_index_long > SLIM_MAX_SUBPOP_SIZE))
1387-
EIDOS_TERMINATION << "ERROR (Species::_InitializePopulationFromTextFile): individual index out of permitted range." << EidosTerminate();
1388-
slim_popsize_t individual_index = static_cast<slim_popsize_t>(individual_index_long); // range-check is above since we need to check against SLIM_MAX_SUBPOP_SIZE
1397+
if (individual_index_long > subpop->parent_subpop_size_)
1398+
EIDOS_TERMINATION << "ERROR (Species::_InitializePopulationFromTextFile): referenced individual i" << individual_index_long << " is out of range." << EidosTerminate();
1399+
slim_popsize_t individual_index = static_cast<slim_popsize_t>(individual_index_long);
13891400

13901401
// detect when this is the second haplosome line for a given individual, and validate that
13911402
// FIXME this code is brittle in various ways -- a second line might be needed but omitted, or a third line might be given
@@ -1401,6 +1412,11 @@ slim_tick_t Species::_InitializePopulationFromTextFile(const char *p_file, Eidos
14011412
int haplosome_index = first_haplosome_index + is_individual_index_repeat;
14021413
Haplosome &haplosome = *(ind->haplosomes_[haplosome_index]);
14031414

1415+
std::cout << "for chromosome index " << (unsigned int)chromosome_index << " individual identifier " << sub << " parsed to subpop id " << subpop_id << " and individual index " << individual_index << ", is_individual_index_repeat == " << is_individual_index_repeat << ", haplosome_index " << haplosome_index << std::endl;
1416+
1417+
if (haplosome.chromosome_index_ != chromosome->index_)
1418+
EIDOS_TERMINATION << "ERROR (Species::_InitializePopulationFromTextFile): (internal error) haplosome does not belong to the focal chromosome." << EidosTerminate();
1419+
14041420
if (iss >> sub)
14051421
{
14061422
// BCH 2/5/2025: We instantiate null haplosomes only where expect them to be, based upon
@@ -1468,6 +1484,8 @@ slim_tick_t Species::_InitializePopulationFromTextFile(const char *p_file, Eidos
14681484
current_mutrun = haplosome.WillModifyRun_UNSHARED(current_mutrun_index, mutrun_context);
14691485
}
14701486

1487+
std::cout << " adding mutation with identifier " << sub << ", mutation ID " << mutation << ", existing count " << current_mutrun->size() << std::endl;
1488+
14711489
current_mutrun->emplace_back(mutation);
14721490
}
14731491
while (iss >> sub);

0 commit comments

Comments
 (0)