diff --git a/QtSLiM/QtSLiMWindow.cpp b/QtSLiM/QtSLiMWindow.cpp index 88023788..5d4d16c4 100644 --- a/QtSLiM/QtSLiMWindow.cpp +++ b/QtSLiM/QtSLiMWindow.cpp @@ -3974,78 +3974,92 @@ void QtSLiMWindow::displayProfileResults(void) continue; } - int64_t power_tallies[20]; // we only go up to 1024 mutruns right now, but this gives us some headroom - int64_t power_tallies_total = static_cast(focal_species->profile_mutcount_history_.size()); - - for (int power = 0; power < 20; ++power) - power_tallies[power] = 0; - - for (int32_t count : focal_species->profile_mutcount_history_) - { - int power = static_cast(round(log2(count))); - - power_tallies[power]++; - } - - for (int power = 0; power < 20; ++power) - { - if (power_tallies[power] > 0) - { - tc.insertText(QString("%1%").arg((power_tallies[power] / static_cast(power_tallies_total)) * 100.0, 6, 'f', 2), menlo11_d); - tc.insertText(QString(" of ticks : %1 mutation runs per haplosome\n").arg(static_cast(round(pow(2.0, power)))), optima13_d); - } - } - - - int64_t regime_tallies[3]; - int64_t regime_tallies_total = static_cast(focal_species->profile_nonneutral_regime_history_.size()); - - for (int regime = 0; regime < 3; ++regime) - regime_tallies[regime] = 0; - - for (int32_t regime : focal_species->profile_nonneutral_regime_history_) - if ((regime >= 1) && (regime <= 3)) - regime_tallies[regime - 1]++; - else - regime_tallies_total--; - - tc.insertText(" \n", optima13_d); - - for (int regime = 0; regime < 3; ++regime) - { - tc.insertText(QString("%1%").arg((regime_tallies[regime] / static_cast(regime_tallies_total)) * 100.0, 6, 'f', 2), menlo11_d); - tc.insertText(QString(" of ticks : regime %1 (%2)\n").arg(regime + 1).arg(regime == 0 ? "no mutationEffect() callbacks" : (regime == 1 ? "constant neutral mutationEffect() callbacks only" : "unpredictable mutationEffect() callbacks present")), optima13_d); - } - - - tc.insertText(" \n", optima13_d); - - tc.insertText(QString("%1").arg(focal_species->profile_mutation_total_usage_), menlo11_d); - tc.insertText(" mutations referenced, summed across all ticks\n", optima13_d); - - tc.insertText(QString("%1").arg(focal_species->profile_nonneutral_mutation_total_), menlo11_d); - tc.insertText(" mutations considered potentially nonneutral\n", optima13_d); - - tc.insertText(QString("%1%").arg(((focal_species->profile_mutation_total_usage_ - focal_species->profile_nonneutral_mutation_total_) / static_cast(focal_species->profile_mutation_total_usage_)) * 100.0, 0, 'f', 2), menlo11_d); - tc.insertText(" of mutations excluded from fitness calculations\n", optima13_d); + { + int64_t regime_tallies[3]; + int64_t regime_tallies_total = static_cast(focal_species->profile_nonneutral_regime_history_.size()); + + for (int regime = 0; regime < 3; ++regime) + regime_tallies[regime] = 0; + + for (int32_t regime : focal_species->profile_nonneutral_regime_history_) + if ((regime >= 1) && (regime <= 3)) + regime_tallies[regime - 1]++; + else + regime_tallies_total--; + + for (int regime = 0; regime < 3; ++regime) + { + tc.insertText(QString("%1%").arg((regime_tallies[regime] / static_cast(regime_tallies_total)) * 100.0, 6, 'f', 2), menlo11_d); + tc.insertText(QString(" of ticks : regime %1 (%2)\n").arg(regime + 1).arg(regime == 0 ? "no mutationEffect() callbacks" : (regime == 1 ? "constant neutral mutationEffect() callbacks only" : "unpredictable mutationEffect() callbacks present")), optima13_d); + } + + tc.insertText(" \n", optima8_d); + } - tc.insertText(QString("%1").arg(focal_species->profile_max_mutation_index_), menlo11_d); + tc.insertText(QString("%1").arg(focal_species->profile_max_mutation_index_), menlo11_d); tc.insertText(" maximum simultaneous mutations\n", optima13_d); + + + const std::vector &chromosomes = focal_species->Chromosomes(); - - tc.insertText(" \n", optima13_d); - - tc.insertText(QString("%1").arg(focal_species->profile_mutrun_total_usage_), menlo11_d); - tc.insertText(" mutation runs referenced, summed across all ticks\n", optima13_d); - - tc.insertText(QString("%1").arg(focal_species->profile_unique_mutrun_total_), menlo11_d); - tc.insertText(" unique mutation runs maintained among those\n", optima13_d); - - tc.insertText(QString("%1%").arg((focal_species->profile_mutrun_nonneutral_recache_total_ / static_cast(focal_species->profile_unique_mutrun_total_)) * 100.0, 6, 'f', 2), menlo11_d); - tc.insertText(" of mutation run nonneutral caches rebuilt per tick\n", optima13_d); - - tc.insertText(QString("%1%").arg(((focal_species->profile_mutrun_total_usage_ - focal_species->profile_unique_mutrun_total_) / static_cast(focal_species->profile_mutrun_total_usage_)) * 100.0, 6, 'f', 2), menlo11_d); - tc.insertText(" of mutation runs shared among haplosomes", optima13_d); + for (Chromosome *focal_chromosome : chromosomes) + { + tc.insertText(" \n", optima13_d); + tc.insertText("Chromosome ", optima13i_d); + tc.insertText(QString::fromStdString(focal_chromosome->Symbol()), optima13i_d); + tc.insertText(":\n", optima13i_d); + tc.insertText(" \n", optima3_d); + + { + int64_t power_tallies[20]; // we only go up to 1024 mutruns right now, but this gives us some headroom + int64_t power_tallies_total = static_cast(focal_chromosome->profile_mutcount_history_.size()); + + for (int power = 0; power < 20; ++power) + power_tallies[power] = 0; + + for (int32_t count : focal_chromosome->profile_mutcount_history_) + { + int power = static_cast(round(log2(count))); + + power_tallies[power]++; + } + + for (int power = 0; power < 20; ++power) + { + if (power_tallies[power] > 0) + { + tc.insertText(QString("%1%").arg((power_tallies[power] / static_cast(power_tallies_total)) * 100.0, 6, 'f', 2), menlo11_d); + tc.insertText(QString(" of ticks : %1 mutation runs per haplosome\n").arg(static_cast(round(pow(2.0, power)))), optima13_d); + } + } + } + + tc.insertText(" \n", optima8_d); + + tc.insertText(QString("%1").arg(focal_chromosome->profile_mutation_total_usage_), menlo11_d); + tc.insertText(" mutations referenced, summed across all ticks\n", optima13_d); + + tc.insertText(QString("%1").arg(focal_chromosome->profile_nonneutral_mutation_total_), menlo11_d); + tc.insertText(" mutations considered potentially nonneutral\n", optima13_d); + + tc.insertText(QString("%1%").arg(((focal_chromosome->profile_mutation_total_usage_ - focal_chromosome->profile_nonneutral_mutation_total_) / static_cast(focal_chromosome->profile_mutation_total_usage_)) * 100.0, 0, 'f', 2), menlo11_d); + tc.insertText(" of mutations excluded from fitness calculations\n", optima13_d); + + + tc.insertText(" \n", optima8_d); + + tc.insertText(QString("%1").arg(focal_chromosome->profile_mutrun_total_usage_), menlo11_d); + tc.insertText(" mutation runs referenced, summed across all ticks\n", optima13_d); + + tc.insertText(QString("%1").arg(focal_chromosome->profile_unique_mutrun_total_), menlo11_d); + tc.insertText(" unique mutation runs maintained among those\n", optima13_d); + + tc.insertText(QString("%1%").arg((focal_chromosome->profile_mutrun_nonneutral_recache_total_ / static_cast(focal_chromosome->profile_unique_mutrun_total_)) * 100.0, 6, 'f', 2), menlo11_d); + tc.insertText(" of mutation run nonneutral caches rebuilt per tick\n", optima13_d); + + tc.insertText(QString("%1%").arg(((focal_chromosome->profile_mutrun_total_usage_ - focal_chromosome->profile_unique_mutrun_total_) / static_cast(focal_chromosome->profile_mutrun_total_usage_)) * 100.0, 6, 'f', 2), menlo11_d); + tc.insertText(" of mutation runs shared among haplosomes\n", optima13_d); + } } #endif @@ -4062,7 +4076,6 @@ void QtSLiMWindow::displayProfileResults(void) double average_total = (mem_tot_C.totalMemoryUsage + mem_tot_S.totalMemoryUsage) / ddiv; double final_total = mem_last_C.totalMemoryUsage + mem_last_S.totalMemoryUsage; - tc.insertText(" \n", menlo11_d); tc.insertText(" \n", optima13_d); tc.insertText("SLiM memory usage (average / final tick)\n", optima14b_d); tc.insertText(" \n", optima3_d); diff --git a/SLiMgui/SLiMWindowController.mm b/SLiMgui/SLiMWindowController.mm index d2b99ef3..4547d0ec 100644 --- a/SLiMgui/SLiMWindowController.mm +++ b/SLiMgui/SLiMWindowController.mm @@ -2059,78 +2059,92 @@ - (void)displayProfileResults continue; } - int64_t power_tallies[20]; // we only go up to 1024 mutruns right now, but this gives us some headroom - int64_t power_tallies_total = (int)focal_species->profile_mutcount_history_.size(); - - for (int power = 0; power < 20; ++power) - power_tallies[power] = 0; - - for (int32_t count : focal_species->profile_mutcount_history_) { - int power = (int)round(log2(count)); + int64_t regime_tallies[3]; + int64_t regime_tallies_total = (int)focal_species->profile_nonneutral_regime_history_.size(); - power_tallies[power]++; - } - - for (int power = 0; power < 20; ++power) - { - if (power_tallies[power] > 0) + for (int regime = 0; regime < 3; ++regime) + regime_tallies[regime] = 0; + + for (int32_t regime : focal_species->profile_nonneutral_regime_history_) + if ((regime >= 1) && (regime <= 3)) + regime_tallies[regime - 1]++; + else + regime_tallies_total--; + + for (int regime = 0; regime < 3; ++regime) { - [content eidosAppendString:[NSString stringWithFormat:@"%6.2f%%", (power_tallies[power] / (double)power_tallies_total) * 100.0] attributes:menlo11_d]; - [content eidosAppendString:[NSString stringWithFormat:@" of ticks : %d mutation runs per haplosome\n", (int)(round(pow(2.0, power)))] attributes:optima13_d]; + [content eidosAppendString:[NSString stringWithFormat:@"%6.2f%%", (regime_tallies[regime] / (double)regime_tallies_total) * 100.0] attributes:menlo11_d]; + [content eidosAppendString:[NSString stringWithFormat:@" of ticks : regime %d (%@)\n", regime + 1, (regime == 0 ? @"no mutationEffect() callbacks" : (regime == 1 ? @"constant neutral mutationEffect() callbacks only" : @"unpredictable mutationEffect() callbacks present"))] attributes:optima13_d]; } + + [content eidosAppendString:@"\n" attributes:optima8_d]; } - - int64_t regime_tallies[3]; - int64_t regime_tallies_total = (int)focal_species->profile_nonneutral_regime_history_.size(); - - for (int regime = 0; regime < 3; ++regime) - regime_tallies[regime] = 0; - - for (int32_t regime : focal_species->profile_nonneutral_regime_history_) - if ((regime >= 1) && (regime <= 3)) - regime_tallies[regime - 1]++; - else - regime_tallies_total--; - - [content eidosAppendString:@"\n" attributes:optima13_d]; - - for (int regime = 0; regime < 3; ++regime) - { - [content eidosAppendString:[NSString stringWithFormat:@"%6.2f%%", (regime_tallies[regime] / (double)regime_tallies_total) * 100.0] attributes:menlo11_d]; - [content eidosAppendString:[NSString stringWithFormat:@" of ticks : regime %d (%@)\n", regime + 1, (regime == 0 ? @"no mutationEffect() callbacks" : (regime == 1 ? @"constant neutral mutationEffect() callbacks only" : @"unpredictable mutationEffect() callbacks present"))] attributes:optima13_d]; - } - - - [content eidosAppendString:@"\n" attributes:optima13_d]; - - [content eidosAppendString:[NSString stringWithFormat:@"%lld", (long long int)focal_species->profile_mutation_total_usage_] attributes:menlo11_d]; - [content eidosAppendString:@" mutations referenced, summed across all ticks\n" attributes:optima13_d]; - - [content eidosAppendString:[NSString stringWithFormat:@"%lld", (long long int)focal_species->profile_nonneutral_mutation_total_] attributes:menlo11_d]; - [content eidosAppendString:@" mutations considered potentially nonneutral\n" attributes:optima13_d]; - - [content eidosAppendString:[NSString stringWithFormat:@"%0.2f%%", ((focal_species->profile_mutation_total_usage_ - focal_species->profile_nonneutral_mutation_total_) / (double)focal_species->profile_mutation_total_usage_) * 100.0] attributes:menlo11_d]; - [content eidosAppendString:@" of mutations excluded from fitness calculations\n" attributes:optima13_d]; - [content eidosAppendString:[NSString stringWithFormat:@"%lld", (long long int)focal_species->profile_max_mutation_index_] attributes:menlo11_d]; [content eidosAppendString:@" maximum simultaneous mutations\n" attributes:optima13_d]; - [content eidosAppendString:@"\n" attributes:optima13_d]; - - [content eidosAppendString:[NSString stringWithFormat:@"%lld", (long long int)focal_species->profile_mutrun_total_usage_] attributes:menlo11_d]; - [content eidosAppendString:@" mutation runs referenced, summed across all ticks\n" attributes:optima13_d]; - - [content eidosAppendString:[NSString stringWithFormat:@"%lld", (long long int)focal_species->profile_unique_mutrun_total_] attributes:menlo11_d]; - [content eidosAppendString:@" unique mutation runs maintained among those\n" attributes:optima13_d]; - - [content eidosAppendString:[NSString stringWithFormat:@"%6.2f%%", (focal_species->profile_mutrun_nonneutral_recache_total_ / (double)focal_species->profile_unique_mutrun_total_) * 100.0] attributes:menlo11_d]; - [content eidosAppendString:@" of mutation run nonneutral caches rebuilt per tick\n" attributes:optima13_d]; + const std::vector &chromosomes = focal_species->Chromosomes(); - [content eidosAppendString:[NSString stringWithFormat:@"%6.2f%%", ((focal_species->profile_mutrun_total_usage_ - focal_species->profile_unique_mutrun_total_) / (double)focal_species->profile_mutrun_total_usage_) * 100.0] attributes:menlo11_d]; - [content eidosAppendString:@" of mutation runs shared among haplosomes" attributes:optima13_d]; + for (Chromosome *focal_chromosome : chromosomes) + { + [content eidosAppendString:@"\n" attributes:optima13_d]; + [content eidosAppendString:@"Chromosome " attributes:optima13i_d]; + [content eidosAppendString:[NSString stringWithUTF8String:focal_chromosome->Symbol().c_str()] attributes:optima13i_d]; + [content eidosAppendString:@":\n" attributes:optima13i_d]; + [content eidosAppendString:@"\n" attributes:optima3_d]; + + { + int64_t power_tallies[20]; // we only go up to 1024 mutruns right now, but this gives us some headroom + int64_t power_tallies_total = (int)focal_chromosome->profile_mutcount_history_.size(); + + for (int power = 0; power < 20; ++power) + power_tallies[power] = 0; + + for (int32_t count : focal_chromosome->profile_mutcount_history_) + { + int power = (int)round(log2(count)); + + power_tallies[power]++; + } + + for (int power = 0; power < 20; ++power) + { + if (power_tallies[power] > 0) + { + [content eidosAppendString:[NSString stringWithFormat:@"%6.2f%%", (power_tallies[power] / (double)power_tallies_total) * 100.0] attributes:menlo11_d]; + [content eidosAppendString:[NSString stringWithFormat:@" of ticks : %d mutation runs per haplosome\n", (int)(round(pow(2.0, power)))] attributes:optima13_d]; + } + } + } + + [content eidosAppendString:@"\n" attributes:optima8_d]; + + [content eidosAppendString:[NSString stringWithFormat:@"%lld", (long long int)focal_chromosome->profile_mutation_total_usage_] attributes:menlo11_d]; + [content eidosAppendString:@" mutations referenced, summed across all ticks\n" attributes:optima13_d]; + + [content eidosAppendString:[NSString stringWithFormat:@"%lld", (long long int)focal_chromosome->profile_nonneutral_mutation_total_] attributes:menlo11_d]; + [content eidosAppendString:@" mutations considered potentially nonneutral\n" attributes:optima13_d]; + + [content eidosAppendString:[NSString stringWithFormat:@"%0.2f%%", ((focal_chromosome->profile_mutation_total_usage_ - focal_chromosome->profile_nonneutral_mutation_total_) / (double)focal_chromosome->profile_mutation_total_usage_) * 100.0] attributes:menlo11_d]; + [content eidosAppendString:@" of mutations excluded from fitness calculations\n" attributes:optima13_d]; + + + [content eidosAppendString:@"\n" attributes:optima8_d]; + + [content eidosAppendString:[NSString stringWithFormat:@"%lld", (long long int)focal_chromosome->profile_mutrun_total_usage_] attributes:menlo11_d]; + [content eidosAppendString:@" mutation runs referenced, summed across all ticks\n" attributes:optima13_d]; + + [content eidosAppendString:[NSString stringWithFormat:@"%lld", (long long int)focal_chromosome->profile_unique_mutrun_total_] attributes:menlo11_d]; + [content eidosAppendString:@" unique mutation runs maintained among those\n" attributes:optima13_d]; + + [content eidosAppendString:[NSString stringWithFormat:@"%6.2f%%", (focal_chromosome->profile_mutrun_nonneutral_recache_total_ / (double)focal_chromosome->profile_unique_mutrun_total_) * 100.0] attributes:menlo11_d]; + [content eidosAppendString:@" of mutation run nonneutral caches rebuilt per tick\n" attributes:optima13_d]; + + [content eidosAppendString:[NSString stringWithFormat:@"%6.2f%%", ((focal_chromosome->profile_mutrun_total_usage_ - focal_chromosome->profile_unique_mutrun_total_) / (double)focal_chromosome->profile_mutrun_total_usage_) * 100.0] attributes:menlo11_d]; + [content eidosAppendString:@" of mutation runs shared among haplosomes\n" attributes:optima13_d]; + } } #endif @@ -2147,7 +2161,6 @@ - (void)displayProfileResults double average_total = (mem_tot_C.totalMemoryUsage + mem_tot_S.totalMemoryUsage) / ddiv; double final_total = mem_last_C.totalMemoryUsage + mem_last_S.totalMemoryUsage; - [content eidosAppendString:@"\n" attributes:menlo11_d]; [content eidosAppendString:@"\n" attributes:optima13_d]; [content eidosAppendString:@"SLiM memory usage (average / final tick)\n" attributes:optima14b_d]; [content eidosAppendString:@"\n" attributes:optima3_d]; diff --git a/core/chromosome.h b/core/chromosome.h index 0f382aba..0770d26e 100644 --- a/core/chromosome.h +++ b/core/chromosome.h @@ -267,6 +267,18 @@ class Chromosome : public EidosDictionaryRetained // a user-defined tag value slim_usertag_t tag_value_ = SLIM_TAG_UNSET_VALUE; + // PROFILING : Chromosome keeps track of some additional profile information that is per-chromosome +#if (SLIMPROFILING == 1) +#if SLIM_USE_NONNEUTRAL_CACHES + std::vector profile_mutcount_history_; // a record of the mutation run count used in each cycle + int64_t profile_mutation_total_usage_ = 0; // how many (non-unique) mutations were used by mutation runs, summed across cycles + int64_t profile_nonneutral_mutation_total_ = 0; // of profile_mutation_total_usage_, how many were deemed to be nonneutral + int64_t profile_mutrun_total_usage_ = 0; // how many (non-unique) mutruns were used by haplosomes, summed across cycles + int64_t profile_unique_mutrun_total_ = 0; // of profile_mutrun_total_usage_, how many unique mutruns existed, summed across cycles + int64_t profile_mutrun_nonneutral_recache_total_ = 0; // of profile_unique_mutrun_total_, how many mutruns regenerated their nonneutral cache +#endif // SLIM_USE_NONNEUTRAL_CACHES +#endif // (SLIMPROFILING == 1) + Chromosome(const Chromosome&) = delete; // no copying Chromosome& operator=(const Chromosome&) = delete; // no copying Chromosome(void) = delete; // no null constructor diff --git a/core/community.cpp b/core/community.cpp index 7d5ddd6c..8cbc0928 100644 --- a/core/community.cpp +++ b/core/community.cpp @@ -3299,14 +3299,18 @@ void Community::StartProfiling(void) // zero out mutation run metrics that are collected by CollectMutationProfileInfo() for (Species *focal_species : all_species_) { - focal_species->profile_mutcount_history_.clear(); focal_species->profile_nonneutral_regime_history_.clear(); - focal_species->profile_mutation_total_usage_ = 0; - focal_species->profile_nonneutral_mutation_total_ = 0; - focal_species->profile_mutrun_total_usage_ = 0; - focal_species->profile_unique_mutrun_total_ = 0; - focal_species->profile_mutrun_nonneutral_recache_total_ = 0; focal_species->profile_max_mutation_index_ = 0; + + for (Chromosome *focal_chromosome : focal_species->Chromosomes()) + { + focal_chromosome->profile_mutcount_history_.clear(); + focal_chromosome->profile_mutation_total_usage_ = 0; + focal_chromosome->profile_nonneutral_mutation_total_ = 0; + focal_chromosome->profile_mutrun_total_usage_ = 0; + focal_chromosome->profile_unique_mutrun_total_ = 0; + focal_chromosome->profile_mutrun_nonneutral_recache_total_ = 0; + } } #endif diff --git a/core/slim_globals.cpp b/core/slim_globals.cpp index 57b572c5..426afd2b 100644 --- a/core/slim_globals.cpp +++ b/core/slim_globals.cpp @@ -2339,38 +2339,6 @@ void WriteProfileResults(std::string profile_output_path, std::string model_name continue; } - { - int64_t power_tallies[20]; // we only go up to 1024 mutruns right now, but this gives us some headroom - int64_t power_tallies_total = (int)focal_species->profile_mutcount_history_.size(); - - for (int power = 0; power < 20; ++power) - power_tallies[power] = 0; - - for (int32_t count : focal_species->profile_mutcount_history_) - { - int power = (int)round(log2(count)); - - power_tallies[power]++; - } - - fout << "

