Skip to content

Commit

Permalink
clean up a CI build error, begin work on addMultiRecombinant()
Browse files Browse the repository at this point in the history
  • Loading branch information
bhaller committed Jan 4, 2025
1 parent 7b0a1fd commit f56aaaf
Show file tree
Hide file tree
Showing 22 changed files with 218 additions and 93 deletions.
1 change: 1 addition & 0 deletions EidosScribe/EidosHelpController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1263,6 +1263,7 @@ - (void)drawRow:(NSInteger)rowIndex clipRect:(NSRect)clipRect
@"\u00A0addCloned()",
@"\u00A0addCrossed()",
@"\u00A0addEmpty()",
@"\u00A0addMultiRecombinant()",
@"\u00A0addRecombinant()",
@"\u00A0addSelfed()",
@"\u00A0removeSubpopulation()",
Expand Down
2 changes: 1 addition & 1 deletion PARALLEL
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ PARALLEL changes (now in the master branch, but disabled):
add support for parallel reproduction when a non-default stacking policy is in use
add support for parallel reproduction with tree-sequence recording
add parallel reproduction in nonWF models, with no callbacks (recombination(), mutation()) active - modifyChild() callbacks are legal but cannot access child haplosomes since they are deferred
this is achieved by passing defer=T to addCrossed(), addCloned(), addSelfed(), or addRecombinant()
this is achieved by passing defer=T to addCrossed(), addCloned(), addSelfed(), addMultiRecombinant(), or addRecombinant()
thread-safety work - break in backward reproducibility for scripts that use a type 's' DFE, because the code path for that shifted
algorithm change for nearestNeighbors() and nearestNeighborsOfPoint(), when count is >1 and <N; the old algorithm was not thread-safe, and was inefficient; breaks backward reproducibility for the relevant case
the break in backward reproducibility is because the old algorithm returned the neighbors in a scrambled order, whereas the new algorithm returns them in sorted order; the order is not documented, so both are compliant
Expand Down
4 changes: 1 addition & 3 deletions QtSLiM/QtSLiMChromosomeWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -646,10 +646,8 @@ Chromosome *QtSLiMChromosomeWidget::focalChromosome(void)
}
else if (focalSpecies->Chromosomes().size() == 1)
{
Chromosome *chromosome = focalSpecies->Chromosomes()[0];

chromosome = focalSpecies->Chromosomes()[0];
focalChromosomeSymbol_ = chromosome->Symbol();
return chromosome;
}
}