"; - bool first_line = true; - - for (int power = 0; power < 20; ++power) - { - if (power_tallies[power] > 0) - { - if (!first_line) - fout << "
\n"; - snprintf(buf, 256, "%6.2f%%", (power_tallies[power] / (double)power_tallies_total) * 100.0); - fout << "" << HTMLMakeSpacesNonBreaking(buf) << " of ticks : " << ((int)(round(pow(2.0, power)))) << " mutation runs per haplosome"; - first_line = false; - } - } - - fout << "

\n"; - } - { int64_t regime_tallies[3]; int64_t regime_tallies_total = (int)focal_species->profile_nonneutral_regime_history_.size(); @@ -2399,18 +2367,58 @@ void WriteProfileResults(std::string profile_output_path, std::string model_name fout << "

\n"; } - fout << "

" << focal_species->profile_mutation_total_usage_ << " mutations referenced, summed across all ticks
\n"; - fout << "" << focal_species->profile_nonneutral_mutation_total_ << " mutations considered potentially nonneutral
\n"; - snprintf(buf, 256, "%0.2f%%", ((focal_species->profile_mutation_total_usage_ - focal_species->profile_nonneutral_mutation_total_) / (double)focal_species->profile_mutation_total_usage_) * 100.0); - fout << "" << buf << " of mutations excluded from fitness calculations
\n"; - fout << "" << focal_species->profile_max_mutation_index_ << " maximum simultaneous mutations

\n"; - - fout << "

" << focal_species->profile_mutrun_total_usage_ << " mutation runs referenced, summed across all ticks
\n"; - fout << "" << focal_species->profile_unique_mutrun_total_ << " unique mutation runs maintained among those
\n"; - snprintf(buf, 256, "%6.2f%%", (focal_species->profile_mutrun_nonneutral_recache_total_ / (double)focal_species->profile_unique_mutrun_total_) * 100.0); - fout << "" << HTMLMakeSpacesNonBreaking(buf) << " of mutation run nonneutral caches rebuilt per tick
\n"; - snprintf(buf, 256, "%6.2f%%", ((focal_species->profile_mutrun_total_usage_ - focal_species->profile_unique_mutrun_total_) / (double)focal_species->profile_mutrun_total_usage_) * 100.0); - fout << "" << HTMLMakeSpacesNonBreaking(buf) << " of mutation runs shared among haplosomes

\n\n"; + fout << "

" << focal_species->profile_max_mutation_index_ << " maximum simultaneous mutations

\n"; + + const std::vector &chromosomes = focal_species->Chromosomes(); + + for (Chromosome *focal_chromosome : chromosomes) + { + fout << "

Chromosome " << focal_chromosome->Symbol() << ":

\n"; + + { + int64_t power_tallies[20]; // we only go up to 1024 mutruns right now, but this gives us some headroom + int64_t power_tallies_total = (int)focal_chromosome->profile_mutcount_history_.size(); + + for (int power = 0; power < 20; ++power) + power_tallies[power] = 0; + + for (int32_t count : focal_chromosome->profile_mutcount_history_) + { + int power = (int)round(log2(count)); + + power_tallies[power]++; + } + + fout << "