Expand Down
8 changes: 4 additions & 4 deletions QtSLiM/QtSLiMChromosomeWidget_GL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ void QtSLiMChromosomeWidget::glDrawMutations(QRect &interiorRect, Chromosome *ch
EIDOS_BZERO(heightBuffer, static_cast<size_t>(displayPixelWidth) * sizeof(int16_t));

// Scan through the mutation list for mutations of this type with the right selcoeff
for (int mutation_index = 0; mutation_index < mutations.size(); ++mutation_index)
for (int mutation_index = 0; mutation_index < (int)mutations.size(); ++mutation_index)
{
const Mutation *mutation = mutations[mutation_index];

Expand Down Expand Up @@ -333,7 +333,7 @@ void QtSLiMChromosomeWidget::glDrawMutations(QRect &interiorRect, Chromosome *ch
else
{
// We're not displaying this mutation type, so we need to mark off all the mutations belonging to it as handled
for (int mutation_index = 0; mutation_index < mutations.size(); ++mutation_index)
for (int mutation_index = 0; mutation_index < (int)mutations.size(); ++mutation_index)
{
const Mutation *mutation = mutations[mutation_index];

Expand All @@ -354,7 +354,7 @@ void QtSLiMChromosomeWidget::glDrawMutations(QRect &interiorRect, Chromosome *ch
if (remainingMutations < 1000)
{
// Plot the remainder by brute force, since there are not that many
for (int mutation_index = 0; mutation_index < mutations.size(); ++mutation_index)
for (int mutation_index = 0; mutation_index < (int)mutations.size(); ++mutation_index)
{
//if (mutation->gui_scratch_reference_count_ == 0)
if (!mutationsPlotted[mutation_index])
Expand Down Expand Up @@ -383,7 +383,7 @@ void QtSLiMChromosomeWidget::glDrawMutations(QRect &interiorRect, Chromosome *ch
EIDOS_BZERO(heightBuffer, static_cast<size_t>(displayPixelWidth) * sizeof(int16_t));

// Find the tallest bar in each column
for (int mutation_index = 0; mutation_index < mutations.size(); ++mutation_index)
for (int mutation_index = 0; mutation_index < (int)mutations.size(); ++mutation_index)
{
//if (mutation->gui_scratch_reference_count_ == 0)
if (!mutationsPlotted[mutation_index])
Expand Down
9 changes: 4 additions & 5 deletions QtSLiM/QtSLiMChromosomeWidget_QT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ void QtSLiMChromosomeWidget::qtDrawMutations(QRect &interiorRect, Chromosome *ch
EIDOS_BZERO(heightBuffer, static_cast<size_t>(displayPixelWidth) * sizeof(int16_t));

// Scan through the mutation list for mutations of this type with the right selcoeff
for (int mutation_index = 0; mutation_index < mutations.size(); ++mutation_index)
for (int mutation_index = 0; mutation_index < (int)mutations.size(); ++mutation_index)
{
const Mutation *mutation = mutations[mutation_index];

Expand Down Expand Up @@ -329,7 +329,7 @@ void QtSLiMChromosomeWidget::qtDrawMutations(QRect &interiorRect, Chromosome *ch
else
{
// We're not displaying this mutation type, so we need to mark off all the mutations belonging to it as handled
for (int mutation_index = 0; mutation_index < mutations.size(); ++mutation_index)
for (int mutation_index = 0; mutation_index < (int)mutations.size(); ++mutation_index)
{
const Mutation *mutation = mutations[mutation_index];

Expand All @@ -350,7 +350,7 @@ void QtSLiMChromosomeWidget::qtDrawMutations(QRect &interiorRect, Chromosome *ch
if (remainingMutations < 1000)
{
// Plot the remainder by brute force, since there are not that many
for (int mutation_index = 0; mutation_index < mutations.size(); ++mutation_index)
for (int mutation_index = 0; mutation_index < (int)mutations.size(); ++mutation_index)
{
//if (mutation->gui_scratch_reference_count_ == 0)
if (!mutationsPlotted[mutation_index])
Expand Down Expand Up @@ -379,7 +379,7 @@ void QtSLiMChromosomeWidget::qtDrawMutations(QRect &interiorRect, Chromosome *ch
EIDOS_BZERO(heightBuffer, static_cast<size_t>(displayPixelWidth) * sizeof(int16_t));

// Find the tallest bar in each column
for (int mutation_index = 0; mutation_index < mutations.size(); ++mutation_index)
for (int mutation_index = 0; mutation_index < (int)mutations.size(); ++mutation_index)
{
//if (mutation->gui_scratch_reference_count_ == 0)
if (!mutationsPlotted[mutation_index])
Expand Down Expand Up @@ -707,7 +707,6 @@ void QtSLiMChromosomeWidget::qtDrawMutationIntervals(QRect &interiorRect, Chromo

void QtSLiMChromosomeWidget::qtDrawRateMaps(QRect &interiorRect, Chromosome *chromosome, QtSLiMRange displayedRange, QPainter &painter)
{
Species *displaySpecies = &chromosome->species_;
bool recombinationWorthShowing = false;
bool mutationWorthShowing = false;

Expand Down
3 changes: 1 addition & 2 deletions QtSLiM/QtSLiMHaplotypeManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,10 @@ void QtSLiMHaplotypeManager::CreateHaplotypePlot(QtSLiMChromosomeWidgetControlle
}

// then create and install the haplotype managers, one by one; each will display once it is completed
for (int index = 0; index < chromosomes.size(); ++index)
for (int index = 0; index < (int)chromosomes.size(); ++index)
{
Chromosome *chromosome = chromosomes[index];
QtSLiMHaplotypeView *haplotypeView = haplotypeViews[index];
size_t haplosomeSampleSize = optionsPanel.haplosomeSampleSize();

// First generate the haplotype plot data, with a progress panel
QtSLiMHaplotypeManager *haplotypeManager = new QtSLiMHaplotypeManager(nullptr, clusteringMethod, clusteringOptimization, controller,
Expand Down
1 change: 1 addition & 0 deletions QtSLiM/QtSLiMHelpWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ void QtSLiMHelpOutlineDelegate::paint(QPainter *painter, const QStyleOptionViewI
"– addCloned()",
"– addCrossed()",
"– addEmpty()",
"– addMultiRecombinant()",
"– addRecombinant()",
"– addSelfed()",
"– removeSubpopulation()",
Expand Down
4 changes: 1 addition & 3 deletions QtSLiM/QtSLiMWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2988,8 +2988,6 @@ void QtSLiMWindow::updateUIEnabling(void)
ui->browserButton->setEnabled(true);
ui->jumpToPopupButton->setEnabled(true);

Species *species = focalDisplaySpecies();

ui->chromosomeActionButton->setEnabled(!invalidSimulation_);
ui->chromosomeDisplayButton->setEnabled(!invalidSimulation_);
ui->clearOutputButton->setEnabled(!invalidSimulation_);
Expand Down Expand Up @@ -5234,7 +5232,7 @@ void QtSLiMWindow::chromosomeDisplayPopupButtonRunMenu(void)

QAction *chromAction = contextMenu.addAction(menuItemTitle);

chromAction->setData(chrom->ID()); // we use the ID temporarily, to run the menu, but the symbol will be the actual key
chromAction->setData(QVariant::fromValue(chrom->ID())); // we use the ID temporarily, to run the menu, but the symbol will be the actual key
chromAction->setEnabled(!disableAll);
}

Expand Down
2 changes: 1 addition & 1 deletion QtSLiM/help/SLiMHelpCallbacks.html
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@
<p class="p2">The callback may perform a variety of actions related to the generated mutation.<span class="Apple-converted-space">  </span>The selection coefficient of the mutation can be changed with <span class="s1">setSelectionCoefficient()</span>, and the mutation type of the mutation can be changed with <span class="s1">setMutationType()</span>; the <span class="s1">drawSelectionCoefficient()</span> method of <span class="s1">MutationType</span> may also be useful here.<span class="Apple-converted-space">  </span>A <span class="s1">tag</span> property value may be set for the mutation, and named values may be attached to the mutation with <span class="s1">setValue()</span>.<span class="Apple-converted-space">  </span>In nucleotide-based models, the <span class="s1">nucleotide</span> (or <span class="s1">nucleotideValue</span>) property of the mutation may also be changed; note that the original nucleotide at the focal position in the parental haplosome is provided through <span class="s1">originalNuc</span> (it could be retrieved with <span class="s1">haplosome.nucleotides()</span>, but SLiM already has it at hand anyway).<span class="Apple-converted-space">  </span>All of these modifications to the new mutation may be based upon the state of the parent, including its genetic state, or upon any other model state.</p>
<p class="p2">It is possible, of course, to do actions unrelated to mutation inside <span class="s1">mutation()</span> callbacks, but it is not recommended; <span class="s1">first()</span>, <span class="s1">early()</span>, and <span class="s1">late()</span> events should be used for general-purpose scripting.<span class="Apple-converted-space">  </span>Besides providing conceptual clarity, following this design principle will also decrease the probability of bugs, since actions that are unrelated to mutation should not influence or be influenced by the dynamics of mutation.</p>
<p class="p2">The proposed mutation will not appear in the <span class="s1">sim.mutations</span> vector of segregating mutations until it has been added to a haplosome; it will therefore not be visible in that vector within its own <span class="s1">mutation()</span> callback invocation, and indeed, may not be visible in subsequent callbacks during the reproduction tick cycle stage until such time as the offspring individual being generated has been completed.<span class="Apple-converted-space">  </span>If that offspring is ultimately rejected, in particular by a <span class="s1">modifyChild()</span> callback, the proposed mutation may not be used by SLiM at all.<span class="Apple-converted-space">  </span>It may therefore be unwise to assume, in a <span class="s1">mutation()</span> callback, that the focal mutation will ultimately be added to the simulation, depending upon the rest of the model’s script.</p>
<p class="p2">There is one subtlety to be mentioned here, having to do with subpopulations.<span class="Apple-converted-space">  </span>The <span class="s1">subpop</span> pseudo-parameter discussed above is always the subpopulation of the parent which possesses the haplosome that is being copied and is mutating; there is no ambiguity about that whatsoever.<span class="Apple-converted-space">  </span>The <span class="s1">&lt;subpop-id&gt;</span> specified in the <span class="s1">mutation()</span> callback declaration, however, is a bit more subtle; above it was said that it restricts the callback “to individuals generated by a specified subpopulation”, and that is usually true but requires some explanation.<span class="Apple-converted-space">  </span>In WF models, recall that migrants are generated in a source subpopulation and placed in a target subpopulation, as a model of juvenile migration; in that context, the <span class="s1">&lt;subpop-id&gt;</span> specifies the <i>source</i> subpopulation to which the <span class="s1">mutation()</span> callback will be restricted.<span class="Apple-converted-space">  </span>In nonWF models, offspring are generated by the <span class="s1">add...()</span> family of <span class="s1">Subpopulation</span> methods, which can cross individuals from two different subpopulations and place the result in a third target subpopulation; in that context, in general, the <span class="s1">&lt;subpop-id&gt;</span> specifies the source subpopulation that is generating the particular <i>gamete</i> that is sustaining a mutation during its production.<span class="Apple-converted-space">  </span>The exception to this rule is <span class="s1">addRecombinant()</span>; since there are four different source subpopulations potentially in play there, it was deemed simpler in that case for the <span class="s1">&lt;subpop-id&gt;</span> to specify the <i>target</i> subpopulation to which the <span class="s1">mutation()</span> callback will be restricted.<span class="Apple-converted-space">  </span>If restriction to the source subpopulation is needed with <span class="s1">addRecombinant()</span>, the <span class="s1">subpop</span> pseudo-parameter may be consulted rather than using <span class="s1">&lt;subpop-id&gt;</span>.</p>
<p class="p2">There is one subtlety to be mentioned here, having to do with subpopulations.<span class="Apple-converted-space">  </span>The <span class="s1">subpop</span> pseudo-parameter discussed above is always the subpopulation of the parent which possesses the haplosome that is being copied and is mutating; there is no ambiguity about that whatsoever.<span class="Apple-converted-space">  </span>The <span class="s1">&lt;subpop-id&gt;</span> specified in the <span class="s1">mutation()</span> callback declaration, however, is a bit more subtle; above it was said that it restricts the callback “to individuals generated by a specified subpopulation”, and that is usually true but requires some explanation.<span class="Apple-converted-space">  </span>In WF models, recall that migrants are generated in a source subpopulation and placed in a target subpopulation, as a model of juvenile migration; in that context, the <span class="s1">&lt;subpop-id&gt;</span> specifies the <i>source</i> subpopulation to which the <span class="s1">mutation()</span> callback will be restricted.<span class="Apple-converted-space">  </span>In nonWF models, offspring are generated by the <span class="s1">add...()</span> family of <span class="s1">Subpopulation</span> methods, which can cross individuals from two different subpopulations and place the result in a third target subpopulation; in that context, in general, the <span class="s1">&lt;subpop-id&gt;</span> specifies the source subpopulation that is generating the particular <i>gamete</i> that is sustaining a mutation during its production.<span class="Apple-converted-space">  </span>The exception to this rule is <span class="s1">addRecombinant()</span> and <span class="s1">addMultiRecombinant()</span>; since there are four different source subpopulations potentially in play there per mutation, it was deemed simpler in that case for the <span class="s1">&lt;subpop-id&gt;</span> to specify the <i>target</i> subpopulation to which the <span class="s1">mutation()</span> callback will be restricted.<span class="Apple-converted-space">  </span>If restriction to the source subpopulation is needed with <span class="s1">addRecombinant()</span> or <span class="s1">addMultiRecombinant()</span>, the <span class="s1">subpop</span> pseudo-parameter may be consulted rather than using <span class="s1">&lt;subpop-id&gt;</span>.</p>
<p class="p2">Note that <span class="s1">mutation()</span> callbacks are only called for mutations that are auto-generated by SLiM, as a consequence of the mutation rate and the genetic structure defined.<span class="Apple-converted-space">  </span>Mutations that are created in script, using <span class="s1">addNewMutation()</span> or <span class="s1">addNewDrawnMutation()</span>, will not trigger <span class="s1">mutation()</span> callbacks; but of course the script may modify or tailor such added mutations in whatever way is desired, so there is no need for callbacks in that situation.</p>
<p class="p2">As with the other callback types, multiple <span class="s1">mutation()</span> callbacks may be registered and active.<span class="Apple-converted-space">  </span>In this case, all registered and active callbacks will be called for each generated mutation to which they apply, in the order that the callbacks were registered.</p>
<p class="p1"><i>5.13.10<span class="Apple-converted-space">  </span>ITEM: 11. </i><span class="s1"><i>survival()</i></span><i> callbacks</i></p>
Expand Down
Loading

0 comments on commit f56aaaf

Please sign in to comment.