"; + bool first_line = true; + + for (int power = 0; power < 20; ++power) + { + if (power_tallies[power] > 0) + { + if (!first_line) + fout << "
\n"; + snprintf(buf, 256, "%6.2f%%", (power_tallies[power] / (double)power_tallies_total) * 100.0); + fout << "" << HTMLMakeSpacesNonBreaking(buf) << " of ticks : " << ((int)(round(pow(2.0, power)))) << " mutation runs per haplosome"; + first_line = false; + } + } + + fout << "

\n"; + } + + fout << "

" << focal_chromosome->profile_mutation_total_usage_ << " mutations referenced, summed across all ticks
\n"; + fout << "" << focal_chromosome->profile_nonneutral_mutation_total_ << " mutations considered potentially nonneutral
\n"; + snprintf(buf, 256, "%0.2f%%", ((focal_chromosome->profile_mutation_total_usage_ - focal_chromosome->profile_nonneutral_mutation_total_) / (double)focal_chromosome->profile_mutation_total_usage_) * 100.0); + fout << "" << buf << " of mutations excluded from fitness calculations

\n"; + + fout << "

" << focal_chromosome->profile_mutrun_total_usage_ << " mutation runs referenced, summed across all ticks
\n"; + fout << "" << focal_chromosome->profile_unique_mutrun_total_ << " unique mutation runs maintained among those
\n"; + snprintf(buf, 256, "%6.2f%%", (focal_chromosome->profile_mutrun_nonneutral_recache_total_ / (double)focal_chromosome->profile_unique_mutrun_total_) * 100.0); + fout << "" << HTMLMakeSpacesNonBreaking(buf) << " of mutation run nonneutral caches rebuilt per tick
\n"; + snprintf(buf, 256, "%6.2f%%", ((focal_chromosome->profile_mutrun_total_usage_ - focal_chromosome->profile_unique_mutrun_total_) / (double)focal_chromosome->profile_mutrun_total_usage_) * 100.0); + fout << "" << HTMLMakeSpacesNonBreaking(buf) << " of mutation runs shared among haplosomes

\n\n"; + } } #endif diff --git a/core/species.cpp b/core/species.cpp index 931f6326..7ea17a4b 100644 --- a/core/species.cpp +++ b/core/species.cpp @@ -3307,14 +3307,7 @@ void Species::ReturnShuffleBuffer(void) #if SLIM_USE_NONNEUTRAL_CACHES void Species::CollectMutationProfileInfo(void) { - // FIXME MULTICHROM this profile info should be moved to be per-chromosome; for now, we protect against not having a chromosome - if (chromosomes_.size() == 0) - return; - - Chromosome &chromosome = TheChromosome(); // only keeping the history for the first chromosome right now, should keep it for all - - // maintain our history of the number of mutruns per haplosome and the nonneutral regime - profile_mutcount_history_.emplace_back(chromosome.mutrun_count_); + // maintain our history of the nonneutral regime profile_nonneutral_regime_history_.emplace_back(last_nonneutral_regime_); // track the maximum number of mutations in existence at one time @@ -3323,46 +3316,56 @@ void Species::CollectMutationProfileInfo(void) population_.MutationRegistry(®istry_size); profile_max_mutation_index_ = std::max(profile_max_mutation_index_, (int64_t)registry_size); - // tally up the number of mutation runs, mutation usage metrics, etc. - int haplosome_count_per_individual = HaplosomeCountPerIndividual(); + // tally per-chromosome information int64_t operation_id = MutationRun::GetNextOperationID(); - for (std::pair &subpop_pair : population_.subpops_) + for (Chromosome *chromosome : Chromosomes()) { - Subpopulation *subpop = subpop_pair.second; + int first_haplosome_index = FirstHaplosomeIndices()[chromosome->Index()]; + int last_haplosome_index = LastHaplosomeIndices()[chromosome->Index()]; + + // maintain our history of the number of mutruns per haplosome + chromosome->profile_mutcount_history_.emplace_back(chromosome->mutrun_count_); - for (Individual *ind : subpop->parent_individuals_) - { - Haplosome **haplosomes = ind->haplosomes_; - - for (int haplosome_index = 0; haplosome_index < haplosome_count_per_individual; haplosome_index++) - { - Haplosome *haplosome = haplosomes[haplosome_index]; - - const MutationRun **mutruns = haplosome->mutruns_; - int32_t mutrun_count = haplosome->mutrun_count_; - - profile_mutrun_total_usage_ += mutrun_count; - - for (int32_t mutrun_index = 0; mutrun_index < mutrun_count; ++mutrun_index) - { - const MutationRun *mutrun = mutruns[mutrun_index]; - - if (mutrun) - { - if (mutrun->operation_id_ != operation_id) - { - mutrun->operation_id_ = operation_id; - profile_unique_mutrun_total_++; - } - - // tally the total and nonneutral mutations - mutrun->tally_nonneutral_mutations(&profile_mutation_total_usage_, &profile_nonneutral_mutation_total_, &profile_mutrun_nonneutral_recache_total_); - } - } - } - } - } + // tally up the number of mutation runs, mutation usage metrics, etc. + for (std::pair &subpop_pair : population_.subpops_) + { + Subpopulation *subpop = subpop_pair.second; + + for (Individual *ind : subpop->parent_individuals_) + { + Haplosome **haplosomes = ind->haplosomes_; + + for (int haplosome_index = first_haplosome_index; haplosome_index <= last_haplosome_index; haplosome_index++) + { + Haplosome *haplosome = haplosomes[haplosome_index]; + const MutationRun **mutruns = haplosome->mutruns_; + int32_t mutrun_count = haplosome->mutrun_count_; + + chromosome->profile_mutrun_total_usage_ += mutrun_count; + + for (int32_t mutrun_index = 0; mutrun_index < mutrun_count; ++mutrun_index) + { + const MutationRun *mutrun = mutruns[mutrun_index]; + + if (mutrun) + { + if (mutrun->operation_id_ != operation_id) + { + mutrun->operation_id_ = operation_id; + chromosome->profile_unique_mutrun_total_++; + } + + // tally the total and nonneutral mutations + mutrun->tally_nonneutral_mutations(&chromosome->profile_mutation_total_usage_, + &chromosome->profile_nonneutral_mutation_total_, + &chromosome->profile_mutrun_nonneutral_recache_total_); + } + } + } + } + } + } } #endif #endif diff --git a/core/species.h b/core/species.h index c1849192..d1b2c306 100644 --- a/core/species.h +++ b/core/species.h @@ -383,17 +383,12 @@ class Species : public EidosDictionaryUnretained #if (SLIMPROFILING == 1) // PROFILING : Species keeps track of its memory usage profile info and mutation-related profile info + // BCH 11/24/2024: Note that Chromosome now keeps additional profile information that is per-chromosome SLiMMemoryUsage_Species profile_last_memory_usage_Species; SLiMMemoryUsage_Species profile_total_memory_usage_Species; #if SLIM_USE_NONNEUTRAL_CACHES - std::vector profile_mutcount_history_; // a record of the mutation run count used in each cycle std::vector profile_nonneutral_regime_history_; // a record of the nonneutral regime used in each cycle - int64_t profile_mutation_total_usage_; // how many (non-unique) mutations were used by mutation runs, summed across cycles - int64_t profile_nonneutral_mutation_total_; // of profile_mutation_total_usage_, how many were deemed to be nonneutral - int64_t profile_mutrun_total_usage_; // how many (non-unique) mutruns were used by haplosomes, summed across cycles - int64_t profile_unique_mutrun_total_; // of profile_mutrun_total_usage_, how many unique mutruns existed, summed across cycles - int64_t profile_mutrun_nonneutral_recache_total_; // of profile_unique_mutrun_total_, how many mutruns regenerated their nonneutral cache int64_t profile_max_mutation_index_; // the largest mutation index seen over the course of the profile #endif // SLIM_USE_NONNEUTRAL_CACHES #endif // (SLIMPROFILING == 1) diff --git a/core/species_eidos.cpp b/core/species_eidos.cpp index 510a4297..7bf9f1a1 100644 --- a/core/species_eidos.cpp +++ b/core/species_eidos.cpp @@ -3399,7 +3399,7 @@ EidosValue_SP Species::ExecuteMethod_subsetMutations(EidosGlobalStringID p_metho EIDOS_TERMINATION << "ERROR (Species::ExecuteMethod_subsetMutations): (internal error) chromosome lookup failed." << EidosTerminate(); chromosome = chromosomes_[chromosome_indices[0]]; - chromosome_index = chromosome->index_; + chromosome_index = chromosome->Index(); } // SPECIES CONSISTENCY CHECK