5.2 Class Chromosome
5.2.1 Chromosome properties
colorSubstitution <–> (string$)
The color used to display substitutions in SLiMgui when both mutations and substitutions are being displayed in the chromosome view. Outside of SLiMgui, this property still exists, but is not used by SLiM. Colors may be specified by name, or with hexadecimal RGB values of the form "#RRGGBB". If colorSubstitution is the empty string, "", SLiMgui will defer to the color scheme of each MutationType, just as it does when only substitutions are being displayed. The default, "3333FF", causes all substitutions to be shown as dark blue when displayed in conjunction with mutations, to prevent the view from becoming too noisy. Note that when substitutions are displayed without mutations also being displayed, this value is ignored by SLiMgui and the substitutions use the color scheme of each MutationType.
geneConversionEnabled => (logical$)
When gene conversion has been enabled by calling initializeGeneConversion(), switching to the DSB recombination model, this property is T; otherwise, when using the crossover breakpoints model, it is F.
geneConversionGCBias => (float$)
The gene conversion bias coefficient, which expresses a bias in the resolution of heteroduplex mismatches in complex gene conversion tracts. When gene conversion has not been enabled by calling initializeGeneConversion(), this property will be unavailable.
geneConversionNonCrossoverFraction => (float$)
The fraction of double-stranded breaks that result in non-crossover events. When gene conversion has not been enabled by calling initializeGeneConversion(), this property will be unavailable.
geneConversionMeanLength => (float$)
The mean length of a gene conversion tract (in base positions). When gene conversion has not been enabled by calling initializeGeneConversion(), this property will be unavailable.
geneConversionSimpleConversionFraction => (float$)
The fraction of gene conversion tracts that are “simple” (i.e., not involving resolution of heteroduplex mismatches); the remainder will be “complex”. When gene conversion has not been enabled by calling initializeGeneConversion(), this property will be unavailable.
genomicElements => (object<GenomicElement>)
All of the GenomicElement objects that comprise the chromosome.
hotspotEndPositions => (integer)
The end positions for hotspot map regions along the chromosome. Each hotspot map region is assumed to start at the position following the end of the previous hotspot map region; in other words, the regions are assumed to be contiguous. When using sex-specific hotspot maps, this property will unavailable; see hotspotEndPositionsF and hotspotEndPositionsM.
hotspotEndPositionsF => (integer)
The end positions for hotspot map regions for females, when using sex-specific hotspot maps; unavailable otherwise. See hotspotEndPositions for further explanation.
hotspotEndPositionsM => (integer)
The end positions for hotspot map regions for males, when using sex-specific hotspot maps; unavailable otherwise. See hotspotEndPositions for further explanation.
hotspotMultipliers => (float)
The hotspot multiplier for each of the hotspot map regions specified by hotspotEndPositions. When using sex-specific hotspot maps, this property will be unavailable; see hotspotMultipliersF and hotspotMultipliersM.
hotspotMultipliersF => (float)
The hotspot multiplier for each of the hotspot map regions specified by hotspotEndPositionsF, when using sex-specific hotspot maps; unavailable otherwise.
hotspotMultipliersM => (float)
The hotspot multiplier for each of the hotspot map regions specified by hotspotEndPositionsM, when using sex-specific hotspot maps; unavailable otherwise.
lastPosition => (integer$)
The last valid position in the chromosome; its length, essentially. Note that the chromosome length is determined by the maximum of the end of the last genomic element, the end of the last recombination region, and the end of the last mutation map region (or hotspot map region).
mutationEndPositions => (integer)
The end positions for mutation rate regions along the chromosome. Each mutation rate region is assumed to start at the position following the end of the previous mutation rate region; in other words, the regions are assumed to be contiguous. When using sex-specific mutation rate maps, this property will unavailable; see mutationEndPositionsF and mutationEndPositionsM.
This property is unavailable in nucleotide-based models.
mutationEndPositionsF => (integer)
The end positions for mutation rate regions for females, when using sex-specific mutation rate maps; unavailable otherwise. See mutationEndPositions for further explanation.
This property is unavailable in nucleotide-based models.
mutationEndPositionsM => (integer)
The end positions for mutation rate regions for males, when using sex-specific mutation rate maps; unavailable otherwise. See mutationEndPositions for further explanation.
This property is unavailable in nucleotide-based models.
mutationRates => (float)
The mutation rate for each of the mutation rate regions specified by mutationEndPositions. When using sex-specific mutation rate maps, this property will be unavailable; see mutationRatesF and mutationRatesM.
This property is unavailable in nucleotide-based models.
mutationRatesF => (float)
The mutation rate for each of the mutation rate regions specified by mutationEndPositionsF, when using sex-specific mutation rate maps; unavailable otherwise.
This property is unavailable in nucleotide-based models.
mutationRatesM => (float)
The mutation rate for each of the mutation rate regions specified by mutationEndPositionsM, when using sex-specific mutation rate maps; unavailable otherwise.
This property is unavailable in nucleotide-based models.
overallMutationRate => (float$)
The overall mutation rate across the whole chromosome determining the overall number of mutation events that will occur anywhere in the chromosome, as calculated from the individual mutation ranges and rates as well as the coverage of the chromosome by genomic elements (since mutations are only generated within genomic elements, regardless of the mutation rate map). When using sex-specific mutation rate maps, this property will unavailable; see overallMutationRateF and overallMutationRateM.
This property is unavailable in nucleotide-based models.
overallMutationRateF => (float$)
The overall mutation rate for females, when using sex-specific mutation rate maps; unavailable otherwise. See overallMutationRate for further explanation.
This property is unavailable in nucleotide-based models.
overallMutationRateM => (float$)
The overall mutation rate for males, when using sex-specific mutation rate maps; unavailable otherwise. See overallMutationRate for further explanation.
This property is unavailable in nucleotide-based models.
overallRecombinationRate => (float$)
The overall recombination rate across the whole chromosome determining the overall number of recombination events that will occur anywhere in the chromosome, as calculated from the individual recombination ranges and rates. When using sex-specific recombination maps, this property will unavailable; see overallRecombinationRateF and overallRecombinationRateM.
overallRecombinationRateF => (float$)
The overall recombination rate for females, when using sex-specific recombination maps; unavailable otherwise. See overallRecombinationRate for further explanation.
overallRecombinationRateM => (float$)
The overall recombination rate for males, when using sex-specific recombination maps; unavailable otherwise. See overallRecombinationRate for further explanation.
recombinationEndPositions => (integer)
The end positions for recombination regions along the chromosome. Each recombination region is assumed to start at the position following the end of the previous recombination region; in other words, the regions are assumed to be contiguous. When using sex-specific recombination maps, this property will unavailable; see recombinationEndPositionsF and recombinationEndPositionsM.
recombinationEndPositionsF => (integer)
The end positions for recombination regions for females, when using sex-specific recombination maps; unavailable otherwise. See recombinationEndPositions for further explanation.
recombinationEndPositionsM => (integer)
The end positions for recombination regions for males, when using sex-specific recombination maps; unavailable otherwise. See recombinationEndPositions for further explanation.
recombinationRates => (float)
The recombination rate for each of the recombination regions specified by recombinationEndPositions. When using sex-specific recombination maps, this property will unavailable; see recombinationRatesF and recombinationRatesM.
recombinationRatesF => (float)
The recombination rate for each of the recombination regions specified by recombinationEndPositionsF, when using sex-specific recombination maps; unavailable otherwise.
recombinationRatesM => (float)
The recombination rate for each of the recombination regions specified by recombinationEndPositionsM, when using sex-specific recombination maps; unavailable otherwise.
species => (object<Species>$)
The species to which the target object belongs.
tag <–> (integer$)
A user-defined integer value. The value of tag is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tag is not used by SLiM; it is free for you to use.
5.2.2 Chromosome methods
– (is)ancestralNucleotides([Ni$ start = NULL], [Ni$ end = NULL], [string$ format = "string"])
Returns the ancestral nucleotide sequence originally supplied to initializeAncestralNucleotides(), including any sequence changes due to nucleotide mutations that have fixed and substituted. This nucleotide sequence is the reference sequence for positions in a genome that do not contain a nucleotide-based mutation. The range of the returned sequence may be constrained by a start position given in start and/or an end position given in end; nucleotides will be returned from start to end, inclusive. The default value of NULL for start and end represent the first and last base positions of the chromosome, respectively.
The format of the returned sequence is controlled by the format parameter. A format of "string" will return the sequence as a singleton string (e.g., "TATA"). A format of "char" will return a string vector with one element per nucleotide (e.g., "T", "A", "T", "A"). A format of "integer" will return an integer vector with values A=0, C=1, G=2, T=3 (e.g., 3, 0, 3, 0). If the sequence returned is likely to be long, the "string" format will be the most memory-efficient, and may also be the fastest (but may be harder to work with).
For purposes related to interpreting the nucleotide sequence as a coding sequence, a format of "codon" is also supported. This format will return an integer vector with values from 0 to 63, based upon successive nucleotide triplets in the sequence (which, for this format, must have a length that is a multiple of three). The codon value for a given nucleotide triplet XYZ is 16X + 4Y + Z, where X, Y, and Z have the usual values A=0, C=1, G=2, T=3. For example, the triplet AAA has a codon value of 0, AAC is 1, AAG is 2, AAT is 3, ACA is 4, and on upward to TTT which is 63. If the nucleotide sequence AACACATTT is requested in codon format, the codon vector 1 4 63 will therefore be returned. These codon values can be useful in themselves; they can also be passed to codonToAminoAcid() to translate them into the corresponding amino acid sequence if desired.
– (integer)drawBreakpoints([No<Individual>$ parent = NULL], [Ni$ n = NULL])
Draw recombination breakpoints, using the chromosome’s recombination rate map, the current gene conversion parameters, and (in some cases – see below) any active and applicable recombination() callbacks. The number of breakpoints to generate, n, may be supplied; if it is NULL (the default), the number of breakpoints will be drawn based upon the overall recombination rate and the chromosome length (following the standard procedure in SLiM). Note that if the double-stranded breaks model has been chosen, the number of breakpoints generated will probably not be equal to the number requested, because most breakpoints will entail gene conversion tracts, which entail additional crossover breakpoints.
It is generally recommended that the parent individual be supplied to this method, but parent is NULL by default. The individual supplied in parent is used for two purposes. First, in sexual models that define separate recombination rate maps for males versus females, the sex of parent will be used to determine which map is used; in this case, a non-NULL value must be supplied for parent, since the choice of recombination rate map must be determined. Second, in models that define recombination() callbacks, parent is used to determine the various pseudo-parameters that are passed to recombination() callbacks (individual, genome1, genome2, subpop), and the subpopulation to which parent belongs is used to select which recombination() callbacks are applicable; given the necessity of this information, recombination() callbacks will not be called as a side effect of this method if parent is NULL. Apart from these two uses, parent is not used, and the caller does not guarantee that the generated breakpoints will actually be used to recombine the genomes of parent in particular. If a recombination() callback is called, genome1 for that callback will always be parent.genome1; in other words, drawBreakpoints() will always treat parent.genome1 as the initial copy strand. If the caller wishes to randomly choose an initial copy strand (which is usually desirable), they should do that themselves.
– (integer$)setAncestralNucleotides(is sequence)
This method, which may be called only in nucleotide-based models, replaces the ancestral nucleotide sequence for the model. The sequence parameter is interpreted exactly as it is in the initializeAncestralSequence() function; see that documentation for details. The length of the ancestral sequence is returned.
It is unusual to replace the ancestral sequence in a running simulation, since the nucleotide states of segregating and fixed mutations will depend upon the original ancestral sequence. It can be useful when loading a new population state with readFromMS() or readFromVCF(), such as when resetting the simulation state to an earlier state in a conditional simulation; however, that is more commonly done using readFromPopulationFile() with a SLiM or .trees file.
– (void)setGeneConversion(numeric$ nonCrossoverFraction, numeric$ meanLength, numeric$ simpleConversionFraction, [numeric$ bias = 0])
This method switches the recombination model to the “double-stranded break (DSB)” model (if it is not already set to that), and configures the details of the gene conversion tracts that will therefore be modeled. The meanings and effects of the parameters exactly mirror the initializeGeneConversion() function.
– (void)setHotspotMap(numeric multipliers, [Ni ends = NULL], [string$ sex = "*"])
In nucleotide-based models, set the mutation rate multiplier along the chromosome. There are two ways to call this method. If the optional ends parameter is NULL (the default), then multipliers must be a singleton value that specifies a single multiplier to be used along the entire chromosome. If, on the other hand, ends is supplied, then multipliers and ends must be the same length, and the values in ends must be specified in ascending order. In that case, multipliers and ends taken together specify the multipliers to be used along successive contiguous stretches of the chromosome, from beginning to end; the last position specified in ends should extend to the end of the chromosome (as previously determined, during simulation initialization). See the initializeHotspotMap() function for further discussion of precisely how these multipliers and positions are interpreted.
If the optional sex parameter is "*" (the default), then the supplied hotspot map will be used for both sexes (which is the only option for hermaphroditic simulations). In sexual simulations sex may be "M" or "F" instead, in which case the supplied hotspot map is used only for that sex. Note that whether sex-specific hotspot maps will be used is set by the way that the simulation is initially configured with initializeHotspot(), and cannot be changed with this method; so if the simulation was set up to use sex-specific hotspot maps then sex must be "M" or "F" here, whereas if it was set up not to, then sex must be "*" or unsupplied here. If a simulation needs sex-specific hotspot maps only some of the time, the male and female maps can simply be set to be identical the rest of the time.
The hotspot map is normally constant in simulations, so be sure you know what you are doing.
– (void)setMutationRate(numeric rates, [Ni ends = NULL], [string$ sex = "*"])
Set the mutation rate per base position per gamete. There are two ways to call this method. If the optional ends parameter is NULL (the default), then rates must be a singleton value that specifies a single mutation rate to be used along the entire chromosome. If, on the other hand, ends is supplied, then rates and ends must be the same length, and the values in ends must be specified in ascending order. In that case, rates and ends taken together specify the mutation rates to be used along successive contiguous stretches of the chromosome, from beginning to end; the last position specified in ends should extend to the end of the chromosome (as previously determined, during simulation initialization). See the initializeMutationRate() function for further discussion of precisely how these rates and positions are interpreted.
If the optional sex parameter is "*" (the default), then the supplied mutation rate map will be used for both sexes (which is the only option for hermaphroditic simulations). In sexual simulations sex may be "M" or "F" instead, in which case the supplied mutation rate map is used only for that sex. Note that whether sex-specific mutation rate maps will be used is set by the way that the simulation is initially configured with initializeMutationRate(), and cannot be changed with this method; so if the simulation was set up to use sex-specific mutation rate maps then sex must be "M" or "F" here, whereas if it was set up not to, then sex must be "*" or unsupplied here. If a simulation needs sex-specific mutation rate maps only some of the time, the male and female maps can simply be set to be identical the rest of the time.
The mutation rate intervals are normally a constant in simulations, so be sure you know what you are doing.
In nucleotide-based models, setMutationRate() may not be called. If variation in the mutation rate along the chromosome is desired, setHotspotMap() should be used.
– (void)setRecombinationRate(numeric rates, [Ni ends = NULL], [string$ sex = "*"])
Set the recombination rate per base position per gamete. All rates must be in the interval [0.0, 0.5]. There are two ways to call this method. If the optional ends parameter is NULL (the default), then rates must be a singleton value that specifies a single recombination rate to be used along the entire chromosome. If, on the other hand, ends is supplied, then rates and ends must be the same length, and the values in ends must be specified in ascending order. In that case, rates and ends taken together specify the recombination rates to be used along successive contiguous stretches of the chromosome, from beginning to end; the last position specified in ends should extend to the end of the chromosome (as previously determined, during simulation initialization). See the initializeRecombinationRate() function for further discussion of precisely how these rates and positions are interpreted.
If the optional sex parameter is "*" (the default), then the supplied recombination rate map will be used for both sexes (which is the only option for hermaphroditic simulations). In sexual simulations sex may be "M" or "F" instead, in which case the supplied recombination map is used only for that sex. Note that whether sex-specific recombination maps will be used is set by the way that the simulation is initially configured with initializeRecombinationRate(), and cannot be changed with this method; so if the simulation was set up to use sex-specific recombination maps then sex must be "M" or "F" here, whereas if it was set up not to, then sex must be "*" or unsupplied here. If a simulation needs sex-specific recombination maps only some of the time, the male and female maps can simply be set to be identical the rest of the time.
The recombination intervals are normally a constant in simulations, so be sure you know what you are doing.
5.3 Class Community
5.3.1 Community properties
allGenomicElementTypes => (object<GenomicElementType>)
All of the GenomicElementType objects defined in the simulation. These are guaranteed to be in sorted order, by their id property.
allInteractionTypes => (object<InteractionType>)
All of the InteractionType objects defined in the simulation. These are guaranteed to be in sorted order, by their id property.
allMutationTypes => (object<MutationType>)
All of the MutationType objects defined in the simulation. These are guaranteed to be in sorted order, by their id property.
allScriptBlocks => (object<SLiMEidosBlock>)
All registered SLiMEidosBlock objects in the simulation. These are guaranteed to be in sorted order, by their id property.
allSpecies => (object<Species>)
All of the Species objects defined in the simulation (in species declaration order).
allSubpopulations => (object<Subpopulation>)
All of the Subpopulation objects defined in the simulation.
cycleStage => (string$)
The current cycle stage, as a string. The values of this property essentially mirror the cycle stages of WF and nonWF models. Common values include "first" (during execution of first() events), "early" (during execution of early() events), "reproduction" (during offspring generation), "fitness" (during fitness evaluation), "survival" (while applying selection and mortality in nonWF models), and "late" (during execution of late() events).
Other possible values include "begin" (during internal setup before each cycle), "tally" (while tallying mutation reference counts and removing fixed mutations), "swap" (while swapping the offspring generation into the parental generation in WF models), "end" (during internal bookkeeping after each cycle), and "console" (during the in-between-ticks state in which commands in SLiMgui’s Eidos console are executed). It would probably be a good idea not to use this latter set of values; they are probably not user-visible during ordinary model execution anyway.
During execution of initialize() callbacks, no Community object yet exists and so this property cannot be accessed. To detect this state, use exists("community"); if that is F, community does not exist, and therefore your code is executing during initialize() callbacks (or outside of SLiM entirely, in some other Eidos-based context).
logFiles => (object<LogFile>)
The LogFile objects being used in the simulation.
modelType => (string$)
The type of model being simulated, as specified in initializeSLiMModelType(). This will be "WF" for WF models (Wright-Fisher models, the default), or "nonWF" for nonWF models (non-Wright-Fisher models). This must be the same for all species in the community; it is therefore a property on Community, not Species.
tag <–> (integer$)
A user-defined integer value. The value of tag is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tag is not used by SLiM; it is free for you to use. See also the getValue() and setValue() methods (provided by the Dictionary class; see the Eidos manual), for another way of attaching state to the simulation.
tick <–> (integer$)
The current tick number.
verbosity <–> (integer$)
The verbosity level, for SLiM’s logging of information about the simulation. This is 1 by default, but can be changed at the command line with the -l[ong] option. It is provided here so that scripts can consult it to govern the level of verbosity of their own output, or set the verbosity level for particular sections of their code. A verbosity level of 0 suppresses most of SLiM’s optional output; 2 adds some extra output beyond SLiM’s standard output.
5.3.2 Community methods
– (object<LogFile>$)createLogFile(string$ filePath, [Ns initialContents = NULL], [logical$ append = F], [logical$ compress = F], [string$ sep = ","], [Ni$ logInterval = NULL], [Ni$ flushInterval = NULL])
Creates and returns a new LogFile object that logs data from the simulation (see the documentation for the LogFile class for details). Logged data will be written to the file at filePath, overwriting any existing file at that path by default, or appending to it instead if append is T (successive rows of the log table will always be appended to the previously written content, of course). Before the header line for the log is written out, any string elements in initialContents will be written first, separated by newlines, allowing for a user-defined file header. If compress is T, the contents will be compressed with zlib as they are written, and the standard .gz extension for gzip-compressed files will be appended to the filename in filePath if it is not already present.
The sep parameter specifies the separator between data values within a row. The default of "," will generate a “comma-separated value” (CSV) file, while passing sep="\t" will use a tab separator instead to generate a “tab-separated value” (TSV) file. Other values for sep may also be used, but are less standard.
LogTable supports periodic automatic logging of a new row of data, enabled by supplying a non-NULL value for logInterval. In this case, a new row will be logged (as if logRow() were called on the LogFile) at the end of every logInterval ticks (just before the tick counter increments, in both WF and nonWF models), starting at the end of the tick in which the LogFile was created. A logInterval of 1 will cause automatic logging at the end of every tick, whereas a logInterval of NULL disables automatic logging. Automatic logging can always be disabled or reconfigured later with the LogFile method setLogInterval(), or logging can be triggered manually by calling logRow().
When compression is enabled, LogFile flushes new data lazily by default, for performance reasons, buffering data for multiple rows before writing to disk. Passing a non-NULL value for flushInterval requests a flush every flushInterval rows (with a value of 1 providing unbuffered operation). Note that flushing very frequently will likely result in both lower performance and a larger final file size (in one simple test, 48943 bytes instead of 4280 bytes, or more than a 10× increase in size). Alternatively, passing a very large value for flushInterval will effectively disable automatic flushing, except at the end of the simulation (but be aware that this may use a large amount of memory for large log files). In any case, the log file will be created immediately, with its requested initial contents; the initial write is not buffered. When compression is not enabled, the flushInterval setting is ignored.
The LogFile documentation discusses how to configure and use LogFile to write out the data you are interested in from your simulation.
– (integer$)estimatedLastTick(void)
Returns SLiM’s current estimate of the last tick in which the model will execute. Because script blocks can be added, removed, and rescheduled, and because the simulation may end prematurely (due to a call to simulationFinished(), for example), this is only an estimate, and may change over time.
– (void)deregisterScriptBlock(io<SLiMEidosBlock> scriptBlocks)
All SLiMEidosBlock objects specified by scriptBlocks (either with SLiMEidosBlock objects or with integer identifiers) will be scheduled for deregistration. The deregistered blocks remain valid, and may even still be executed in the current stage of the current tick; the blocks are not actually deregistered and deallocated until sometime after the currently executing script block has completed. To immediately prevent a script block from executing, even when it is scheduled to execute in the current stage of the current tick, use the active property of the script block.
– (object<GenomicElementType>)genomicElementTypesWithIDs(integer ids)
Find and return the GenomicElementType objects with id values matching the values in ids. If no matching GenomicElementType object can be found with a given id, an error results.
– (object<InteractionType>)interactionTypesWithIDs(integer ids)
Find and return the InteractionType objects with id values matching the values in ids. If no matching InteractionType object can be found with a given id, an error results.
– (object<MutationType>)mutationTypesWithIDs(integer ids)
Find and return the MutationType objects with id values matching the values in ids. If no matching MutationType object can be found with a given id, an error results.
– (void)outputUsage(void)
Output the current memory usage of the simulation to Eidos’s output stream. The specifics of what is printed, and in what format, should not be relied upon as they may change from version to version of SLiM. This method is primarily useful for understanding where the memory usage of a simulation predominantly resides, for debugging or optimization. Note that it does not capture all memory usage by the process; rather, it summarizes the memory usage by SLiM and Eidos in directly allocated objects and buffers. To get the same memory usage reported by outputUsage(), but as a float$ value, use the Community method usage(). To get the total memory usage of the running process (either current or peak), use the Eidos function usage().
– (object<SLiMEidosBlock>$)registerEarlyEvent(Nis$ id, string$ source, [Ni$ start = NULL], [Ni$ end = NULL], [No<Species>$ ticksSpec = NULL])
Register a block of Eidos source code, represented as the string singleton source, as an Eidos early() event in the current simulation, with optional start and end ticks (and, for multispecies models, optional ticks specifier ticksSpec) limiting its applicability. The script block will be given identifier id (specified as an integer, or as a string symbolic name such as "s5"); this may be NULL if there is no need to be able to refer to the block later. The registered event is added to the end of the list of registered SLiMEidosBlock objects, and is active immediately; it may be eligible to execute in the current tick. The new SLiMEidosBlock will be defined as a global variable immediately by this method, and will also be returned by this method.
– (object<SLiMEidosBlock>$)registerFirstEvent(Nis$ id, string$ source, [Ni$ start = NULL], [Ni$ end = NULL], [No<Species>$ ticksSpec = NULL])
Register a block of Eidos source code, represented as the string singleton source, as an Eidos first() event in the current simulation, with optional start and end ticks (and, for multispecies models, optional ticks specifier ticksSpec) limiting its applicability. The script block will be given identifier id (specified as an integer, or as a string symbolic name such as "s5"); this may be NULL if there is no need to be able to refer to the block later. The registered event is added to the end of the list of registered SLiMEidosBlock objects, and is active immediately; it may be eligible to execute in the current tick. The new SLiMEidosBlock will be defined as a global variable immediately by this method, and will also be returned by this method.
– (object<SLiMEidosBlock>$)registerInteractionCallback(Nis$ id, string$ source, io<InteractionType>$ intType, [Nio<Subpopulation>$ subpop = NULL], [Ni$ start = NULL], [Ni$ end = NULL])
Register a block of Eidos source code, represented as the string singleton source, as an Eidos interaction() callback in the current simulation (global to the community), with a required interaction type intType (which may be an integer identifier), optional exerter subpopulation subpop (which may also be an integer identifier, or NULL, the default, to indicate all subpopulations), and optional start and end ticks all limiting its applicability. The script block will be given identifier id (specified as an integer, or as a string symbolic name such as "s5"); this may be NULL if there is no need to be able to refer to the block later. The registered callback is added to the end of the list of registered SLiMEidosBlock objects, and is active immediately; it will be eligible to execute the next time an InteractionType is evaluated. The new SLiMEidosBlock will be defined as a global variable immediately by this method, and will also be returned by this method.
– (object<SLiMEidosBlock>$)registerLateEvent(Nis$ id, string$ source, [Ni$ start = NULL], [Ni$ end = NULL], [No<Species>$ ticksSpec = NULL])
Register a block of Eidos source code, represented as the string singleton source, as an Eidos late() event in the current simulation, with optional start and end ticks (and, for multispecies models, optional ticks specifier ticksSpec) limiting its applicability. The script block will be given identifier id (specified as an integer, or as a string symbolic name such as "s5"); this may be NULL if there is no need to be able to refer to the block later. The registered event is added to the end of the list of registered SLiMEidosBlock objects, and is active immediately; it may be eligible to execute in the current tick. The new SLiMEidosBlock will be defined as a global variable immediately by this method, and will also be returned by this method.
– (object<SLiMEidosBlock>$)rescheduleScriptBlock(io<SLiMEidosBlock>$ block, [Ni$ start = NULL], [Ni$ end = NULL], [Ni ticks = NULL])
Reschedule the target script block given by block to execute in a specified set of ticks. The block parameter may be either an integer representing the ID of the desired script block, or a SLiMScriptBlock specified directly. The target script block, block, is returned.
The first way to specify the tick set is with start and end parameter values; block will then execute from start to end, inclusive.
The second way to specify the tick set is using the ticks parameter, specifying each tick in which the block should execute. The vector supplied for ticks does not need to be in sorted order, but it must not contain any duplicates.
It can sometimes be better to handle script block scheduling in other ways. If an early() event needs to execute every tenth tick over the whole duration of a long model run, for example, it might not be advisable to use a call like community.rescheduleScriptBlock(s1, ticks=seq(10, 100000, 10)) for that purpose, since that would make things complicated for SLiM’s scheduler. Instead, it might be preferable to add a test such as if (community.tick % 10 != 0) return; at the beginning of the event. It is legal to reschedule a script block while the block is executing; a call like community.rescheduleScriptBlock(self, community.tick + 10, community.tick + 10); made inside a given block would therefore also cause the block to execute every tenth tick, although this sort of self-rescheduling code is probably harder to read, maintain, and debug.
Whichever way of specifying the tick set is used, block may continue to be executed during the current tick cycle stage even after it has been rescheduled, unless it is made inactive using its active property, and similarly, the block may not execute during the current tick cycle stage if it was not already scheduled to do so. Rescheduling script blocks during the tick and tick cycle stage in which they are executing, or in which they are intended to execute, should be avoided. Also, note that script blocks which are open-ended (i.e., with no specified end tick), are not used in determining whether the end of the simulation has been reached (because then the simulation would run forever).
Note that new script blocks can also be created and scheduled using the register...() methods of Community and Species; by using the same source as a template script block, the template can be duplicated and scheduled for different ticks, perhaps with modifications or variations. In multispecies models, note that blocks may not run due to their species or ticks specifier, even in ticks in which they are scheduled to run.
– (object<SLiMEidosBlock>)scriptBlocksWithIDs(integer ids)
Find and return the SLiMEidosBlock objects with id values matching the values in ids. If no matching SLiMEidosBlock object can be found with a given id, an error results.
– (void)simulationFinished(void)
Declare the current simulation finished. Normally SLiM ends a simulation when, at the end of a tick, there are no script events or callbacks registered for any future tick (excluding scripts with no declared end tick). If you wish to end a simulation before this condition is met, a call to simulationFinished() will cause the current simulation to end at the end of the current tick. For example, a simulation might self-terminate if a test for a dynamic equilibrium condition is satisfied. Note that the current tick will finish executing; if you want the simulation to stop immediately, you can use the Eidos method stop(), which raises an error condition.
– (object<Species>)speciesWithIDs(integer ids)
Find and return the Species objects with id values matching the values in ids. If no matching Species object can be found with a given id, an error results.
– (object<Subpopulation>)subpopulationsWithIDs(integer ids)
Find and return the Subpopulation objects with id values matching the values in ids. If no matching Subpopulation object can be found with a given id, an error results.
– (float$)usage(void)
Return the current memory usage of the simulation. The specifics of what is totalled up should not be relied upon as it may change from version to version of SLiM. This method is primarily useful for understanding where the memory usage of a simulation predominantly resides, for debugging or optimization. Note that it does not capture all memory usage by the process; rather, it summarizes the memory usage by SLiM and Eidos in directly allocated objects and buffers. To see details of this internal memory usage, use the Community method outputUsage(). To get the total memory usage of the running process (either current or peak), use the Eidos function usage().
5.4 Class Genome
5.4.1 Genome properties
genomePedigreeID => (integer$)
If pedigree tracking is turned on with initializeSLiMOptions(keepPedigrees=T), genomePedigreeID is a unique non-negative identifier for each genome in a simulation, never re-used throughout the duration of the simulation run. Furthermore, the genomePedigreeID of a given genome will be equal to either (2*pedigreeID) or (2*pedigreeID + 1) of the individual that the genome belongs to (the former for the first genome of the individual, the latter for the second genome of the individual); this invariant relationship is guaranteed. If pedigree tracking is not enabled, this property is unavailable.
genomeType => (string$)
The type of chromosome represented by this genome; one of "A", "X", or "Y".
individual => (object<Individual>$)
The Individual object to which this genome belongs.
isNullGenome => (logical$)
T if the genome is a “null” genome, F if it is an ordinary genome object. When a sex chromosome (X or Y) is simulated, the other sex chromosome also exists in the simulation, but it is a “null” genome that does not carry any mutations. Instead, it is a placeholder, present to allow SLiM’s code to operate in much the same way as it does when an autosome is simulated. Null genomes should not be accessed or manipulated.
mutations => (object<Mutation>)
All of the Mutation objects present in this genome.
tag <–> (integer$)
A user-defined integer value. The value of tag is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tag is not used by SLiM; it is free for you to use. Note that the Genome objects used by SLiM are new with every new individual, so the tag value of each new offspring generated in each tick will be initially undefined.
5.4.2 Genome methods
+ (void)addMutations(object<Mutation> mutations)
Add the existing mutations in mutations to the genome, if they are not already present (if they are already present, they will be ignored), and if the addition is not prevented by the mutation stacking policy (see the mutationStackPolicy property of MutationType).
Calling this will normally affect the fitness values calculated toward the end of the current tick; if you want current fitness values to be affected, you can call the Species method recalculateFitness() – but see the documentation of that method for caveats.
Note that in nonWF models that use tree-sequence recording, mutations cannot be added to an individual after the tick in which the individual is created (i.e., when the age of the individual is greater than 0), to prevent the possibility of inconsistencies in the recorded tree sequence.
+ (object<Mutation>)addNewDrawnMutation(io<MutationType> mutationType, integer position, [Nio<Subpopulation> originSubpop = NULL], [Nis nucleotide = NULL])
Add new mutations to the target genome(s) with the specified mutationType (specified by the MutationType object or by integer identifier), position, and originSubpop (specified by the Subpopulation object or by integer identifier, or by NULL, the default, to specify the subpopulation to which the first target genome belongs). If originSubpop is supplied as an integer, it is intentionally not checked for validity; you may use arbitrary values of originSubpop to “tag” the mutations that you create. The selection coefficients of the mutations are drawn from their mutation types; addNewMutation() may be used instead if you wish to specify selection coefficients.
In non-nucleotide-based models, mutationType will always be a non-nucleotide-based mutation type, and so nucleotide must be NULL (the default). In a nucleotide-based model, mutationType might still be non-nucleotide-based (in which case nucleotide must still be NULL), or mutationType might be nucleotide-based, in which case a non-NULL value must be supplied for nucleotide, specifying the nucleotide(s) to be associated with the new mutation(s). Nucleotides may be specified with string values ("A", "C", "G", or "T"), or with integer values (A=0, C=1, G=2, T=3). If a nucleotide mutation already exists at the mutating position, it is replaced automatically in accordance with the stacking policy for nucleotide-based mutation types. No check is performed that a new mutation’s nucleotide differs from the ancestral sequence, or that its selection coefficient is consistent with other mutations that may already exist at the given position with the same nucleotide; model consistency is the responsibility of the model.
Beginning in SLiM 2.5 this method is vectorized, so all of these parameters may be singletons (in which case that single value is used for all mutations created by the call) or non-singleton vectors (in which case one element is used for each corresponding mutation created). Non-singleton parameters must match in length, since their elements need to be matched up one-to-one.
The new mutations created by this method are returned, even if their actual addition is prevented by the mutation stacking policy (see the mutationStackPolicy property of MutationType). However, the order of the mutations in the returned vector is not guaranteed to be the same as the order in which the values are specified in parameter vectors, unless the position parameter is specified in ascending order. In other words, pre-sorting the parameters to this method into ascending order by position, using order() and subsetting, will guarantee that the order of the returned vector of mutations corresponds to the order of elements in the parameters to this method; otherwise, no such guarantee exists.
Beginning in SLiM 2.1, this is a class method, not an instance method. This means that it does not get multiplexed out to all of the elements of the receiver (which would add a different new mutation to each element); instead, it is performed as a single operation, adding the same new mutation objects to all of the elements of the receiver. Before SLiM 2.1, to add the same mutations to multiple genomes, it was necessary to call addNewDrawnMutation() on one of the genomes, and then add the returned Mutation object to all of the other genomes using addMutations(). That is not necessary in SLiM 2.1 and later, because of this change (although doing it the old way does no harm and produces identical behavior). Pre-2.1 code that actually relied upon the old multiplexing behavior will no longer work correctly (but this is expected to be an extremely rare pattern of usage).
Before SLiM 4, this method also took a originGeneration parameter. This was deprecated (the origin generation was then required to be equal to the current generation, for internal consistency), and was removed in SLiM 4.
Calling this will normally affect the fitness values calculated at the end of the current tick (but not sooner); if you want current fitness values to be affected, you can call the Species method recalculateFitness() – but see the documentation of that method for caveats.
Note that in nonWF models that use tree-sequence recording, mutations cannot be added to an individual after the tick in which the individual is created (i.e., when the age of the individual is greater than 0), to prevent the possibility of inconsistencies in the recorded tree sequence.
+ (object<Mutation>)addNewMutation(io<MutationType> mutationType, numeric selectionCoeff, integer position, [Nio<Subpopulation> originSubpop = NULL], [Nis nucleotide = NULL])
Add new mutations to the target genome(s) with the specified mutationType (specified by the MutationType object or by integer identifier), selectionCoeff, position, and originSubpop (specified by the Subpopulation object or by integer identifier, or by NULL, the default, to specify the subpopulation to which the first target genome belongs). If originSubpop is supplied as an integer, it is intentionally not checked for validity; you may use arbitrary values of originSubpop to “tag” the mutations that you create. The addNewDrawnMutation() method may be used instead if you wish selection coefficients to be drawn from the mutation types of the mutations.
In non-nucleotide-based models, mutationType will always be a non-nucleotide-based mutation type, and so nucleotide must be NULL (the default). In a nucleotide-based model, mutationType might still be non-nucleotide-based (in which case nucleotide must still be NULL), or mutationType might be nucleotide-based, in which case a non-NULL value must be supplied for nucleotide, specifying the nucleotide(s) to be associated with the new mutation(s). Nucleotides may be specified with string values ("A", "C", "G", or "T"), or with integer values (A=0, C=1, G=2, T=3). If a nucleotide mutation already exists at the mutating position, it is replaced automatically in accordance with the stacking policy for nucleotide-based mutation types. No check is performed that a new mutation’s nucleotide differs from the ancestral sequence, or that its selection coefficient is consistent with other mutations that may already exist at the given position with the same nucleotide; model consistency is the responsibility of the model.
The new mutations created by this method are returned, even if their actual addition is prevented by the mutation stacking policy (see the mutationStackPolicy property of MutationType). However, the order of the mutations in the returned vector is not guaranteed to be the same as the order in which the values are specified in parameter vectors, unless the position parameter is specified in ascending order. In other words, pre-sorting the parameters to this method into ascending order by position, using order() and subsetting, will guarantee that the order of the returned vector of mutations corresponds to the order of elements in the parameters to this method; otherwise, no such guarantee exists.
Beginning in SLiM 2.1, this is a class method, not an instance method. This means that it does not get multiplexed out to all of the elements of the receiver (which would add a different new mutation to each element); instead, it is performed as a single operation, adding the same new mutation object to all of the elements of the receiver. Before SLiM 2.1, to add the same mutation to multiple genomes, it was necessary to call addNewMutation() on one of the genomes, and then add the returned Mutation object to all of the other genomes using addMutations(). That is not necessary in SLiM 2.1 and later, because of this change (although doing it the old way does no harm and produces identical behavior). Pre-2.1 code that actually relied upon the old multiplexing behavior will no longer work correctly (but this is expected to be an extremely rare pattern of usage).
Before SLiM 4, this method also took a originGeneration parameter. This was deprecated (the origin generation was then required to be equal to the current generation, for internal consistency), and was removed in SLiM 4.
Calling this will normally affect the fitness values calculated at the end of the current tick (but not sooner); if you want current fitness values to be affected, you can call the Species method recalculateFitness() – but see the documentation of that method for caveats.
Note that in nonWF models that use tree-sequence recording, mutations cannot be added to an individual after the tick in which the individual is created (i.e., when the age of the individual is greater than 0), to prevent the possibility of inconsistencies in the recorded tree sequence.
– (Nlo<Mutation>$)containsMarkerMutation(io<MutationType>$ mutType, integer$ position, [logical$ returnMutation = F])
Returns T if the genome contains a mutation of type mutType at position, F otherwise (if returnMutation has its default value of F; see below). This method is, as its name suggests, intended for checking for “marker mutations”: mutations of a special mutation type that are not literally mutations in the usual sense, but instead are added in to particular genomes to mark them as possessing some property. Marker mutations are not typically added by SLiM’s mutation-generating machinery; instead they are added explicitly with addNewMutation() or addNewDrawnMutation() at a known, constant position in the genome. This method provides a check for whether a marker mutation of a given type exists in a particular genome; because the position to check is known in advance, that check can be done much faster than the equivalent check with containsMutations() or countOfMutationsOfType(), using a binary search of the genome.
If returnMutation is T (an option added in SLiM 3), this method returns the actual mutation found, rather than just T or F. More specifically, the first mutation found of mutType at position will be returned; if more than one such mutation exists in the target genome, which one is returned is not defined. If returnMutation is T and no mutation of mutType is found at position, NULL will be returned.
– (logical)containsMutations(object<Mutation> mutations)
Returns a logical vector indicating whether each of the mutations in mutations is present in the genome; each element in the returned vector indicates whether the corresponding mutation is present (T) or absent (F). This method is provided for speed; it is much faster than the corresponding Eidos code.
– (integer$)countOfMutationsOfType(io<MutationType>$ mutType)
Returns the number of mutations that are of the type specified by mutType, out of all of the mutations in the genome. If you need a vector of the matching Mutation objects, rather than just a count, use -mutationsOfType(). This method is provided for speed; it is much faster than the corresponding Eidos code.
+ (integer)mutationCountsInGenomes([No<Mutation> mutations = NULL])
Return an integer vector with the frequency counts of all of the Mutation objects passed in mutations, within the target Genome vector. If the optional mutations argument is NULL (the default), frequency counts will be returned for all of the active Mutation objects in the simulation – the same Mutation objects, and in the same order, as would be returned by the mutations property of sim, in other words.
See the +mutationFrequenciesInGenomes() method to obtain float frequencies instead of integer counts. See also the Species methods mutationCounts() and mutationFrequencies(), which may be more efficient for getting counts/frequencies for whole subpopulations or for the whole simulation.
+ (float)mutationFrequenciesInGenomes([No<Mutation> mutations = NULL])
Return a float vector with the frequencies of all of the Mutation objects passed in mutations, within the target Genome vector. If the optional mutations argument is NULL (the default), frequencies will be returned for all of the active Mutation objects in the simulation – the same Mutation objects, and in the same order, as would be returned by the mutations property of sim, in other words.
See the +mutationCountsInGenomes() method to obtain integer counts instead of float frequencies. See also the Species methods mutationCounts() and mutationFrequencies(), which may be more efficient for getting counts/frequencies for whole subpopulations or for the whole simulation.
– (object<Mutation>)mutationsOfType(io<MutationType>$ mutType)
Returns an object vector of all the mutations that are of the type specified by mutType, out of all of the mutations in the genome. If you just need a count of the matching Mutation objects, rather than a vector of the matches, use -countOfMutationsOfType(); if you need just the positions of matching Mutation objects, use -positionsOfMutationsOfType(); and if you are aiming for a sum of the selection coefficients of matching Mutation objects, use -sumOfMutationsOfType(). This method is provided for speed; it is much faster than the corresponding Eidos code.
– (is)nucleotides([Ni$ start = NULL], [Ni$ end = NULL], [string$ format = "string"])
Returns the nucleotide sequence for the genome. This is the current ancestral sequence, as would be returned by the Chromosome method ancestralNucleotides(), with the nucleotides for any nucleotide-based mutations in the genome overlaid. The range of the returned sequence may be constrained by a start position given in start and/or an end position given in end; nucleotides will be returned from start to end, inclusive. The default value of NULL for start and end represent the first and last base positions of the chromosome, respectively.
The format of the returned sequence is controlled by the format parameter. A format of "string" will return the sequence as a singleton string (e.g., "TATA"). A format of "char" will return a string vector with one element per nucleotide (e.g., "T", "A", "T", "A"). A format of "integer" will return an integer vector with values A=0, C=1, G=2, T=3 (e.g., 3, 0, 3, 0). A format of "codon" will return an integer vector with values from 0 to 63, based upon successive nucleotide triplets in the sequence (which, for this format, must have a length that is a multiple of three); see the ancestralNucleotides() documentation for details. If the sequence returned is likely to be long, the "string" format will be the most memory-efficient, and may also be the fastest (but may be harder to work with).
Several helper functions are provided for working with sequences, such as nucleotideCounts() to get the counts of A/C/G/T nucleotides in a sequence, nucleotideFrequencies() to get the same information as frequencies, and codonsToAminoAcids() to convert a codon sequence (such as provided by the codon format described above) to an amino acid sequence.
+ (void)output([Ns$ filePath = NULL], [logical$ append = F])
Output the target genomes in SLiM’s native format. This low-level output method may be used to output any sample of Genome objects (the Eidos function sample() may be useful for constructing custom samples, as may the SLiM class Individual). For output of a sample from a single Subpopulation, the outputSample() of Subpopulation may be more straightforward to use. If the optional parameter filePath is NULL (the default), output is directed to SLiM’s standard output. Otherwise, the output is sent to the file specified by filePath, overwriting that file if append if F, or appending to the end of it if append is T.
See outputMS() and outputVCF() for other output formats. Output is generally done in a late() event, so that the output reflects the state of the simulation at the end of a tick.
+ (void)outputMS([Ns$ filePath = NULL], [logical$ append = F], [logical$ filterMonomorphic = F])
Output the target genomes in MS format. This low-level output method may be used to output any sample of Genome objects (the Eidos function sample() may be useful for constructing custom samples, as may the SLiM class Individual). For output of a sample from a single Subpopulation, the outputMSSample() of Subpopulation may be more straightforward to use. If the optional parameter filePath is NULL (the default), output is directed to SLiM’s standard output. Otherwise, the output is sent to the file specified by filePath, overwriting that file if append if F, or appending to the end of it if append is T. Positions in the output will span the interval [0,1].
If filterMonomorphic is F (the default), all mutations that are present in the sample will be included in the output. This means that some mutations may be included that are actually monomorphic within the sample (i.e., that exist in every sampled genome, and are thus apparently fixed). These may be filtered out with filterMonomorphic = T if desired; note that this option means that some mutations that do exist in the sampled genomes might not be included in the output, simply because they exist in every sampled genome.
See output() and outputVCF() for other output formats. Output is generally done in a late() event, so that the output reflects the state of the simulation at the end of a tick.
+ (void)outputVCF([Ns$ filePath = NULL], [logical$ outputMultiallelics = T], [logical$ append = F], [logical$ simplifyNucleotides = F], [logical$ outputNonnucleotides = T])
Output the target genomes in VCF format. The target genomes are treated as pairs comprising individuals for purposes of structuring the VCF output, so an even number of genomes is required. This low-level output method may be used to output any sample of Genome objects (the Eidos function sample() may be useful for constructing custom samples, as may the SLiM class Individual). For output of a sample from a single Subpopulation, the outputVCFSample() of Subpopulation may be more straightforward to use. If the optional parameter filePath is NULL (the default), output is directed to SLiM’s standard output. Otherwise, the output is sent to the file specified by filePath, overwriting that file if append if F, or appending to the end of it if append is T.
The parameters outputMultiallelics, simplifyNucleotides, and outputNonnucleotides affect the format of the output produced; see the reference documentation for further discussion.
See outputMS() and output() for other output formats. Output is generally done in a late() event, so that the output reflects the state of the simulation at the end of a tick.
– (integer)positionsOfMutationsOfType(io<MutationType>$ mutType)
Returns the positions of mutations that are of the type specified by mutType, out of all of the mutations in the genome. If you need a vector of the matching Mutation objects, rather than just positions, use -mutationsOfType(). This method is provided for speed; it is much faster than the corresponding Eidos code.
+ (object<Mutation>)readFromMS(string$ filePath, io<MutationType>$ mutationType)
Read new mutations from the MS format file at filePath and add them to the target genomes. The number of target genomes must match the number of genomes represented in the MS file. To read into all of the genomes in a given subpopulation pN, simply call pN.genomes.readFromMS(), assuming the subpopulation’s size matches that of the MS file. A vector containing all of the mutations created by readFromMS() is returned.
Each mutation is created at the position specified in the file, using the mutation type given by mutationType. Positions are expected to be in [0,1], and are scaled to the length of the chromosome by multiplying by the last valid base position of the chromosome (i.e., one less than the chromosome length). Selection coefficients are drawn from the mutation type. The population of origin for each mutation is set to -1, and the tick of origin is set to the current tick. In a nucleotide-based model, if mutationType is nucleotide-based, a random nucleotide different from the ancestral nucleotide at the position will be chosen with equal probability.
The target genomes correspond, in order, to the call lines in the MS file. In sex-based models that simulate the X or Y chromosome, null genomes in the target vector will be skipped, and will not be used to correspond to any call line; however, care should be taken in this case that the lines in the MS file correspond to the target genomes in the manner desired.
+ (object<Mutation>)readFromVCF(string$ filePath, [Nio<MutationType>$ mutationType = NULL])
Read new mutations from the VCF format file at filePath and add them to the target genomes. The number of target genomes must match the number of genomes represented in the VCF file (i.e., two times the number of samples, if each sample is diploid). To read into all of the genomes in a given subpopulation pN, simply call pN.genomes.readFromVCF(), assuming the subpopulation’s size matches that of the VCF file taking ploidy into account. A vector containing all of the mutations created by readFromVCF() is returned.
SLiM’s VCF parsing is quite primitive. The header is parsed only inasmuch as SLiM looks to see whether SLiM-specific VCF fields are defined or not; the rest of the header information is ignored. Call lines are assumed to follow the format:
#CHROM POS ID REF ALT QUAL FILTER INFO FORMAT i0...iN
The CHROM, ID, QUAL, FILTER, and FORMAT fields are ignored, and information in the genotype fields beyond the GT genotype subfield are also ignored. SLiM’s own VCF annotations are honored; in particular, mutations will be created using the given values of MID, S, PO, TO, and MT if those subfields are present, and DOM, if it is present, must match the dominance coefficient of the mutation type. The parameter mutationType (a MutationType object or id) will be used for any mutations that have no supplied mutation type id in the MT subfield; if mutationType would be used but is NULL an error will result. Mutation IDs supplied in MID will be used if no mutation IDs have been used in the simulation so far; if any have been used, it is difficult for SLiM to guarantee that there are no conflicts, so a warning will be emitted and the MID values will be ignored. If selection coefficients are not supplied with the S subfield, they will be drawn from the mutation type used for the mutation. If a population of origin is not supplied with the PO subfield, -1 will be used. If a tick of origin is not supplied with the TO subfield (or a generation of origin GO field, which was the SLiM convention before SLiM 4), the current tick will be used.
REF and ALT must always be comprised of simple nucleotides (A/C/G/T) rather than values representing indels or other complex states. Beyond this, the handling of the REF and ALT fields depends upon several factors. First of all, these fields are ignored in non-nucleotide-based models, although they are still checked for conformance. In nucleotide-based models, when a header definition for SLiM’s NONNUC tag is present (as when nucleotide-based output is generated by SLiM): Second, if a NONNUC field is present in the INFO field the call line is taken to represent a non-nucleotide-based mutation, and REF and ALT are again ignored. In this case the mutation type used must be non-nucleotide-based. Third, if NONNUC is not present the call line is taken to represent a nucleotide-based mutation. In this case, the mutation type used must be nucleotide-based. Also, in this case, the specified reference nucleotide must match the existing ancestral nucleotide at the given position. In nucleotide-based models, when a header definition for SLiM’s NONNUC tag is not present (as when loading a non-SLiM-generated VCF file): The mutation type will govern the way nucleotides are handled. If the mutation type used for a mutation is nucleotide-based, the nucleotide provided in the VCF file for that allele will be used. If the mutation type is non-nucleotide-based, the nucleotide provided will be ignored.
If multiple alleles using the same nucleotide at the same position are specified in the VCF file, a separate mutation will be created for each, mirroring SLiM’s behavior with independent mutational lineages when writing VCF. The MULTIALLELIC flag is ignored by readFromVCF(); call lines for mutations at the same base position in the same genome will result in stacked mutations whether or not MULTIALLELIC is present.
The target genomes correspond, in order, to the haploid or diploid calls provided for i0…iN (the sample IDs) in the VCF file. In sex-based models that simulate the X or Y chromosome, null genomes in the target vector will be skipped, and will not be used to correspond to any of i0…iN; however, care should be taken in this case that the genomes in the VCF file correspond to the target genomes in the manner desired.
+ (void)removeMutations([No<Mutation> mutations = NULL], [logical$ substitute = F])
Remove the mutations in mutations from the target genome(s), if they are present (if they are not present, they will be ignored). If NULL is passed for mutations (which is the default), then all mutations will be removed from the target genomes; in this case, substitute must be F (a specific vector of mutations to be substituted is required). Note that the Mutation objects removed remain valid, and will still be in the simulation’s mutation registry (i.e., will be returned by the Species property mutations), until the next tick.
Removing mutations will normally affect the fitness values calculated at the end of the current tick; if you want current fitness values to be affected, you can call the Species method recalculateFitness() – but see the documentation of that method for caveats.
The optional parameter substitute was added in SLiM 2.2, with a default of F for backward compatibility. If substitute is T, Substitution objects will be created for all of the removed mutations so that they are recorded in the simulation as having fixed, just as if they had reached fixation and been removed by SLiM’s own internal machinery. This will occur regardless of whether the mutations have in fact fixed, regardless of the convertToSubstitution property of the relevant mutation types, and regardless of whether all copies of the mutations have even been removed from the simulation (making it possible to create Substitution objects for mutations that are still segregating). It is up to the caller to perform whatever checks are necessary to preserve the integrity of the simulation’s records. Typically substitute will only be set to T in the context of calls like sim.subpopulations.genomes.removeMutations(muts, T), such that the substituted mutations are guaranteed to be entirely removed from circulation. As mentioned above, substitute may not be T if mutations is NULL.
– (float$)sumOfMutationsOfType(io<MutationType>$ mutType)
Returns the sum of the selection coefficients of all mutations that are of the type specified by mutType, out of all of the mutations in the genome. This is often useful in models that use a particular mutation type to represent QTLs with additive effects; in that context, sumOfMutationsOfType() will provide the sum of the additive effects of the QTLs for the given mutation type. This method is provided for speed; it is much faster than the corresponding Eidos code. Note that this method also exists on Individual, for cases in which the sum across both genomes of an individual is desired.
5.5 Class GenomicElement
5.5.1 GenomicElement properties
endPosition => (integer$)
The last position in the chromosome contained by this genomic element.
genomicElementType => (object<GenomicElementType>$)
The GenomicElementType object that defines the behavior of this genomic element.
startPosition => (integer$)
The first position in the chromosome contained by this genomic element.
tag <–> (integer$)
A user-defined integer value. The value of tag is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tag is not used by SLiM; it is free for you to use.
5.5.2 GenomicElement methods
– (void)setGenomicElementType(io<GenomicElementType>$ genomicElementType)
Set the genomic element type used for a genomic element. The genomicElementType parameter should supply the new genomic element type for the element, either as a GenomicElementType object or as an integer identifier. The genomic element type for a genomic element is normally a constant in simulations, so be sure you know what you are doing.
5.6 Class GenomicElementType
5.6.1 GenomicElementType properties
color <–> (string$)
The color used to display genomic elements of this type in SLiMgui. Outside of SLiMgui, this property still exists, but is not used by SLiM. Colors may be specified by name, or with hexadecimal RGB values of the form "#RRGGBB". If color is the empty string, "", SLiMgui’s default color scheme is used; this is the default for new GenomicElementType objects.
id => (integer$)
The identifier for this genomic element type; for genomic element type g3, for example, this is 3.
mutationFractions => (float)
For each MutationType represented in this genomic element type, this property has the corresponding fraction of all mutations that will be drawn from that MutationType.
mutationMatrix => (float)
The nucleotide mutation matrix used for this genomic element type, set up by initializeGenomicElementType() and setMutationMatrix(). This property is only defined in nucleotide-based models; it is unavailable otherwise.
mutationTypes => (object<MutationType>)
The MutationType instances used by this genomic element type.
species => (object<Species>$)
The species to which the target object belongs.
tag <–> (integer$)
A user-defined integer value. The value of tag is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tag is not used by SLiM; it is free for you to use. See also the getValue() and setValue() methods (provided by the Dictionary class; see the Eidos manual), for another way of attaching state to genomic element types.
5.6.2 GenomicElementType methods
– (void)setMutationFractions(io<MutationType> mutationTypes, numeric proportions)
Set the mutation type fractions contributing to a genomic element type. The mutationTypes vector should supply the mutation types used by the genomic element (either as MutationType objects or as integer identifiers), and the proportions vector should be of equal length, specifying the relative proportion of mutations that will be drawn from each corresponding type. This is normally a constant in simulations, so be sure you know what you are doing.
– (void)setMutationMatrix(float mutationMatrix)
Sets a new nucleotide mutation matrix for the genomic element type. This replaces the mutation matrix originally set by initializeGenomicElementType(). This method may only be called in nucleotide-based models.
5.7 Class Individual
5.7.1 Individual properties
age <–> (integer$)
The age of the individual, measured in cycles. A newly generated offspring individual will have an age of 0 in the same tick in which it was created. The age of every individual is incremented by one at the same point that its species cycle counter is incremented, at the end of the tick cycle, if and only if its species was active in that tick. The age of individuals may be changed; usually this only makes sense when setting up the initial state of a model, however.
color <–> (string$)
The color used to display the individual in SLiMgui. Outside of SLiMgui, this property still exists, but is not used by SLiM. Colors may be specified by name, or with hexadecimal RGB values of the form "#RRGGBB" (see the Eidos manual). If color is the empty string, "", SLiMgui’s default (fitness-based) color scheme is used; this is the default for new Individual objects. Note that named colors will be converted to RGB internally, so the value of this property will always be a hexadecimal RGB color string (or "").
fitnessScaling <–> (float$)
A float scaling factor applied to the individual’s fitness (i.e., the fitness value computed for the individual will be multiplied by this value). This provides a simple, fast way to modify the fitness of an individual; conceptually it is similar to returning a fitness effect for the individual from a fitnessEffect() callback, but without the complexity and performance overhead of implementing such a callback. To scale the fitness of all individuals in a subpopulation by the same factor, see the fitnessScaling property of Subpopulation.
The value of fitnessScaling is reset to 1.0 every tick, so that any scaling factor set lasts for only a single tick. This reset occurs immediately after fitness values are calculated, in both WF and nonWF models.
genomes => (object<Genome>)
The pair of Genome objects associated with this individual. If only one of the two genomes is desired, the genome1 or genome2 property may be used.
genomesNonNull => (object<Genome>)
The pair of Genome objects associated with this individual, as with the genomes property, if both are not null genomes. If one or both are null genomes, the null genomes are excluded from the returned vector. This is a convenience shorthand, sometimes useful in models that involve null genomes.
genome1 => (object<Genome>$)
The first Genome object associated with this individual. This property is particularly useful when you want the first genome from each of a vector of individuals, as often arises in haploid models.
genome2 => (object<Genome>$)
The second Genome object associated with this individual. This property is particularly useful when you want the second genome from each of a vector of individuals, as often arises in haploid models.
index => (integer$)
The index of the individual in the individuals vector of its Subpopulation.
meanParentAge => (float$)
The average age of the parents of this individual, measured in cycles. Parentless individuals will have a meanParentAge of 0.0. The mean parent age is determined when a new offspring is generated, from the age property of the parent or parents involved in generating the offspring. For addRecombinant() that is somewhat complex; see that method for details.
migrant => (logical$)
Set to T if the individual is a recent migrant, F otherwise. The definition of “recent” depends upon the model type (WF or nonWF).
In WF models, this flag is set at the point when a new child is generated if it is a migrant (i.e., if its source subpopulation is not the same as its subpopulation), and remains valid, with the same value, for the rest of the individual’s lifetime.
In nonWF models, this flag is F for all new individuals, is set to F in all individuals at the end of the reproduction tick cycle stage, and is set to T on all individuals moved to a new subpopulation by takeMigrants() or a survival() callback; the T value set by takeMigrants() or survival() will remain until it is reset at the end of the next reproduction tick cycle stage.
pedigreeID => (integer$)
If pedigree tracking is turned on with initializeSLiMOptions(keepPedigrees=T), pedigreeID is a unique non-negative identifier for each individual in a simulation, never re-used throughout the duration of the simulation run. If pedigree tracking is not enabled, this property is unavailable.
pedigreeParentIDs => (integer)
If pedigree tracking is turned on with initializeSLiMOptions(keepPedigrees=T), pedigreeParentIDs contains the values of pedigreeID that were possessed by the parents of an individual; it is thus a vector of two values. If pedigree tracking is not enabled, this property is unavailable. Parental values may be -1 if insufficient ticks have elapsed for that information to be available (because the simulation just started, or because a subpopulation is new).
pedigreeGrandparentIDs => (integer)
If pedigree tracking is turned on with initializeSLiMOptions(keepPedigrees=T), pedigreeGrandparentIDs contains the values of pedigreeID that were possessed by the grandparents of an individual; it is thus a vector of four values. If pedigree tracking is not enabled, this property is unavailable. Grandparental values may be -1 if insufficient ticks have elapsed for that information to be available (because the simulation just started, or because a subpopulation is new).
reproductiveOutput => (integer$)
If pedigree tracking is turned on with initializeSLiMOptions(keepPedigrees=T), reproductiveOutput contains the number of offspring for which this individual has been a parent. If pedigree tracking is not enabled, this property is unavailable. If an individual is a parent by cloning or selfing, or as both parents for a biparental mating, this value is incremented by two. Involvement of an individual as a parent for an addRecombinant() call does not change this property’s value, since the reproductive contribution in that case is unclear; one must conduct separate bookkeeping for that case if necessary.
See also the Subpopulation property lifetimeReproductiveOutput.
sex => (string$)
The sex of the individual. This will be "H" if sex is not enabled in the simulation (i.e., for hermaphrodites), otherwise "F" or "M" as appropriate.
spatialPosition => (float)
The spatial position of the individual. The length of the spatialPosition property (the number of coordinates in the spatial position of an individual) depends upon the spatial dimensionality declared with initializeSLiMOptions(). If the spatial dimensionality is zero (as it is by default), it is an error to access this property. The elements of this property are identical to the values of the x, y, and z properties (if those properties are encompassed by the spatial dimensionality of the simulation). In other words, if the declared dimensionality is "xy", the individual.spatialPosition property is equivalent to c(individual.x, individual.y); individual.z is not used since it is not encompassed by the simulation’s dimensionality.
subpopulation => (object<Subpopulation>$)
The Subpopulation object to which the individual belongs.
tag <–> (integer$)
A user-defined integer value (as opposed to tagF, which is of type float). The value of tag is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tag is not used by SLiM; it is free for you to use. See also the getValue() and setValue() methods (provided by the Dictionary class; see the Eidos manual), for another way of attaching state to individuals. Note that the Individual objects used by SLiM are new for every new offspring, so the tag value of each new offspring generated in each tick will be initially undefined.
tagF <–> (float$)
A user-defined float value (as opposed to tag, which is of type integer). The value of tagF is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tagF is not used by SLiM; it is free for you to use. See also the getValue() and setValue() methods (provided by the Dictionary class; see the Eidos manual), for another way of attaching state to individuals.
Note that at present, although many classes in SLiM have an integer-type tag property, only Individual has a float-type tagF property, because attaching model state to individuals seems to be particularly common and useful. If a tagF property would be helpful on another class, it would be easy to add.
See the description of the tag property above for additional comments.
tagL0 <–> (logical$)
A user-defined logical value (see also tag and tagF). The value of tagL0 is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tagL0 is not used by SLiM; it is free for you to use. See also the getValue() and setValue() methods (provided by the Dictionary class; see the Eidos manual), for another way of attaching state to individuals.
tagL1 <–> (logical$)
A user-defined logical value (see also tag and tagF). The value of tagL1 is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tagL1 is not used by SLiM; it is free for you to use. See also the getValue() and setValue() methods (provided by the Dictionary class; see the Eidos manual), for another way of attaching state to individuals.
tagL2 <–> (logical$)
A user-defined logical value (see also tag and tagF). The value of tagL2 is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tagL2 is not used by SLiM; it is free for you to use. See also the getValue() and setValue() methods (provided by the Dictionary class; see the Eidos manual), for another way of attaching state to individuals.
tagL3 <–> (logical$)
A user-defined logical value (see also tag and tagF). The value of tagL3 is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tagL3 is not used by SLiM; it is free for you to use. See also the getValue() and setValue() methods (provided by the Dictionary class; see the Eidos manual), for another way of attaching state to individuals.
tagL4 <–> (logical$)
A user-defined logical value (see also tag and tagF). The value of tagL4 is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tagL4 is not used by SLiM; it is free for you to use. See also the getValue() and setValue() methods (provided by the Dictionary class; see the Eidos manual), for another way of attaching state to individuals.
uniqueMutations => (object<Mutation>)
All of the Mutation objects present in this individual. Mutations present in both genomes will occur only once in this property, and the mutations will be given in sorted order by position, so this property is similar to sortBy(unique(individual.genomes.mutations), "position"). It is not identical to that call, only because if multiple mutations exist at the exact same position, they may be sorted differently by this method than they would be by sortBy(). This method is provided primarily for speed; it executes much faster than the Eidos equivalent above. Indeed, it is faster than just individual.genomes.mutations, and gives uniquing and sorting on top of that, so it is advantageous unless duplicate entries for homozygous mutations are actually needed.
x <–> (float$)
A user-defined float value. The value of x is initially undefined (i.e., has an effectively random value that could be different every time you run your model); if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of x is not used by SLiM unless the optional “continuous space” facility is enabled with the dimensionality parameter to initializeSLiMOptions(), in which case x will be understood to represent the x coordinate of the individual in space. If continuous space is not enabled, you may use x as an additional tag value of type float.
xy => (float)
This property provides joint read-only access to the x and y properties; they are returned as a two-element float vector. This can be useful in complex spatial models in which the spatiality of interactions/maps differs from the overall dimensionality of the model. See the documentation for the separate properties x and y for further comments.
xyz => (float)
This property provides joint read-only access to the x, y, and z properties; they are returned as a three-element float vector. This can be useful in complex spatial models in which the spatiality of interactions/maps differs from the overall dimensionality of the model. See the documentation for the separate properties x, y, and z for further comments.
xz => (float)
This property provides joint read-only access to the x and z properties; they are returned as a two-element float vector. This can be useful in complex spatial models in which the spatiality of interactions/maps differs from the overall dimensionality of the model. See the documentation for the separate properties x and z for further comments.
y <–> (float$)
A user-defined float value. The value of y is initially undefined (i.e., has an effectively random value that could be different every time you run your model); if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of y is not used by SLiM unless the optional “continuous space” facility is enabled with the dimensionality parameter to initializeSLiMOptions(), in which case y will be understood to represent the y coordinate of the individual in space (if the dimensionality is "xy" or "xyz"). If continuous space is not enabled, or the dimensionality is not "xy" or "xyz", you may use y as an additional tag value of type float.
yz => (float)
This property provides joint read-only access to the y and z properties; they are returned as a two-element float vector. This can be useful in complex spatial models in which the spatiality of interactions/maps differs from the overall dimensionality of the model. See the documentation for the separate properties y and z for further comments.
z <–> (float$)
A user-defined float value. The value of z is initially undefined (i.e., has an effectively random value that could be different every time you run your model); if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of z is not used by SLiM unless the optional “continuous space” facility is enabled with the dimensionality parameter to initializeSLiMOptions(), in which case z will be understood to represent the z coordinate of the individual in space (if the dimensionality is "xyz"). If continuous space is not enabled, or the dimensionality is not "xyz", you may use z as an additional tag value of type float.
5.7.2 Individual methods
– (logical)containsMutations(object<Mutation> mutations)
Returns a logical vector indicating whether each of the mutations in mutations is present in the individual (in either of its genomes); each element in the returned vector indicates whether the corresponding mutation is present (T) or absent (F). This method is provided for speed; it is much faster than the corresponding Eidos code.
– (integer$)countOfMutationsOfType(io<MutationType>$ mutType)
Returns the number of mutations that are of the type specified by mutType, out of all of the mutations in the individual (in both of its genomes; a mutation that is present in both genomes counts twice). If you need a vector of the matching Mutation objects, rather than just a count, use the Genome method -mutationsOfType(). This method is provided for speed; it is much faster than the corresponding Eidos code.
– (float)relatedness(object<Individual> individuals)
Returns a vector containing the degrees of relatedness between the receiver and each of the individuals in individuals. The relatedness between A and B is always 1.0 if A and B are actually the same individual; this facility works even if SLiM’s optional pedigree tracking is not enabled (in which case all other relatedness values will be 0.0). Otherwise, if pedigree tracking is turned on with initializeSLiMOptions(keepPedigrees=T), this method will use the pedigree information to construct a relatedness estimate.
More specifically, this method uses all available pedigree information from the grandparental and parental pedigree records of A and B to compute an estimate of the degree of consanguinity between A and B. Siblings have a relatedness of 0.5, as do parents to their children and vice versa; cousins have a relatedness of 0.125; and so forth. If, according to the pedigree information available, A and B have no blood relationship, the value returned is 0.0. Note that the value returned by relatedness() is what is called the “coefficient of relationship” between the two individuals (Wright, 1922; https://doi.org/10.1086/279872), and ranges from 0.0 to 1.0.
There is another commonly used metric of relatedness, called the “kinship coefficient”, that reflects the probability of identity by descent between two individuals A and B. In general, it is approximately equal to one-half of the coefficient of relationship; if an approximate estimate of the kinship coefficient is acceptable, especially in models in which individuals are expected to be outbred, you can simply divide relatedness() by two. However, it should be noted that Wright’s coefficient of relationship is not a measure of the probability of identity by descent, and so it is not exactly double the kinship coefficient; they actually measure different things. More precisely, the relationship between them is r = 2φ/sqrt((1+fA)(1+fB)), where r is Wright’s coefficient of relatedness, φ is the kinship coefficient, and fA and fB are the inbreeding coefficients of A and B respectively.
Note that this relatedness is simply pedigree-based relatedness, and does not necessarily correspond to genetic relatedness, because of the effects of factors like assortment and recombination. If a metric of actual genetic relatedness is desired, tree-sequence recording can be used after simulation is complete, to compute the exact genetic relatedness between individuals based upon the complete ancestry tree (a topic which is beyond the scope of this manual). Actual genetic relatedness cannot presently be calculated during a simulation run; the information is implicitly contained in the recorded tree-sequence tables, but calculating it is too computationally expensive to be reasonable.
This method assumes that the grandparents (or the parents, if grandparental information is not available) are themselves unrelated and that they are not inbred; this assumption is necessary because we have no information about their parentage, since SLiM’s pedigree tracking information only goes back two generations. Be aware that in a model where inbreeding or selfing occurs at all (including “incidental selfing”, where a hermaphroditic individual happens to choose itself as a mate), some level of “background relatedness” will be present and this assumption will be violated. In such circumstances, relatedness() will therefore tend to underestimate the degree of relatedness between individuals, and the greater the degree of inbreeding, the greater the underestimation will be. If inbreeding is allowed in a model – and particularly if it is common – the results of relatedness() should therefore not be taken as an estimate of absolute relatedness, but can still be useful as an estimate of relative relatedness (indicating that, say, A appears from the information available to be more closely related to B than it is to C).
See also sharedParentCount() for a different metric of relatedness.
+ (void)setSpatialPosition(float position)
Sets the spatial position of the individual (as accessed through the spatialPosition property). The length of position (the number of coordinates in the spatial position of an individual) depends upon the spatial dimensionality declared with initializeSLiMOptions(). If the spatial dimensionality is zero (as it is by default), it is an error to call this method. The elements of position are set into the values of the x, y, and z properties (if those properties are encompassed by the spatial dimensionality of the simulation). In other words, if the declared dimensionality is "xy", calling individual.setSpatialPosition(c(1.0, 0.5)) property is equivalent to individual.x = 1.0; individual.y = 0.5; individual.z is not set (even if a third value is supplied in position) since it is not encompassed by the simulation’s dimensionality in this example.
Note that this is an Eidos class method, somewhat unusually, which allows it to work in a special way when called on a vector of individuals. When the target vector of individuals is non-singleton, this method can do one of two things. If position contains just a single point (i.e., is equal in length to the spatial dimensionality of the model), the spatial position of all of the target individuals will be set to the given point. Alternatively, if position contains one point per target individual (i.e., is equal in length to the number of individuals multiplied by the spatial dimensionality of the model), the spatial position of each target individual will be set to the corresponding point from position (where the point data is concatenated, not interleaved, just as it would be returned by accessing the spatialPosition property on the vector of target individuals). Calling this method with a position vector of any other length is an error.
– (integer)sharedParentCount(object<Individual> individuals)
Returns a vector containing the number of parents shared between the receiver and each of the individuals in individuals. The number of shared parents between A and B is always 2 if A and B are actually the same individual; this facility works even if SLiM’s optional pedigree tracking is not enabled (in which case all other relatedness values will be 0). Otherwise, if pedigree tracking is turned on with initializeSLiMOptions(keepPedigrees=T), this method will use the pedigree information to construct a relatedness estimate.
More specifically, this method uses the parental pedigree IDs from the pedigree records of a pair of individuals to count the number of shared parents between them, such that full siblings (with all of the same parents) have a count of 2, and half siblings (with half of the same parents) have a count of 1. If possible parents of the two individuals are A, B, C, and D, then the shared parent count is as follows, for some illustrative examples. The first column showing the two parents of the first individual, the second column showing the two parents of the second individual; note that the two parents of an individual can be the same due to cloning or selfing:
AB CD → 0 (no shared parents)
AB CC → 0 (no shared parents)
AB AC → 1 (half siblings)
AB AA → 1 (half siblings)
AA AB → 1 (half siblings)
AB AB → 2 (full siblings)
AB BA → 2 (full siblings)
AA AA → 2 (full siblings)
This method does not estimate consanguinity. For example, if one individual is itself a parent of the other individual, that is irrelevant for this method. Similarly, in simulations of sex chromosomes, the sexes of the parents are irrelevant, even if no genetic material would have been inherited from a given parent. See relatedness() for an assessment of pedigree-based relatedness that does estimate the consanguinity of individuals. The sharedParentCount() method is preferable if your exact question is simply whether individuals are full siblings, half siblings, or non-siblings; in other cases, relatedness() is probably more useful.
– (float$)sumOfMutationsOfType(io<MutationType>$ mutType)
Returns the sum of the selection coefficients of all mutations that are of the type specified by mutType, out of all of the mutations in the genomes of the individual. This is often useful in models that use a particular mutation type to represent QTLs with additive effects; in that context, sumOfMutationsOfType() will provide the sum of the additive effects of the QTLs for the given mutation type. This method is provided for speed; it is much faster than the corresponding Eidos code. Note that this method also exists on Genome, for cases in which the sum for just one genome is desired.
– (object<Mutation>)uniqueMutationsOfType(io<MutationType>$ mutType)
Returns an object vector of all the mutations that are of the type specified by mutType, out of all of the mutations in the individual. Mutations present in both genomes will occur only once in the result of this method, and the mutations will be given in sorted order by position, so this method is similar to sortBy(unique(individual.genomes.mutationsOfType(mutType)), "position"). It is not identical to that call, only because if multiple mutations exist at the exact same position, they may be sorted differently by this method than they would be by sortBy(). If you just need a count of the matching Mutation objects, rather than a vector of the matches, use -countOfMutationsOfType(). This method is provided for speed; it is much faster than the corresponding Eidos code. Indeed, it is faster than just individual.genomes.mutationsOfType(mutType), and gives uniquing and sorting on top of that, so it is advantageous unless duplicate entries for homozygous mutations are actually needed.
5.8 Class InteractionType
5.8.1 InteractionType properties
id => (integer$)
The identifier for this interaction type; for interaction type i3, for example, this is 3.
maxDistance <–> (float$)
The maximum distance over which this interaction will be evaluated. For inter-individual distances greater than maxDistance, the interaction strength will be zero.
reciprocal => (logical$)
The reciprocality of the interaction, as specified in initializeInteractionType(). This will be T for reciprocal interactions (those for which the interaction strength of B upon A is equal to the interaction strength of A upon B), and F otherwise.
sexSegregation => (string$)
The sex-segregation of the interaction, as specified in initializeInteractionType() or with setConstraints(). For non-sexual simulations, this will be "**". For sexual simulations, this string value indicates the sex of individuals feeling the interaction, and the sex of individuals exerting the interaction; see initializeInteractionType() for details.
spatiality => (string$)
The spatial dimensions used by the interaction, as specified in initializeInteractionType(). This will be "" (the empty string) for non-spatial interactions, or "x", "y", "z", "xy", "xz", "yz", or "xyz", for interactions using those spatial dimensions respectively. The specified dimensions are used to calculate the distances between individuals for this interaction. The value of this property is always the same as the value given to initializeInteractionType().
tag <–> (integer$)
A user-defined integer value. The value of tag is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tag is not used by SLiM; it is free for you to use. See also the getValue() and setValue() methods (provided by the Dictionary class; see the Eidos manual), for another way of attaching state to interaction types.
5.8.2 InteractionType methods
– (float)clippedIntegral(No<Individual> receivers)
Returns a vector containing the integral of the interaction function as experienced by each of the individuals in receivers. For each given individual, the interaction function is clipped to the edges of the spatial bounds of the subpopulation that individual inhabits; the individual’s spatial position must be within bounds or an error is raised. A periodic boundary will, correctly, not clip the interaction function. The interaction function is also clipped to the interaction’s maximum distance; that distance must be less than half of the extent of the spatial bounds in each dimension (so that, for a given dimension, the interaction function is clipped by the spatial bounds on only one side), otherwise an error is raised. Note that receiver constraints are not applied; an individual might not actually receive any interactions because of those constraints, but it is still considered to have the same interaction function integral. If receivers is NULL, the maximal integral is returned, as would be experienced by an individual farther than the maximum distance from any edge. The evaluate() method must have been previously called for the receiver subpopulation, and positions saved at evaluation time will be used. If the InteractionType is non-spatial, this method may not be called.
The computed value of the integral is not exact; it is calculated by an approximate numerical method designed to be fast, but the error should be fairly small (typically less than 1% from the true value). A large amount of computation will occur the first time this method is called (perhaps taking more than a second, depending upon hardware), but subsequent calls should be very fast. This method does not invoke interaction() callbacks; the calculated integrals are only for the interaction function itself, and so will not be accurate if interaction() callbacks modify the relationship between distance and interaction strength. For this reason, the overhead of the first call will not reoccur when individuals move or when the interaction is re-evaluated; for typical models, the initial overhead will be incurred only once. The initial overhead will reoccur, however, if the interaction function itself, or the maximum interaction distance, are changed; frequent change of those parameters may render the performance of this method unacceptable.
The integral values returned by clippedIntegral() can be useful for computing interaction metrics that are scaled by the amount of “interaction field” (to coin a term) that is present for a given individual, producing metrics of interaction density. Notably, the localPopulationDensity() method automatically incorporates the mechanics of clippedIntegral() into the calculations it performs; see that method’s documentation for further discussion of this concept. This approach can also be useful with the interactingNeighborCount() method, provided that the interaction function is of type "f" (since the neighbor count does not depend upon interaction strength).
– (float)distance(object<Individual>$ receiver, [No<Individual> exerters = NULL])
Returns a vector containing distances between receiver and the individuals in exerters. If exerters is NULL (the default), then a vector of the distances from receiver to all individuals in its subpopulation (including itself) is returned; this case may be handled differently internally, for greater speed, so supplying NULL is preferable to supplying the vector of all individuals in the subpopulation explicitly. Otherwise, all individuals in exerters must belong to a single subpopulation (but not necessarily the same subpopulation as receiver). The evaluate() method must have been previously called for the receiver and exerter subpopulations, and positions saved at evaluation time will be used. If the InteractionType is non-spatial, this method may not be called.
Importantly, distances are calculated according to the spatiality of the InteractionType (as declared in initializeInteractionType()), not the dimensionality of the model as a whole (as declared in initializeSLiMOptions()). The distances returned are therefore the distances that would be used to calculate interaction strengths. However, distance() will return finite distances for all pairs of individuals, even if the individuals are non-interacting due to the maximum interaction distance or the interaction constraints; the distance() between an individual and itself will thus be 0. See interactionDistance() for an alternative distance definition.
– (float)distanceFromPoint(float point, object<Individual> exerters)
Returns a vector containing distances between the point given by the spatial coordinates in point, which may be thought of as the “receiver”, and individuals in exerters. The point vector is interpreted as providing coordinates precisely as specified by the spatiality of the interaction type; if the interaction type’s spatiality is "xz", for example, then point[0] is assumed to be an x value, and point[1] is assumed to be a z value. Be careful; this means that in general it is not safe to pass an individual’s spatialPosition property for point, for example (although it is safe if the spatiality of the interaction matches the dimensionality of the simulation). A coordinate for a periodic spatial dimension must be within the spatial bounds for that dimension, since coordinates outside of periodic bounds are meaningless (pointPeriodic() may be used to ensure this); coordinates for non-periodic spatial dimensions are not restricted. All individuals in exerters must belong to a single subpopulation; the evaluate() method must have been previously called for that subpopulation, and positions saved at evaluation time will be used. If the InteractionType is non-spatial, this method may not be called. The vector point must be exactly as long as the spatiality of the InteractionType.
Importantly, distances are calculated according to the spatiality of the InteractionType (as declared in initializeInteractionType()) not the dimensionality of the model as a whole (as declared in initializeSLiMOptions()). The distances are therefore interaction distances: the distances that are used to calculate interaction strengths. However, the maximum interaction distance and interaction constraints are not used.
This method replaces the distanceToPoint() method that existed prior to SLiM 4.
– (object)drawByStrength(object<Individual> receiver, [integer$ count = 1], [No<Subpopulation>$ exerterSubpop = NULL], [logical$ returnDict = F])
Returns an object<Individual> vector containing up to count individuals drawn from exerterSubpop, or if that is NULL (the default), then from the subpopulation of receiver, which must be singleton in the default mode of operation (but see below). The probability of drawing particular individuals is proportional to the strength of interaction they exert upon receiver (which is zero for receiver itself). All exerters must belong to a single subpopulation (but not necessarily the same subpopulation as receiver). The evaluate() method must have been previously called for the receiver and exerter subpopulations, and positions saved at evaluation time will be used.
This method may be used with either spatial or non-spatial interactions, but will be more efficient with spatial interactions that set a short maximum interaction distance. Draws are done with replacement, so the same individual may be drawn more than once; sometimes using unique() on the result of this call is therefore desirable. If more than one draw will be needed, it is much more efficient to use a single call to drawByStrength(), rather than drawing individuals one at a time. Note that if no individuals exert a non-zero interaction strength upon receiver, the vector returned will be zero-length; it is important to consider this possibility.
Beginning in SLiM 4.1, this method has a vectorized mode of operation in which the receiver parameter may be non-singleton. To switch the method to this mode, pass T for returnDict, rather than the default of F (the operation of which is described above). In this mode, the return value is a Dictionary object instead of a vector of Individual objects. This dictionary uses integer keys that range from 0 to N-1, where N is the number of individuals passed in receiver; these keys thus correspond directly to the indices of the individuals in receiver, and there is one entry in the dictionary for each receiver. The value in the dictionary, for a given integer key, is an object<Individual> vector with the individuals drawn for the corresponding receiver, exactly as described above for the non-vectorized case. The results for each receiver can therefore be obtained from the returned dictionary with getValue(), passing the index of the receiver. The speed of this mode of operation will probably be similar to the speed of making N separate non-vectorized calls to drawByStrength(), when running single-threaded. When running multi-threaded, however, a substantial performance improvement may be realized by using the vectorized version of this method, since the queries can then be executed in parallel. In this mode of operation, all receivers must belong to the same subpopulation.
– (void)evaluate(io<Subpopulation> subpops)
Snapshots model state in preparation for the use of the interaction, for the receiver and exerter subpopulations specified by subpops. The subpopulations may be supplied either as integer IDs, or as Subpopulation objects. This method will discard all previously cached data for the subpopulation(s), and will cache the current spatial positions of all individuals they contain (so that the spatial positions of those individuals may then change without disturbing the state of the interaction at the moment of evaluation). It will also cache which individuals in the subpopulation are eligible to act as exerters, according to the configured exerter constraints, but it will not cache such eligibility information for receiver constraints (which are applied at the time a spatial query is made). Particular interaction distances and strengths are not computed by evaluate(), and interaction() callbacks will not be called in response to this method; that work is deferred until required to satisfy a query (at which point the tick and cycle counters may have advanced, so be careful with the tick ranges used in defining interaction() callbacks).
You must explicitly call evaluate() at an appropriate time in the tick cycle before the interaction is used, but after any relevant changes have been made to the population. SLiM will invalidate any existing interactions after any portion of the tick cycle in which new individuals have been born or existing individuals have died. In a WF model, this occurs just before late() events execute (see the WF tick cycle diagram in chapter 23), so late() events are often the appropriate place to put evaluate() calls, but first() or early() events can work too if the interaction is not needed until that point in the tick cycle anyway. In nonWF models, on the other hand, new offspring are produced just before early() events and then individuals die just before late() events (see the nonWF tick cycle diagram in chapter 24), so interactions will be invalidated twice during each tick cycle. This means that in a nonWF model, an interaction that influences reproduction should usually be evaluated in a first() event, while an interaction that influences fitness or mortality should usually be evaluated in an early() event (and an interaction that affects both may need to be evaluated at both times).
If an interaction is never evaluated for a given subpopulation, it is guaranteed that there will be essentially no memory or computational overhead associated with the interaction for that subpopulation. Furthermore, attempting to query an interaction for a receiver or exerter in a subpopulation that has not been evaluated is guaranteed to raise an error.
– (integer)interactingNeighborCount(object<Individual> receivers, [No<Subpopulation>$ exerterSubpop = NULL])
Returns the number of interacting individuals for each individual in receivers, within the maximum interaction distance according to the distance metric of the InteractionType, from among the exerters in exerterSubpop (or, if that is NULL, then from among all individuals in the receiver’s subpopulation). More specifically, this method counts the number of individuals which can exert an interaction upon each receiver (which does not include the receiver itself). All of the receivers must belong to a single subpopulation, and all of the exerters must belong to a single subpopulation, but those two subpopulations do not need to be the same. The evaluate() method must have been previously called for the receiver and exerter subpopulations, and positions saved at evaluation time will be used.
This method is similar to nearestInteractingNeighbors() (when passed a large count so as to guarantee that all interacting individuals are returned), but this method returns only a count of the interacting individuals, not a vector containing the individuals.
Note that this method uses interaction eligibility as a criterion; it will not count neighbors that do not exert an interaction upon a given receiver (due to the configured receiver or exerter constraints). (It also does not count a receiver as a neighbor of itself.) If a count of all neighbors is desired, rather than just interacting neighbors, use neighborCount(). If the InteractionType is non-spatial, this method may not be called.
– (float)interactionDistance(object<Individual>$ receiver, [No<Individual> exerters = NULL])
Returns a vector containing interaction-dependent distances between receiver and individuals in exerters. If exerters is NULL (the default), then a vector of the interaction-dependent distances from receiver to all individuals in its subpopulation (including receiver itself) is returned; this case may be handled much more efficiently than if a vector of all individuals in the subpopulation is explicitly provided. Otherwise, all individuals in exerters must belong to a single subpopulation (but not necessarily the same subpopulation as receiver). The evaluate() method must have been previously called for the receiver and exerter subpopulations, and positions saved at evaluation time will be used. If the InteractionType is non-spatial, this method may not be called.
Importantly, distances are calculated according to the spatiality of the InteractionType (as declared in initializeInteractionType()), not the dimensionality of the model as a whole (as declared in initializeSLiMOptions()). The distances returned are therefore the distances that would be used to calculate interaction strengths. In addition, interactionDistance() will return INF as the distance between receiver and any individual which does not exert an interaction upon receiver; the interactionDistance() between an individual and itself will thus be INF, and likewise for pairs excluded from interacting by receiver constraints, exerter constraints, or the maximum interaction distance of the interaction type. See distance() for an alternative distance definition.
– (float)localPopulationDensity(object<Individual> receivers, [No<Subpopulation>$ exerterSubpop = NULL])
Returns a vector of the local population density present at the location of each individual in receivers, which does not need to be a singleton; indeed, it can be a vector of all of the individuals in a given subpopulation. However, all receivers must be in the same subpopulation. The local population density is computed from exerters in exerterSubpop, or if that is NULL (the default), then from the receiver’s subpopulation. The evaluate() method must have been previously called for the receiver and exerter subpopulations, and positions saved at evaluation time will be used.
Population density is estimated using interaction strengths, effectively doing a kernel density estimate using the interaction function as the kernel. What is returned is computed as the total interaction strength present at a given point, divided by the integral of the interaction function around that point after clipping by the spatial bounds of the exerter subpopulation (what one might think of as the amount of “interaction field” around the point). This provides an estimate of local population density, in units of individuals per unit area, as a weighted average over the area covered by the interaction function, where the weight of each exerter in the average is the value of the interaction function at that exerter’s position. This can also be thought of as a measure of the amount of interaction happening per unit of interaction field in the space surrounding the point.
To calculate the clipped integral of the interaction function, this method uses the same numerical estimator used by the clippedIntegral() method of InteractionType, and all of the caveats described for that method apply here also; notably, all individuals must be within spatial bounds, the maximum interaction distance must be less than half the spatial extent of the subpopulation, and interaction() callbacks are not used (and so, for this method, are not allowed to be active). See the documentation for clippedIntegral() for further discussion of the details of these calculations.
To calculate the total interaction strength around the position of a receiver, this method uses the same machinery as the totalOfNeighborStrengths() method of InteractionType, except that – in contrast to other InteractionType methods – the interaction strength exerted by the receiver itself is included in the total (if the exerter subpopulation is the receiver’s own subpopulation). This is because population density at the location of an individual includes the individual itself. If this is not desirable, the totalOfNeighborStrengths() method should probably be used.
To see the point of this method, consider a receiver located near the edge of the spatial bounds of its subpopulation. Some portion of the interaction function that surrounds that receiver falls outside the spatial bounds of its subpopulation, and will therefore never contain an interacting exerter. If, for example, interaction strengths are used as a measure of competition, this receiver will therefore have an advantage, because it will never feel any competition from the portion of its range that falls outside spatial bounds. However, that portion of its range is presumably also not available to the receiver itself, for foraging or hunting, in which case this advantage is not biologically realistic, but is instead just an undesirable “edge effect” artifact. Dividing by the integral of the interaction function, clipped to the spatial bounds, provides a way to compensate for this edge effect. A nice side effect of using local population densities instead of total interaction strengths is that the maximum interaction strength passed to setInteractionFunction() no longer matters; it cancels out when the total interaction strength is divided by the receiver’s clipped integral. However, the shape of the interaction function does still matter; it determines the relative weights used for exerters at different distances from the position of the receiver.
– (object)nearestInteractingNeighbors(object<Individual> receiver, [integer$ count = 1], [No<Subpopulation>$ exerterSubpop = NULL], [logical$ returnDict = F])
Returns an object<Individual> vector containing up to count interacting individuals that are spatially closest to receiver, according to the distance metric of the InteractionType, from among the exerters in exerterSubpop (or, if that is NULL, then from among all individuals in the receiver’s subpopulation). More specifically, this method returns only individuals which can exert an interaction upon receiver, which must be singleton in the default mode of operation (but see below). To obtain all of the interacting individuals within the maximum interaction distance of receiver, simply pass a value for count that is greater than or equal to the size of the exerter subpopulation. Note that if fewer than count interacting individuals are within the maximum interaction distance, the vector returned may be shorter than count, or even zero-length; it is important to check for this possibility even when requesting a single neighbor. If only the number of interacting individuals is needed, use interactingNeighborCount() instead. The evaluate() method must have been previously called for the receiver and exerter subpopulations, and positions saved at evaluation time will be used. If the InteractionType is non-spatial, this method may not be called.
Note that this method uses interaction eligibility as a criterion; it will not return neighbors that cannot exert an interaction upon the receiver (due to the configured receiver or exerter constraints). (It will also never return the receiver as a neighbor of itself.) To find all neighbors of a receiver, whether they can interact with it or not, use nearestNeighbors().
Beginning in SLiM 4.1, this method has a vectorized mode of operation in which the receiver parameter may be non-singleton. To switch the method to this mode, pass T for returnDict, rather than the default of F (the operation of which is described above). In this mode, the return value is a Dictionary object instead of a vector of Individual objects. This dictionary uses integer keys that range from 0 to N-1, where N is the number of individuals passed in receiver; these keys thus correspond directly to the indices of the individuals in receiver, and there is one entry in the dictionary for each receiver. The value in the dictionary, for a given integer key, is an object<Individual> vector with the interacting neighbors found for the corresponding receiver, exactly as described above for the non-vectorized case. The results for each receiver can therefore be obtained from the returned dictionary with getValue(), passing the index of the receiver. The speed of this mode of operation will probably be similar to the speed of making N separate non-vectorized calls to nearestInteractingNeighbors(), when running single-threaded. When running multi-threaded, however, a substantial performance improvement may be realized by using the vectorized version of this method, since the queries can then be executed in parallel. In this mode of operation, all receivers must belong to the same subpopulation.
– (object)nearestNeighbors(object<Individual> receiver, [integer$ count = 1], [No<Subpopulation>$ exerterSubpop = NULL], [logical$ returnDict = F])
Returns an object<Individual> vector containing up to count individuals that are spatially closest to receiver, according to the distance metric of the InteractionType, from among the exerters in exerterSubpop (or, if that is NULL, then from among all individuals in the receiver’s subpopulation). In the default mode of operation, receiver must be singleton (but see below). To obtain all of the individuals within the maximum interaction distance of receiver, simply pass a value for count that is greater than or equal to the size of individual’s subpopulation. Note that if fewer than count individuals are within the maximum interaction distance, the vector returned may be shorter than count, or even zero-length; it is important to check for this possibility even when requesting a single neighbor. The evaluate() method must have been previously called for the receiver and exerter subpopulations, and positions saved at evaluation time will be used. If the InteractionType is non-spatial, this method may not be called.
Note that this method does not use interaction eligibility as a criterion; it will return neighbors that could not interact with the receiver due to the configured receiver or exerter constraints. (It will never return the receiver as a neighbor of itself, however.) To find only neighbors that are eligible to exert an interaction upon the receiver, use nearestInteractingNeighbors().
Beginning in SLiM 4.1, this method has a vectorized mode of operation in which the receiver parameter may be non-singleton. To switch the method to this mode, pass T for returnDict, rather than the default of F (the operation of which is described above). In this mode, the return value is a Dictionary object instead of a vector of Individual objects. This dictionary uses integer keys that range from 0 to N-1, where N is the number of individuals passed in receiver; these keys thus correspond directly to the indices of the individuals in receiver, and there is one entry in the dictionary for each receiver. The value in the dictionary, for a given integer key, is an object<Individual> vector with the neighbors found for the corresponding receiver, exactly as described above for the non-vectorized case. The results for each receiver can therefore be obtained from the returned dictionary with getValue(), passing the index of the receiver. The speed of this mode of operation will probably be similar to the speed of making N separate non-vectorized calls to nearestNeighbors(), when running single-threaded. When running multi-threaded, however, a substantial performance improvement may be realized by using the vectorized version of this method, since the queries can then be executed in parallel. In this mode of operation, all receivers must belong to the same subpopulation.
– (object<Individual>)nearestNeighborsOfPoint(float point, io<Subpopulation>$ exerterSubpop, [integer$ count = 1])
Returns up to count individuals in exerterSubpop that are spatially closest to point, according to the distance metric of the InteractionType. The subpopulation may be supplied either as an integer ID, or as a Subpopulation object. To obtain all of the individuals within the maximum interaction distance of point, simply pass a value for count that is greater than or equal to the size of exerterSubpop. Note that if fewer than count individuals are within the maximum interaction distance, the vector returned may be shorter than count, or even zero-length; it is important to check for this possibility even when requesting a single neighbor. The evaluate() method must have been previously called for exerterSubpop, and positions saved at evaluation time will be used. If the InteractionType is non-spatial, this method may not be called.
– (integer)neighborCount(object<Individual> receivers, [No<Subpopulation>$ exerterSubpop = NULL])
Returns the number of neighbors for each individual in receivers, within the maximum interaction distance according to the distance metric of the InteractionType, from among the individuals in exerterSubpop (or, if that is NULL, then from among all individuals in the receiver’s subpopulation). All of the receivers must belong to a single subpopulation, and all of the exerters must belong to a single subpopulation, but those two subpopulations do not need to be the same. The evaluate() method must have been previously called for the receiver and exerter subpopulations, and positions saved at evaluation time will be used.
This method is similar to nearestNeighbors() (when passed a large count so as to guarantee that all neighbors are returned), but this method returns only a count of the individuals, not a vector containing the individuals.
Note that this method does not use interaction eligibility as a criterion; it will count neighbors that cannot exert an interaction upon a receiver (due to the configured receiver or exerter constraints). (It still does not count a receiver as a neighbor of itself, however.) If a count of only interacting neighbors is desired, use interactingNeighborCount(). If the InteractionType is non-spatial, this method may not be called.
– (integer$)neighborCountOfPoint(float point, io<Subpopulation>$ exerterSubpop)
Returns the number of individuals in exerterSubpop that are within the maximum interaction distance according to the distance metric of the InteractionType. The subpopulation may be supplied either as an integer ID, or as a Subpopulation object. The evaluate() method must have been previously called for exerterSubpop, and positions saved at evaluation time will be used. If the InteractionType is non-spatial, this method may not be called.
This method is similar to nearestNeighborsOfPoint() (when passed a large count so as to guarantee that all neighbors are returned), but this method returns only a count of the individuals, not a vector containing the individuals.
– (void)setConstraints(string$ who, [Ns$ sex = NULL], [Ni$ tag = NULL], [Ni$ minAge = NULL], [Ni$ maxAge = NULL], [Nl$ migrant = NULL], [Nl$ tagL0 = NULL], [Nl$ tagL1 = NULL], [Nl$ tagL2 = NULL], [Nl$ tagL3 = NULL], [Nl$ tagL4 = NULL])
Sets constraints upon which individuals can be receivers and/or exerters, making the target InteractionType measure interactions between only subsets of the population. The parameter who specifies upon whom the specified constraints apply; it may be "exerter" to set constraints upon exerters, "receiver" to set constraints upon receivers, or "both" to set constraints upon both. If "both" is used, the same constraints are set for both exerters and receivers; different constraints can be set for exerters versus receivers by making a separate call to setConstraints() for each. Constraints only affect queries that involve the concept of interaction; for example, they will affect the result of nearestInteractingNeighbors(), but not the result of nearestNeighbors(). The constraints specified by a given call to setConstraints() override all previously set constraints for the category specified (receivers, exerters, or both).
There is a general policy for the remaining arguments: they are NULL by default, and if NULL is used, it specifies “no constraint” for that property (removing any currently existing constraint for that property). The sex parameter constrains the sex of individuals; it may be "M" or “F" (or "*" as another way of specifying no constraint, for historical reasons). If sex is "M" or "F", the individuals to which the constraint is applied (potential receivers/exerters) must belong to a sexual species. The tag parameter constrains the tag property of individuals; if this set, the individuals to which the constraint is applied must have defined tag values. The minAge and maxAge properties constrain the age property of individuals to the given minimum and/or maximum values; these constraints can only be used in nonWF models. The migrant property constraints the migrant property of individuals (T constrains to only migrants, F to only non-migrants). Finally, the tagL0, tagL1, tagL2, tagL3, and tagL4 properties constrain the corresponding logical properties of individuals, requiring them to be either T or F as specified; the individuals to which these constraints are applied must have defined values for the constrained property or properties. Again, NULL should be supplied (as it is by default) for any property which you do not wish to constrain.
These constraints may be used in any combination, as desired. For example, calling setConstraints("receivers", sex="M", minAge=5, tagL0=T) constrains the interaction type’s operation so that receivers must be males, with an age of at least 5, with a tagL0 property value of T. For that configuration the potential receivers used with the interaction type must be sexual (since sex is specified), must be in a nonWF model (since minAge is specified), and must have a defined value for their tagL0 property (since that property is constrained). Note that the sexSegregation parameter to initializeInteractionType() is a shortcut which does the same thing as the corresponding calls to setConstraints().
Exerter constraints are applied at evaluate() time, whereas receiver constraints are applied at query time; see the InteractionType class documentation for further discussion. The interaction constraints for an interaction type are normally a constant in simulations; in any case, they cannot be changed when an interaction has already been evaluated, so either they should be set prior to evaluation, or unevaluate() should be called first.
– (void)setInteractionFunction(string$ functionType, ...)
Set the function used to translate spatial distances into interaction strengths for an interaction type. The functionType may be "f", in which case the ellipsis ... should supply a numeric$ fixed interaction strength; "l", in which case the ellipsis should supply a numeric$ maximum strength for a linear function; "e", in which case the ellipsis should supply a numeric$ maximum strength and a numeric$ lambda (rate) parameter for a negative exponential function; "n", in which case the ellipsis should supply a numeric$ maximum strength and a numeric$ sigma (standard deviation) parameter for a Gaussian function; "c", in which case the ellipsis should supply a numeric$ maximum strength and a numeric$ scale parameter for a Cauchy distribution function; or "t", in which case the ellipsis should supply a numeric$ maximum strength, a numeric$ degrees of freedom, and a numeric$ scale parameter for a t-distribution function. See the InteractionType class documentation for discussions of these interaction functions. Non-spatial interactions must use function type "f", since no distance values are available in that case.
The interaction function for an interaction type is normally a constant in simulations; in any case, it cannot be changed when an interaction has already been evaluated, so either it should be set prior to evaluation, or unevaluate() should be called first.
– (float)strength(object<Individual>$ receiver, [No<Individual> exerters = NULL])
Returns a vector containing the interaction strengths exerted upon receiver by the individuals in exerters. If exerters is NULL (the default), then a vector of the interaction strengths exerted by all individuals in the subpopulation of receiver (including receiver itself, with a strength of 0.0) is returned; this case may be handled much more efficiently than if a vector of all individuals in the subpopulation is explicitly provided. Otherwise, all individuals in exerters must belong to a single subpopulation (but not necessarily the same subpopulation as receiver). The evaluate() method must have been previously called for the receiver and exerter subpopulations, and positions saved at evaluation time will be used.
If the strengths of interactions exerted by a single individual upon multiple individuals are needed instead (the inverse of what this method provides), multiple calls to this method will be necessary, one per pairwise interaction queried; the interaction engine is not optimized for the inverse case, and so it will likely be quite slow to compute. If the interaction is reciprocal and has the same receiver and exerter constraints, the opposite query should provide identical results in a single efficient call (because then the interactions exerted are equal to the interactions received); otherwise, the best approach might be to define a second interaction type representing the inverse interaction that you wish to be able to query efficiently.
– (lo<Individual>)testConstraints(object<Individual> individuals, string$ constraints, [logical$ returnIndividuals = F])
Tests the individuals in the parameter individuals against the interaction constraints specified by constraints. The value of constraints may be "receiver" to use the receiver constraints, or "exerter" to use the exerter constraints. If returnIndividuals is F (the default), a logical vector will be returned, with T values indicating that the corresponding individual satisfied the constraints, F values indicating that it did not. If returnIndividuals is T, an object vector of class Individual will be returned containing only those elements of individuals that satisfied the constraints (in the same order as individuals). Note that unlike most queries, the InteractionType does not need to have been evaluated before calling this method, and the individuals passed in need not belong to a single population or even a single species.
This method can be useful for narrowing a vector of individuals down to just those that satisfy constraints. Outside the context of InteractionType, similar functionality is provided by the Subpopulation method subsetIndividuals(). Note that the use of testConstraints() is somewhat rare; usually, queries are evaluated across a vector of individuals, each of which might or might not satisfy the defined constraints. Individuals that do not satisfy constraints do not participate in interactions, so their interaction strength with other individuals will simply be zero.
See the setConstraints() method to set up constraints, as well as the sexSegregation parameter to initializeInteractionType(). Note that if the constraints tested involve tag values (including tagL0 / tagL1 / tagL2 / tagL3 / tagL4), the corresponding property or properties of the tested individuals must be defined (i.e., must have been set to a value), or an error will result because the constraints cannot be applied.
– (float)totalOfNeighborStrengths(object<Individual> receivers, [No<Subpopulation>$ exerterSubpop = NULL])
Returns a vector of the total interaction strength felt by each individual in receivers by the exerters in exerterSubpop (or, if that is NULL, then by all individuals in the receiver’s subpopulation). The receivers parameter does not need to be a singleton; indeed, it can be a vector of all of the individuals in a given subpopulation. All of the receivers must belong to a single subpopulation, and all of the exerters must belong to a single subpopulation, but those two subpopulations do not need to be the same. The evaluate() method must have been previously called for the receiver and exerter subpopulations, and positions saved at evaluation time will be used. If the InteractionType is non-spatial, this method may not be called.
For one individual, this is essentially the same as calling nearestInteractingNeighbors() with a large count so as to obtain the complete vector of all interacting neighbors, calling strength() for each of those interactions to get each interaction strength, and adding those interaction strengths together with sum(). This method is much faster than that implementation, however, since all of that work is done as a single operation. Also, totalOfNeighborStrengths() can total up interactions for more than one receiver in a single vectorized call.
Similarly, for one individual this is essentially the same as calling strength() to get the interaction strengths between a receiver and all individuals in the exerter subpopulation, and then calling sum(). Again, this method should be much faster, since this algorithm looks only at neighbors, whereas calling strength() directly assesses interaction strengths with all other individuals. This will make a particularly large difference when the subpopulation size is large and the maximum distance of the InteractionType is small.
See localPopulationDensity() for a related method that calculates the total interaction strength divided by the amount of “interaction field” present for an individual (i.e., the integral of the interaction function clipped to the spatial bounds of the subpopulation) to provide an estimate of the “interaction density” felt by an individual.
– (void)unevaluate(void)
Discards all evaluation of this interaction, for all subpopulations. The state of the InteractionType is reset to a state prior to evaluation. This can be useful if the model state has changed in such a way that the evaluation already conducted is no longer valid. For example, if the maximum distance, the interaction function, or the receiver or exerter constraints of the InteractionType need to be changed with immediate effect, or if the data used by an interaction() callback has changed in such a way that previously calculated interaction strengths are no longer correct, unevaluate() allows the interaction to begin again from scratch.
In WF models, all interactions are automatically reset to an unevaluated state at the moment when the new offspring generation becomes the parental generation (at step 4 in the tick cycle).
In nonWF models, all interactions are automatically reset to an unevaluated state twice per tick: immediately after reproduction() callbacks have completed (after step 1 in the tick cycle), and immediately before viability/survival selection (before step 4 in the tick cycle).
Given this automatic invalidation, most simulations have no reason to call unevaluate().
5.9 Class LogFile
5.9.1 LogFile properties
filePath => (string$)
The path of the log file being written to. This may be changed with setFilePath().
logInterval => (integer$)
The interval for automatic logging; a new row of data will be logged every logInterval ticks. This may be set with the logInterval parameter to createLogFile() and changed with setLogInterval(). If automatic logging has been disabled, this property will be 0.
precision <–> (integer$)
The precision of float output. To be exact, precision specifies the preferred number of significant digits that will be output for float values. The default is 6; values in [1,22] are legal, but 17 is probably the largest value that makes sense given the limits of double-precision floating point.
tag <–> (integer$)
A user-defined integer value. The value of tag is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tag is not used by SLiM; it is free for you to use.
5.9.2 LogFile methods
– (void)addCustomColumn(string$ columnName, string$ source, [* context = NULL])
Adds a new data column with its name provided by columnName. The new column will be logged each time that a row is generated, either by automatic logging or by a call to logRow(). The value for the column, when a given row is generated, will be produced by the code supplied in source, which is expected to return either NULL (which will write out NA), or a singleton value of any non-object type.
The context parameter will be set up as a pseudo-parameter, named context, when source is called, allowing the same source code to be used to generate values for multiple data columns; you might, for example, provide the particular Subpopulation object here that you wish source to use for its calculations. This is optional; if the default value of NULL is used, then context will be NULL when source is called.
See addMeanSDColumns() for a useful variant.
– (void)addCycle([No<Species>$ species = NULL])
Adds a new data column that provides the cycle counter for species (the same as the value of the cycle property of that species). The new column will be logged each time that a row is generated, either by automatic logging or by a call to logRow(). In single-species models, species may be NULL to indicate that single species. The column will simply be named cycle in single-species models; an underscore and the name of the species will be appended in multispecies models.
– (void)addCycleStage(void)
Adds a new data column that provides the cycle stage, named cycle_stage. The new column will be logged each time that a row is generated, either by automatic logging or by a call to logRow(). The stage is provided as a string, and will typically be "first", "early", "late", or "end" (the latter used for the point in time at which end-of-tick automatic logging occurs). Other possible values are discussed in the documentation for the cycleStage property of Community, which this column reflects.
– (void)addKeysAndValuesFrom(object$ source)
This Dictionary method has an override in LogFile to make it illegal to call, since LogFile manages its Dictionary entries.
– (void)addMeanSDColumns(string$ columnName, string$ source, [* context = NULL])
Adds two new data columns with names of columnName_mean and columnName_sd. The new columns will be logged each time that a row is generated, either by automatic logging or by a call to logRow(). When a given row is generated, the code supplied in source is expected to return either a zero-length vector of any type including NULL (which will write out NA to both columns), or a non-zero-length vector of integer or float values. In the latter case, the result vector will be summarized in the two columns by its mean and standard deviation respectively. If the result vector has exactly one value, the standard deviation will be written as NA. The context parameter is set up as a pseudo-parameter when source is called, as described in addCustomColumn().
– (void)addPopulationSexRatio([No<Species>$ species = NULL])
Adds a new data column that provides the population sex ratio M:(M+F) for species. The new column will be logged each time that a row is generated, either by automatic logging or by a call to logRow(). In single-species models, species may be NULL to indicate that single species. The column will simply be named sex_ratio in single-species models; an underscore and the name of the species will be appended in multispecies models. If the species is hermaphroditic, NA will be written.
– (void)addPopulationSize([No<Species>$ species = NULL])
Adds a new data column that provides the total population size for species. The new column will be logged each time that a row is generated, either by automatic logging or by a call to logRow(). In single-species models, species may be NULL to indicate that single species. The column will simply be named num_individuals in single-species models; an underscore and the name of the species will be appended in multispecies models.
– (void)addSubpopulationSexRatio(io<Subpopulation>$ subpop)
Adds a new data column that provides the sex ratio M:(M+F) of the subpopulation subpop, named pX_sex_ratio. The new column will be logged each time that a row is generated, either by automatic logging or by a call to logRow(). If the subpopulation exists but has a size of zero, NA will be written.
– (void)addSubpopulationSize(io<Subpopulation>$ subpop)
Adds a new data column that provides the size of the subpopulation subpop, named pX_num_individuals. The new column will be logged each time that a row is generated, either by automatic logging or by a call to logRow(). If the subpopulation exists but has a size of zero, 0 will be written.
– (void)addSuppliedColumn(string$ columnName)
Adds a new data column with its name provided by columnName. The new column will be logged each time that a row is generated, either by automatic logging or by a call to logRow(). The value for the column is initially undefined, and will be written as NA. A different value may (optionally) be provided by calling setSuppliedValue() with a value for columnName. That value will be used for the column the next time a row is generated (whether automatically or by a call to logRow()), and the column’s value will subsequently be undefined again. In other words, for any given logged row the default of NA may be kept, or a different value may be supplied. This allows the value for the column to be set at any point during the tick cycle, which can be convenient if the column’s value depends upon transient state that is no longer available at the time the row is logged.
– (void)addTick(void)
Adds a new data column, named tick, that provides the tick number for the simulation. The new column will be logged each time that a row is generated, either by automatic logging or by a call to logRow().
– (void)clearKeysAndValues(void)
This Dictionary method has an override in LogFile to make it illegal to call, since LogFile manages its Dictionary entries.
– (void)flush(void)
Flushes all buffered data to the output file, synchronously. This will make the contents of the file on disk be up-to-date with the running simulation. Flushing frequently may entail a small performance penalty. More importantly, if .gz compression has been requested with compress=T the size of the resulting file will be larger – potentially much larger – if flush() is called frequently. Note that automatic periodic flushing can be requested with the flushInterval parameter to createLogFile().
– (void)logRow(void)
This logs a new row of data, by evaluating all of the generators added to the LogFile with add...() calls. Note that the new row may be buffered, and thus may not be written out to disk immediately; see flush(). This method may be used instead of, or in conjunction with, automatic logging.
You can get the LogFile instance, in order to call logRow() on it, from community.logFiles, or you can remember it in a global constant with defineConstant().
– (void)setLogInterval([Ni$ logInterval = NULL])
Sets the automatic logging interval. A logInterval of NULL stops automatic logging immediately. Other values request that a new row should be logged (as if logRow() were called) at the end of every logInterval ticks (just before the tick count increment, in both WF and nonWF models), starting at the end of the tick in which setLogInterval() was called.
– (void)setFilePath(string$ filePath, [Ns initialContents = NULL], [logical$ append = F], [Nl$ compress = NULL], [Ns$ sep = NULL])
Redirects the LogFile to write new rows to a new filePath. Any rows that have been buffered but not flushed will be written to the previous file first, as if flush() had been called. With this call, new initialContents may be supplied, which will either replace any existing file or will be appended to it, depending upon the value of append. New values may be supplied for compress and sep; the meaning of these parameters is identical to their meaning in createLogFile(), except that a value of NULL for these means “do not change this setting from its previous value”. In effect, then, this method lets you start a completely new log file at a new path, without having to create and configure a new LogFile object. The new file will be created (or appended) synchronously, with the specified initial contents.
– (void)setSuppliedValue(string$ columnName, +$ value)
Registers a value, passed in value, to be used for the supplied column named columnName when a row is next logged. This column must have been added with addSuppliedColumn(). A value of NULL may be passed to log NA, but logging NA is the default behavior for supplied columns in any case. Otherwise, the value must be a singleton, and its type should match the values previously supplied for the column (otherwise the log file may be difficult to parse, since the values within the column will not be of one consistent type). See addSuppliedColumn() for further details.
– (void)setValue(is$ key, * value)
This Dictionary method has an override in LogFile to make it illegal to call, since LogFile manages its Dictionary entries.
– (logical$)willAutolog(void)
Returns T if the log file is configured to log a new row automatically at the end of the current tick; otherwise, returns F. This is useful for calculating a value that will be logged only in ticks when the value is needed.
5.10 Class Mutation
5.10.1 Mutation properties
id => (integer$)
The identifier for this mutation. Each mutation created during a run receives an immutable identifier that will be unique across the duration of the run. These identifiers are not re-used during a run, except that if a population file is loaded from disk, the loaded mutations will receive their original identifier values as saved in the population file.
isFixed => (logical$)
T if the mutation has fixed (in the SLiM sense of having been converted to a Substitution object), F otherwise. Since fixed/substituted mutations are removed from the simulation, you will only see this flag be T if you have held onto a mutation beyond its usual lifetime.
isSegregating => (logical$)
T if the mutation is segregating (in the SLiM sense of not having been either lost or converted to a Substitution object), F otherwise. Since both lost and fixed/substituted mutations are removed from the simulation, you will only see this flag be F if you have held onto a mutation beyond its usual lifetime. Note that if isSegregating is F, isFixed will let you determine whether the mutation is no longer segregating because it was lost, or because it fixed.
mutationType => (object<MutationType>$)
The MutationType from which this mutation was drawn.
nucleotide <–> (string$)
A string representing the nucleotide associated with this mutation; this will be "A", "C", "G", or "T". If the mutation is not nucleotide-based, this property is unavailable.
nucleotideValue <–> (integer$)
An integer representing the nucleotide associated with this mutation; this will be 0 (A), 1 (C), 2 (G), or 3 (T). If the mutation is not nucleotide-based, this property is unavailable.
originTick => (integer$)
The tick in which this mutation arose.
position => (integer$)
The position in the chromosome of this mutation.
selectionCoeff => (float$)
The selection coefficient of the mutation, drawn from the distribution of fitness effects of its MutationType. If a mutation has a selectionCoeff of s, the multiplicative fitness effect of the mutation in a homozygote is 1+s; in a heterozygote it is 1+hs, where h is the dominance coefficient kept by the mutation type.
Note that this property has a quirk: it is stored internally in SLiM using a single-precision float, not the double-precision float type normally used by Eidos. This means that if you set a mutation mut’s selection coefficient to some number x, mut.selectionCoeff==x may be F due to floating-point rounding error. Comparisons of floating-point numbers for exact equality is often a bad idea, but this is one case where it may fail unexpectedly. Instead, it is recommended to use the id or tag properties to identify particular mutations.
subpopID <–> (integer$)
The identifier of the subpopulation in which this mutation arose. This property can be used to track the ancestry of mutations through their subpopulation of origin.
If you don’t care which subpopulation a mutation originated in, the subpopID may be used as an arbitrary integer “tag” value for any purpose you wish; SLiM does not do anything with the value of subpopID except propagate it to Substitution objects and report it in output. (It must still be >= 0, however, since SLiM object identifiers are limited to nonnegative integers).
tag <–> (integer$)
A user-defined integer value. The value of tag is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tag is not used by SLiM; it is free for you to use.
5.10.2 Mutation methods
– (void)setMutationType(io<MutationType>$ mutType)
Set the mutation type of the mutation to mutType (which may be specified as either an integer identifier or a MutationType object). This implicitly changes the dominance coefficient of the mutation to that of the new mutation type, since the dominance coefficient is a property of the mutation type. On the other hand, the selection coefficient of the mutation is not changed, since it is a property of the mutation object itself; it can be changed explicitly using the setSelectionCoeff() method if so desired.
The mutation type of a mutation is normally a constant in simulations, so be sure you know what you are doing. Changing this will normally affect the fitness values calculated toward the end of the current tick; if you want current fitness values to be affected, you can call the Species method recalculateFitness() – but see the documentation of that method for caveats.
In nucleotide-based models, a restriction applies: nucleotide-based mutations may not be changed to a non-nucleotide-based mutation type, and non-nucleotide-based mutations may not be changed to a nucleotide-based mutation type.
– (void)setSelectionCoeff(float$ selectionCoeff)
Set the selection coefficient of the mutation to selectionCoeff. The selection coefficient will be changed for all individuals that possess the mutation, since they all share a single Mutation object (note that the dominance coefficient will remain unchanged, as it is determined by the mutation type).
This is normally a constant in simulations, so be sure you know what you are doing; often setting up a mutationEffect() callback is preferable, in order to modify the selection coefficient in a more limited and controlled fashion. Changing this will normally affect the fitness values calculated toward the end of the current tick; if you want current fitness values to be affected, you can call the Species method recalculateFitness() – but see the documentation of that method for caveats.
5.11 Class MutationType
5.11.1 MutationType properties
color <–> (string$)
The color used to display mutations of this type in SLiMgui. Outside of SLiMgui, this property still exists, but is not used by SLiM. Colors may be specified by name, or with hexadecimal RGB values of the form "#RRGGBB". If color is the empty string, "", SLiMgui’s default (selection-coefficient–based) color scheme is used; this is the default for new MutationType objects.
colorSubstitution <–> (string$)
The color used to display substitutions of this type in SLiMgui (see the discussion for the colorSubstitution property of the Chromosome class for details). Outside of SLiMgui, this property still exists, but is not used by SLiM. Colors may be specified by name, or with hexadecimal RGB values of the form "#RRGGBB". If colorSubstitution is the empty string, "", SLiMgui’s default (selection-coefficient–based) color scheme is used; this is the default for new MutationType objects.
convertToSubstitution <–> (logical$)
This property governs whether mutations of this mutation type will be converted to Substitution objects when they reach fixation.
In WF models this property is T by default, since conversion to Substitution objects provides large speed benefits; it should be set to F only if necessary, and only on the mutation types for which it is necessary. This might be needed, for example, if you are using a mutationEffect() callback to implement an epistatic relationship between mutations; a mutation epistatically influencing the fitness of other mutations through a mutationEffect() callback would need to continue having that influence even after reaching fixation, but if the simulation were to replace the fixed mutation with a Substitution object the mutation would no longer be considered in fitness calculations (unless the callback explicitly consulted the list of Substitution objects kept by the simulation). Other script-defined behaviors in mutationEffect(), interaction(), mateChoice(), modifyChild(), and recombination() callbacks might also necessitate the disabling of substitution for a given mutation type; this is an important consideration to keep in mind.
In contrast, for nonWF models this property is F by default, because even mutations with no epistatis or other indirect fitness effects will continue to influence the survival probabilities of individuals. For nonWF models, only neutral mutation types with no epistasis or other side effects can safely be converted to substitutions upon fixation. When such a pure-neutral mutation type is defined in a nonWF model, this property should be set to T to tell SLiM that substitution is allowed; this may have very large positive effects on performance, so it is important to remember when modeling background neutral mutations.
SLiM consults this flag at the end of each tick when deciding whether to substitute each fixed mutation. If this flag is T, all eligible fixed mutations will be converted at the end of the current tick, even if they were previously left unconverted because of the previous value of the flag. Setting this flag to F will prevent future substitutions, but will not cause any existing Substitution objects to be converted back into Mutation objects.
distributionParams => (fs)
The parameters that configure the chosen distribution of fitness effects. This will be of type string for DFE type "s", and type float for all other DFE types.
distributionType => (string$)
The type of distribution of fitness effects; one of "f", "g", "e", "n", "w", or "s":
"f" – A fixed fitness effect. This DFE type has a single parameter, the selection coefficient s to be used by all mutations of the mutation type.
"g" – A gamma-distributed fitness effect. This DFE type is specified by two parameters, a shape parameter and a mean value. The gamma distribution from which mutations are drawn is given by the probability density function P(s | α,β) = [Γ(α)βα]−1exp(−s/β), where α is the shape parameter, and the specified mean for the distribution is equal to αβ. Note that this parameterization is the same as for the Eidos function rgamma(). A gamma distribution is often used to model deleterious mutations at functional sites.
"e" – An exponentially-distributed fitness effect. This DFE type is specified by a single parameter, the mean of the distribution. The exponential distribution from which mutations are drawn is given by the probability density function P(s | β) = β−1exp(−s/β), where β is the specified mean for the distribution. This parameterization is the same as for the Eidos function rexp(). An exponential distribution is often used to model beneficial mutations.
"n" – A normally-distributed fitness effect. This DFE type is specified by two parameters, a mean and a standard deviation. The normal distribution from which mutations are drawn is given by the probability density function P(s | μ,σ) = (2πσ2)−1/2exp(−(s−μ)2/2σ2), where μ is the mean and σ is the standard deviation. This parameterization is the same as for the Eidos function rnorm(). A normal distribution is often used to model mutations that can be either beneficial or deleterious, since both tails of the distribution are unbounded.
"p" – A Laplace-distributed fitness effect. This DFE type is specified by two parameters, a mean and a scale. The Laplace distribution from which mutations are drawn is given by the probability density function P(s | μ,b) = exp(−|s−μ|/b)/2b, where μ is the mean and b is the scale parameter. A Laplace distribution is sometimes used to model a mix of both deleterious and beneficial mutations.
"w" – A Weibull-distributed fitness effect. This DFE type is specified by a scale parameter and a shape parameter. The Weibull distribution from which mutations are drawn is given by the probability density function P(s | λ,k) = (k/λk)sk−1exp(−(s/λ)k), where λ is the scale parameter and k is the shape parameter. This parameterization is the same as for the Eidos function rweibull(). A Weibull distribution is often used to model mutations following extreme-value theory.
"s" – A script-based fitness effect. This DFE type is specified by a script parameter of type string, specifying an Eidos script to be executed to produce each new selection coefficient. For example, the script "return rbinom(1);" could be used to generate selection coefficients drawn from a binomial distribution, using the Eidos function rbinom(), even though that mutational distribution is not supported by SLiM directly. The script must return a singleton float or integer.
Note that these distributions can in principle produce selection coefficients smaller than -1.0. In that case, the mutations will be evaluated as “lethal” by SLiM, and the relative fitness of the individual will be set to 0.0.
dominanceCoeff <–> (float$)
The dominance coefficient used for mutations of this type when heterozygous. Changing this will normally affect the fitness values calculated toward the end of the current tick; if you want current fitness values to be affected, you can call the Species method recalculateFitness() – but see the documentation of that method for caveats.
Note that the dominance coefficient is not bounded. A dominance coefficient greater than 1.0 may be used to achieve an overdominance effect. By making the selection coefficient very small and the dominance coefficient very large, an overdominance scenario in which both homozygotes have the same fitness may be approximated, to a nearly arbitrary degree of precision.
Note that this property has a quirk: it is stored internally in SLiM using a single-precision float, not the double-precision float type normally used by Eidos. This means that if you set a mutation type muttype’s dominance coefficient to some number x, muttype.dominanceCoeff==x may be F due to floating-point rounding error. Comparisons of floating-point numbers for exact equality is often a bad idea, but this is one case where it may fail unexpectedly. Instead, it is recommended to use the id or tag properties to identify particular mutation types.
haploidDominanceCoeff <–> (float$)
The dominance coefficient used for mutations of this type when they occur opposite a null genome (as in sex-chromosome models and models involving haploids). This defaults to 1.0, and is used only in models where null genomes are present; the dominanceCoeff property is the dominance coefficient used in most circumstances. Changing this will normally affect the fitness values calculated toward the end of the current tick; if you want current fitness values to be affected, you can call the Species method recalculateFitness() – but see the documentation of that method for caveats.
As with the dominanceCoeff property, this is stored internally using a single-precision float; see the documentation for dominanceCoeff for discussion.
id => (integer$)
The identifier for this mutation type; for mutation type m3, for example, this is 3.
mutationStackGroup <–> (integer$)
The group into which this mutation type belongs for purposes of mutation stacking policy. This is equal to the mutation type’s id by default. See mutationStackPolicy, below, for discussion.
In nucleotide-based models, the stacking group for nucleotide-based mutation types is always -1, and cannot be changed. Non-nucleotide-based mutation types may also be set to share the -1 stacking group, if they should participate in the same stacking policy as nucleotide-based mutations, but that would be quite unusual.
mutationStackPolicy <–> (string$)
This property and the mutationStackGroup property together govern whether mutations of this mutation type’s stacking group can “stack” – can occupy the same position in a single individual. A set of mutation types with the same value for mutationStackGroup is called a “stacking group”, and all mutation types in a given stacking group must have the same mutationStackPolicy value, which defines the stacking behavior of all mutations of the mutation types in the stacking group. In other words, one stacking group might allow its mutations to stack, while another stacking group might not, but the policy within each stacking group must be unambiguous.
This property is "s" by default, indicating that mutations in this stacking group should be allowed to stack without restriction. If the policy is set to "f", the first mutation of stacking group at a given site is retained; further mutations of this stacking group at the same site are discarded with no effect. This can be useful for modeling one-way changes; once a gene is disabled by a premature stop codon, for example, you might wish to assume, for simplicity, that further mutations cannot alter that fact. If the policy is set to "l", the last mutation of this stacking group at a given site is retained; earlier mutation of this stacking group at the same site are discarded. This can be useful for modeling an “infinite-alleles” scenario in which every new mutation at a site generates a completely new allele, rather than retaining the previous mutations at the site.
The mutation stacking policy applies only within the given mutation type’s stacking group; mutations of different stacking groups are always allowed to stack in SLiM. The policy applies to all mutations added to the model after the policy is set, whether those mutations are introduced by calls such as addMutation(), addNewMutation(), or addNewDrawnMutation(), or are added by SLiM’s own mutation-generation machinery. However, no attempt is made to enforce the policy for mutations already existing at the time the policy is set; typically, therefore, the policy is set in an initialize() callback so that it applies throughout the simulation. The policy is also not enforced upon the mutations loaded from a file with readFromPopulationFile(); such mutations were governed by whatever stacking policy was in effect when the population file was generated.
In nucleotide-based models, the stacking policy for nucleotide-based mutation types is always "l", and cannot be changed. This ensures that new nucleotide mutations always replace the previous nucleotide at a site, and that more than one nucleotide mutation is never present at the same position in a single genome.
nucleotideBased => (logical$)
If the mutation type was created with initializeMutationType(), it is not nucleotide-based, and this property is F. If it was created with initializeMutationTypeNuc(), it is nucleotide-based, and this property is T. See those methods for further discussion.
species => (object<Species>$)
The species to which the target object belongs.
tag <–> (integer$)
A user-defined integer value. The value of tag is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tag is not used by SLiM; it is free for you to use. See also the getValue() and setValue() methods (provided by the Dictionary class; see the Eidos manual), for another way of attaching state to mutation types.
5.11.2 MutationType methods
– (float)drawSelectionCoefficient([integer$ n = 1])
Draws and returns a vector of n selection coefficients using the currently defined distribution of fitness effects (DFE) for the target mutation type. If the DFE is type "s", this method will result in synchronous execution of the DFE’s script.
– (void)setDistribution(string$ distributionType, ...)
Set the distribution of fitness effects for a mutation type. The distributionType may be "f", in which case the ellipsis ... should supply a numeric$ fixed selection coefficient; "e", in which case the ellipsis should supply a numeric$ mean selection coefficient for the exponential distribution; "g", in which case the ellipsis should supply a numeric$ mean selection coefficient and a numeric$ alpha shape parameter for a gamma distribution; "n", in which case the ellipsis should supply a numeric$ mean selection coefficient and a numeric$ sigma (standard deviation) parameter for a normal distribution; "p", in which case the ellipsis should supply a numeric$ mean selection coefficient and a numeric$ scale parameter for a Laplace distribution; "w", in which case the ellipsis should supply a numeric$ λ scale parameter and a numeric$ k shape parameter for a Weibull distribution; or "s", in which case the ellipsis should supply a string$ Eidos script parameter. The DFE for a mutation type is normally a constant in simulations, so be sure you know what you are doing.
5.12 Class Plot
5.12.1 Plot properties
title => (string$)
The title of the plot, as originally passed to createPlot(). See also the plotWithTitle() method of SLiMgui.
5.12.2 Plot methods
– (void)abline([Nif a = NULL], [Nif b = NULL], [Nif h = NULL], [Nif v = NULL], [string color = "red"], [numeric lwd = 1.0])
Adds one or more straight lines to the plot. There are three supported modes of operation for this method. In the first mode, the lines are specified by a and b, representing the intercepts and slopes of the lines, respectively; in this case, a and b may be the same length, or one of them may be a singleton to provide a single value used for all of the lines specified by the other. In the second mode, the lines are specified by h, representing the y-values of horizontal lines. In the third mode, the lines are specified by v, representing the x-values of vertical lines. These modes are mutually exclusive and cannot be mixed within one call to abline(). The new lines will be plotted on top of any previously added data.
The lines will be drawn in colors and line widths specified by color and lwd, each of which may be either a singleton (to provide one value used for all lines) or a vector equal in length to the number of lines plotted (to provide one value per line).
See also lines(), for a more common approach to line plotting. The abline() method is different, and more specialized; the lines plotted by it span the full extent of the plot area, and their coordinates are not considered when dynamically resizing the axes of the plot (i.e., when createPlot() is not passed explicit, non-NULL values for xrange or yrange). This is typically useful for plotting things such as expected values and fit lines.
– (void)addLegend([Ns$ position = NULL], [Ni$ inset = NULL], [Nif$ labelSize = NULL], [Nif$ lineHeight = NULL], [Nif$ graphicsWidth = NULL], [Nif$ exteriorMargin = NULL], [Nif$ interiorMargin = NULL])
Adds a legend to the plot. The legend will be displayed within the plot at the location specified by position, which must be "topRight", "topLeft", "bottomRight", or "bottomLeft", or NULL (the default) requesting that SLiMgui choose the position. The position of the legend will be inset from the chosen corner by a margin inset, measured in pixels; the default of NULL allows SLiMgui to choose the inset.
The internal layout of the legend is a bit complex, and can be controlled by five parameters; in all cases, the default value of NULL requests that SLiMgui provide a reasonable default. The labelSize parameter specifies the font size used for the text labels for each legend entry (measured in “points”, the standard metric of font sizes). The lineHeight parameter specifies the vertical size, in pixels, of one entry line. The graphicsWidth parameter species the width, in pixels, of the column used to display the “graphics” (whether a line segment, a point symbol, a swatch, or a combination of those) associated with each entry. The exteriorMargin parameter specifies the width/height of margins, in pixels, outside of the entries (between the entries and the legend’s frame). Finally, the interiorMargin parameter specifies the width/height of margins, in pixels, vertically between entries, and also between the “graphics” column and the label. It is easy to produce a legend that looks terrible, using these layout metrics; SLiMgui does only minimal sanity-checking of their values, to provide maximal flexibility.
The legend is initially empty; entries for it can be added with legendLineEntry(), legendPointEntry(), and legendSwatchEntry().
– (void)axis(integer$ side, [Nif at = NULL], [ls labels = T])
Configures an axis of the plot. The side parameter controls which axis is being configured; at present, it may be 1 for the x-axis (at the bottom of the plot), or 2 for the y-axis (at the left of the plot).
The positions of tick marks (and of any associated labels) are controlled by at; if at is NULL (the default) these positions will be computed automatically based upon the range of the data in the plot, otherwise at must be a vector of numeric positions. Note that the coordinate system of the plot is controlled not by this method, but by the xrange and yrange parameters of createPlot(); at controls only the positions of axis ticks within that coordinate system.
The labels parameter controls the text labels displayed for ticks; it may be T (the default) to label ticks with their numeric positions, F to suppress all tick labels, or a vector of type string, equal in length to at, providing the label for each position in at. Label values may be the empty string, "", if a label at a given position is not desired, and if labels is T, some ticks may not receive a label for readability.
– (void)legendLineEntry(string$ label, [string$ color = "red"], [numeric$ lwd = 1.0])
Adds a legend entry with text label to the plot. The entry will be displayed as a line segment drawn in color color, using line width lwd, mirroring the appearance produced by lines() for the same parameters. If one or more other legend entries already exist with the same label, the new entry will be drawn on top of the previously set entries for that label (allowing legend entries that display both a line and a point, for example).
– (void)legendPointEntry(string$ label, [integer$ symbol = 0], [string$ color = "red"], [string$ border = "black"], [numeric$ lwd = 1.0], [numeric$ size = 1.0])
Adds a legend entry with text label to the plot. The entry will be displayed as a point symbol specified by symbol, color, border, lwd, and size, mirroring the appearance produced by points() for the same parameters; see points() for further details. If one or more other legend entries already exist with the same label, the new entry will be drawn on top of the previously set entries for that label (allowing legend entries that display both a line and a point, for example).
– (void)legendSwatchEntry(string$ label, [string$ color = "red"])
Adds a legend entry with text label to the plot. The entry will be displayed as a swatch drawn in color color. If one or more other legend entries already exist with the same label, the new entry will be drawn on top of the previously set entries for that label (allowing legend entries that display both a line and a point, for example).
– (void)lines(numeric x, numeric y, [string$ color = "red"], [numeric$ lwd = 1.0])
Adds line data given by x and y to the plot. The data will be plotted as a series of connected line segments, following the (x, y) positions given; note that the x and y vectors must be the same length. The new line data will be plotted on top of any previously added data.
The lines will be drawn in color color, using line width lwd. Unlike points() and text(), color and lwd must be singletons, since each point (except the two ends) is shared by two line segments; if you wish to vary the color and width for each line segment, separate calls to lines() are necessary. See also abline().
– (void)points(numeric x, numeric y, [integer symbol = 0], [string color = "red"], [string border = "black"], [numeric lwd = 1.0], [numeric size = 1.0])
Adds point data given by x and y to the plot. The data will be plotted as a set of point symbols, centered at the (x, y) positions given; note that the x and y vectors must be the same length. The new point data will be plotted on top of any previously added data.
The symbol plotted for each point depends upon the value of symbol. In general, symbols will be drawn in color color, with a line width lwd used for lines (if any) in the symbol, and an overall size scaled by size. Symbols 21–25 involve both a filled shape and a border line around that shape; for those symbols, the border line will use the color provided by border, while the filled shape will use color color. All of these parameters (symbol, color, border, lwd, and size) may either be a singleton value applied to all points, or a vector with one value per corresponding point.
– (void)text(numeric x, numeric y, string labels, [string color = "black"], [numeric size = 10.0], [Nif adj = NULL])
Adds text data given by x, y, and labels to the plot. The string values in labels will be plotted at the (x, y) positions given; note that x, y, and labels must all be the same length. The new text data will be plotted on top of any previously added data.
The text will be drawn in color color, at the font size given by size (measured in “points”, the standard metric of font sizes); the font family and style cannot be controlled at this time. Both of these parameters (color and size) may either be a singleton value applied to all points, or a vector with one value per corresponding point.
The exact position of the text, relative to each point (x, y), is adjusted by the optional parameter adj. The value of adj, if specified, must be a vector of length 2, where adj[0] adjusts the x position and adj[1] adjusts the y position of the text. Relative to a given x position, a value of 0.0 aligns the left edge of the text to it; a value of 0.5 aligns the center of the text to it; and a value of 1.0 aligns the right edge of the text to it. Similarly, relative to a given y position, a value of 0.0 aligns the bottom edge of the text to it; a value of 0.5 aligns the center of the text to it; and a value of 1.0 aligns the top edge of the text to it. Intermediate values will produce intermediate alignments, and values of adj outside of [0.0, 1.0] are also allowed. The default value of adj, NULL, is equivalent to c(0.5, 0.5), aligning the center of the text to (x, y) both horizontally and vertically.
– (void)write(string$ filePath)
Writes the plot to the given filesystem path filePath as a PDF file. It is suggested, but not required, that filePath should end in a .pdf or .PDF filename extension. If the file cannot be written, an error will result.
5.13 Class SLiMEidosBlock
5.13.1 SLiMEidosBlock properties
active <–> (integer$)
If this evaluates to logical F (i.e., is equal to 0), the script block is inactive and will not be called. The value of active for all registered script blocks is reset to -1 at the beginning of each tick, prior to script events being called, thus activating all blocks (except callbacks associated with a species that is not active in that tick, which are deactivated as part of the deactivation of the species). Any integer value other than -1 may be used instead of -1 to represent that a block is active; for example, active may be used as a counter to make a block execute a fixed number of times in each tick. This value is not cached by SLiM; if it is changed, the new value takes effect immediately. For example, a callback might be activated and inactivated repeatedly during a single tick.
end => (integer$)
The last tick in which the script block is active.
id => (integer$)
The identifier for this script block; for script s3, for example, this is 3. A script block for which no id was given will have an id of -1.
source => (string$)
The source code string of the script block.
speciesSpec => (object<Species>)
The species specifier for the script block. The species specifier for a callback block indicates the callback’s associated species; the callback is called to modify the default behavior for that species. If the script block has no species specifier, this property’s value is a zero-length object vector of class Species. This property is read-only; normally it is set by preceding the definition of a callback with a species specifier, of the form species <species-name>.
start => (integer$)
The first tick in which the script block is active.
tag <–> (integer$)
A user-defined integer value. The value of tag is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tag is not used by SLiM; it is free for you to use.
ticksSpec => (object<Species>)
The ticks specifier for the script block. The ticks specifier for an event block indicates the event’s associated species; the event executes only in ticks when that species is active. If the script block has no ticks specifier, this property’s value is a zero-length object vector of class Species. This property is read-only; normally it is set by preceding the definition of an event with a ticks specifier, of the form ticks <species-name>.
type => (string$)
The type of the script block; this will be "first", "early", or "late" for the three types of Eidos events, or "initialize", "fitnessEffect", "interaction", "mateChoice", "modifyChild", "mutation", "mutationEffect", "recombination", "reproduction", or "survival" for the respective types of Eidos callbacks.
5.13.2 SLiMEidosBlock methods
5.14 Class SLiMgui
5.14.1 SLiMgui properties
pid => (integer$)
The Un*x process identifier (commonly called the “pid”) of the running SLiMgui application. This can be useful for scripts that wish to use system calls to influence the SLiMgui application.
5.14.2 SLiMgui methods
– (No<Plot>$)createPlot(string$ title, [Nif xrange = NULL], [Nif yrange = NULL], [string$ xlab = "x"], [string$ ylab = "y"], [Nif$ width = NULL], [Nif$ height = NULL], [logical$ horizontalGrid = F], [logical$ verticalGrid = F], [logical$ fullBox = T], [numeric$ axisLabelSize = 15], [numeric$ tickLabelSize = 10])
Creates and returns a new custom plot referred to by title, or restarts and returns the existing plot with that title; if the plot cannot be created (notably, when running under SLiMguiLegacy rather than SLiMgui), NULL is returned. The range for the x and y axes of the plot can optionally be provided in xrange and yrange, as vectors of length 2 containing the minimum and maximum values for the corresponding axis; the default of NULL for these parameters requests that the axis ranges be determined heuristically based upon the data subsequently added to the plot. Labels for the x and y axes can be provided in xlab and ylab; if no axis label is desired, the empty string "" may be passed. The width and height of the window itself can optionally be set with width and height, in units of pixels (perhaps 70–100 pixels per inch, depending on your screen’s pixel density); the default of NULL for these parameters requests SLiMgui’s default plot window size. The display of horizontal grid lines, vertical grid lines, and a full box around the plot area can be controlled with horizontalGrid, verticalGrid, and fullBox respectively, and the size (in points) of axis and tick labels can be controlled with axisLabelSize and tickLabelSize respectively.
Once the plot has been created, data can be added to it using Plot methods such as lines(), points(), and text(). As with other plot windows in SLiMgui, the “action button” can be used to access plot configuration options, and to copy or save the final plot as a raster image or a PDF file.
– (Nfs)logFileData(object<LogFile>$ logFile, is$ column)
Returns a vector containing data from the LogFile object logFile, taken from a specified column (identified in column either by the column’s name or by its zero-based index). If the data are all numeric, they will be returned as a float vector. Otherwise – if the data are non-numeric – they will be returned as a string vector. If the specified column does not exist in the log file, NULL will be returned.
This functionality is provided as a method on the SLiMgui class, rather than on LogFile, because in SLiMgui logged data is kept in memory anyway, for display in the debugging output viewer window. When running at the command line logged data is not kept in memory, and thus is not available.
– (void)openDocument(string$ filePath)
Open the document at filePath in SLiMgui, if possible. Supported document types include SLiM model files (typically with a .slim path extension), text files (typically with a .txt path extension, and opened as untitled model files), and PNG, JPG/JPEG, BMP, and GIF image file formats (typically .png / .jpg / .jpeg / .bmp / .gif, respectively). (Note that in SLiMguiLegacy, PDF files (.pdf) are supported but these other image file formats are not.) This method can be particularly useful for opening images created by the simulation itself, often by sublaunching a plotting process in R or another environment.
– (void)pauseExecution(void)
Pauses a model that is playing in SLiMgui. This is essentially equivalent to clicking the “Play” button to stop the execution of the model. Execution can be resumed by the user, by clicking the “Play” button again; unlike calling stop() or simulationFinished(), the simulation is not terminated. This method can be useful for debugging or exploratory purposes, to pause the model at a point of interest. Execution is paused at the end of the currently executing tick, not mid-tick.
If the model is being profiled, or is executing forward to a tick number entered in the tick field, pauseExecution() will do nothing; by design, pauseExecution() only pauses execution when SLiMgui is doing a simple “Play” of the model.
– (No<Plot>$)plotWithTitle(string$ title)
Returns an existing plot that was created by createPlot() with title; if such a plot does not exist, NULL is returned. Note that other SLiMgui plots cannot be accessed through this method; only plots created by createPlot() are available in Eidos.
5.15 Class SpatialMap
(object<SpatialMap>$)SpatialMap(string$ name, object<SpatialMap>$ map)
Creates a new SpatialMap object that is a copy of map, named name.
5.15.1 SpatialMap properties
gridDimensions => (integer)
The dimensions of the spatial map’s grid of values, in the order of the components of the map’s spatiality. For example, a map with spatiality "xz" and a grid of values that is 500 in the "x" dimension by 300 in the "z" dimension would return c(500, 300) for this property.
interpolate <–> (logical$)
Whether interpolation between grid values is enabled (T) or disabled (F). The initial value of this property is set by defineSpatialMap(), but it can be changed. The interpolation performed is linear; for cubic interpolation, use the interpolate() method.
name => (string$)
The name of the spatial map, usually as provided to defineSpatialMap(). The names of spatial maps must be unique within any given subpopulation, but the same name may be reused for different spatial maps in different subpopulations. The name is used to identify a map for methods such as spatialMapValue(), and is also used for display in SLiMgui.
spatialBounds => (float)
The spatial bounds to which the spatial map is aligned. These bounds come from the subpopulation that originally created the map, with the defineSpatialMap() method, and cannot be subsequently changed. All subpopulations that use a given spatial map must match that map’s spatial bounds, so that the map does not stretch or shrink relative to its initial configuration. The components of the spatial bounds of a map correspond to the components of the map’s spatiality; for example, a map with spatiality "xz" will have bounds (x0, z0, x1, z1); bounds for "y" are not included, since that dimension is not used by the spatial map.
spatiality => (string$)
The spatiality of the map: the subset of the model’s dimensions that are used by the spatial map. The spatiality of a map is configured by defineSpatialMap() and cannot subsequently be changed. For example, a 3D model (with dimensionality "xyz") might define a 2D spatial map with spatiality "xz", providing spatial values that do not depend upon the "y" dimension. Often, however, the spatiality of a map will match the dimensionality of the model.
tag <–> (integer$)
A user-defined integer value. The value of tag is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tag is not used by SLiM; it is free for you to use. See also the getValue() and setValue() methods (provided by the Dictionary class; see the Eidos manual), for another way of attaching state to spatial maps.
5.15.2 SpatialMap methods
– (object<SpatialMap>$)add(ifo<SpatialMap> x)
Adds x to the spatial map. One possibility is that x is a singleton integer or float value; in this case, x is added to each grid value of the target spatial map. Another possibility is that x is an integer or float vector/matrix/array of the same dimensions as the target spatial map’s grid; in this case, each value of x is added to the corresponding grid value of the target spatial map. The third possibility is that x is itself a (singleton) spatial map; in this case, each grid value of x is added to the corresponding grid value of the target spatial map (and thus the two spatial maps must match in their spatiality, their spatial bounds, and their grid dimensions). The target spatial map is returned, to allow easy chaining of operations.
– (object<SpatialMap>$)blend(ifo<SpatialMap> x, float$ xFraction)
Blends x into the spatial map, giving x a weight of xFraction and the existing values in the target spatial map a weight of 1 - xFraction, such that the resulting values in the target spatial map are then given by x * xFraction + target * (1 - xFraction). The value of xFraction must be in [0.0, 1.0].
One possibility is that x is a singleton integer or float value; in this case, x is blended with each grid value of the target spatial map. Another possibility is that x is an integer or float vector/matrix/array of the same dimensions as the target spatial map’s grid; in this case, each value of x is blended with the corresponding grid value of the target spatial map. The third possibility is that x is itself a (singleton) spatial map; in this case, each grid value of x is blended with the corresponding grid value of the target spatial map (and thus the two spatial maps must match in their spatiality, their spatial bounds, and their grid dimensions). The target spatial map is returned, to allow easy chaining of operations.
– (void)changeColors([Nif valueRange = NULL], [Ns colors = NULL])
Changes the color scheme for the target spatial map. The meaning of valueRange and colors are identical to their meaning in defineSpatialMap(), but are also described here.
The valueRange and colors parameters travel together; either both are NULL, or both are specified. They control how map values will be transformed into colors, by SLiMgui and by the mapColor() method. The valueRange parameter establishes the color-mapped range of spatial map values, as a vector of length two specifying a minimum and maximum; this does not need to match the actual range of values in the map. The colors parameter then establishes the corresponding colors for values within the interval defined by valueRange: values less than or equal to valueRange[0] will map to colors[0], values greater than or equal to valueRange[1] will map to the last colors value, and intermediate values will shade continuously through the specified vector of colors, with interpolation between adjacent colors to produce a continuous spectrum. This is much simpler than it sounds in this description; see the recipes in chapter 15 for an illustration of its use.
If valueRange and colors are both NULL, a default grayscale color scheme will be used in SLiMgui, but an error will result if mapColor() is called.
– (void)changeValues(ifo<SpatialMap> x)
Changes the grid values used for the target spatial map. The parameter x should be either a SpatialMap object from which values are taken directly, or a vector, matrix, or array of numeric values as described in the documentation for defineSpatialMap(). Other characteristics of the spatial map, such as its color mapping (if defined), its spatial bounds, and its spatiality, will remain unchanged. The grid resolution of the spatial map is allowed to change with this method. This method is useful for changing the values of a spatial map over time, such as to implement changes to the landscape’s characteristics due to seasonality, climate change, processes such as fire or urbanization, and so forth. As with the original map values provided to defineSpatialMap(), it is often useful to read map values from a PNG image file using the Eidos class Image.
– (object<SpatialMap>$)divide(ifo<SpatialMap> x)
Divides the spatial map by x. One possibility is that x is a singleton integer or float value; in this case, each grid value of the target spatial map is divided by x. Another possibility is that x is an integer or float vector/matrix/array of the same dimensions as the target spatial map’s grid; in this case, each grid value of the target spatial map is divided by the corresponding value of x. The third possibility is that x is itself a (singleton) spatial map; in this case, each grid value of the target spatial map is divided by the corresponding grid value of x (and thus the two spatial maps must match in their spatiality, their spatial bounds, and their grid dimensions). The target spatial map is returned, to allow easy chaining of operations.
– (object<SpatialMap>$)exp(void)
Exponentiates the values of the spatial map. More precisely, each grid value x of the target spatial map is exponentiated – replaced by the value ex. The target spatial map is returned, to allow easy chaining of operations.
– (float)gridValues(void)
Returns the values for the spatial map’s grid as a vector (for a 1D map), a matrix (for a 2D map), or an array (for a 3D map). The form and orientation of the returned values is such that it could be used to create a new spatial map, with defineSpatialMap(), which would be identical to the original.
– (object<SpatialMap>$)interpolate(integer$ factor, [string$ method = "linear"])
Increases the resolution of the spatial map by factor, changing the dimensions of the spatial map’s grid of values (while leaving its spatial bounds unchanged), by interpolating new values between the existing values. The parameter factor must be an integer in [2, 10001], somewhat arbitrarily. The target spatial map is returned, to allow easy chaining of operations.
For a 1D spatial map, factor-1 new values will be inserted between every pair of values in the original value grid. A factor of 2 would therefore insert one new value between each pair of existing values, thereby increasing the map’s resolution by a factor of two. Note that if the spatial map’s original grid dimension was N, the new grid dimension with a factor of k would be k(N−1)+1, not kN, because new values are inserted only between existing values. For 2D and 3D spatial maps, essentially the same process is conducted along each axis of the map’s spatiality, increasing the resolution of the map by factor in every dimension.
If method is "linear" (the default), linear (or bilinear or trilinear, for 2D/3D maps) interpolation will be used to interpolate the values for the new grid points. Alternatively, if method is "nearest", the nearest value in the old grid will be used for new grid points; with this method, it is recommended that factor be odd, not even, to avoid artifacts due to rounding of coordinates midway between the original grid positions. If method is "cubic", cubic (or bicubic, for 2D maps) will be used; this generally produces smoother interpolation with fewer artifacts than "linear", but it is not supported for 3D maps. The choice of interpolation method used here is independent of the map’s interpolate property. Note that while the "nearest" and "linear" interpolation methods will leave the range of values in the map unchanged, "cubic" interpolation may produce interpolated values that are outside the original range of values (by design). Periodic boundaries are currently supported only for "nearest", "linear", and 1D "cubic" interpolation.
– (string)mapColor(numeric value)
Uses the spatial map’s color-translation machinery (as defined by the valueRange and colors parameters to defineSpatialMap()) to translate each element of value into a corresponding color string. If the spatial map does not have color-translation capabilities, an error will result. See the documentation for defineSpatialMap() for information regarding the details of color translation. See the Eidos manual for further information on color strings.
– (object<Image>$)mapImage([Ni$ width = NULL], [Ni$ height = NULL], [logical$ centers = F], [logical$ color = T])
Returns an Image object sampled from the spatial map. The image will be width pixels wide and height pixels tall; the intrinsic size of the spatial map itself will be used if one of these parameters is NULL. The image will be oriented in the same way as it is displayed in SLiMgui (which conceptually entails a transformation from matrix coordinates, which store values by column, to standard image coordinates, which store values by row; see the Eidos manual’s documentation of Image for details). This method may only be called for 2D spatial maps at present.
The sampling of the spatial map can be done in one of two ways, as controlled by the centers parameter. If centers is T, a (width+1) × (height+1) grid of lines that delineates width × height rectangular pixels will be overlaid on top of the spatial map, and values will be sampled from the spatial map at the center of each of these pixels. If centers is F (the default), a width × height grid of lines will be overlaid on top of the spatial map, and values will be sampled from the spatial map at the vertices of the grid. If interpolation is not enabled for the spatial map, these two options will both recover the original matrix of values used to define the spatial map (assuming, here and below, that width and height are NULL). If interpolation is enabled for the spatial map, however, centers == F will recover the original values, but will not capture the “typical” value of each pixel in the image; centers == T, on the other hand, will not recover the original values, but will capture the “typical” value of each pixel in the image (i.e., the value at the center of each pixel, as produced by interpolation).
If color is T (the default), the valueRange and colors parameters supplied to defineSpatialMap() will be used to translate map values to RGB color values as described in the documentation of that method, providing the same appearance as in SLiMgui; of course those parameters must have been supplied, otherwise an error will result. If color is F, on the other hand, a grayscale image will be produced that directly reflects the map values without color translation. In this case, this method needs to translate map values, which can have any float value, into grayscale pixel values that are integers in [0, 255]. To do so, the map values are multiplied by 255.0, clamped to [0.0, 255.0], and then rounded to the nearest integer. This translation scheme essentially assumes that map values are in [0, 1]; for spatial maps that were defined using the floatK channel of a grayscale PNG image, this should recover the original image’s pixel values. (If a different translation scheme is desired, color=T with the desired valueRange and colors should be used.)
– (float)mapValue(float point)
Uses the spatial map’s mapping machinery (as defined by the gridSize, values, and interpolate parameters to defineSpatialMap()) to translate the coordinates of point into a corresponding map value. The length of point must be equal to the spatiality of the spatial map; in other words, for a spatial map with spatiality "xz", point must be of length 2, specifying the x and z coordinates of the point to be evaluated. Interpolation will automatically be used if it was enabled for the spatial map. Point coordinates are clamped into the range defined by the spatial boundaries, even if the spatial boundaries are periodic; use pointPeriodic() to wrap the point coordinates first if desired. See the documentation for defineSpatialMap() for information regarding the details of value mapping.
The point parameter may also contain more than one point to be looked up. In this case, the length of point must be an exact multiple of the spatiality of the spatial map; for a spatial map with spatiality "xz", for example, the length of point must be an exact multiple of 2, and successive pairs of elements from point (elements 0 and 1, then elements 2 and 3, etc.) will be taken as the x and z coordinates of the points to be evaluated. This allows mapValue() to be used in a vectorized fashion.
The spatialMapValue() method of Subpopulation provides essentially the same functionality as this method; it may be more convenient to use, for some usage cases, and it checks that the spatial map is actually added to the subpopulation in question, providing an additional consistency check. However, either method may be used.
– (object<SpatialMap>$)multiply(ifo<SpatialMap> x)
Multiplies the spatial map by x. One possibility is that x is a singleton integer or float value; in this case, each grid value of the target spatial map is multiplied by x. Another possibility is that x is an integer or float vector/matrix/array of the same dimensions as the target spatial map’s grid; in this case, each grid value of the target spatial map is multiplied by the corresponding value of x. The third possibility is that x is itself a (singleton) spatial map; in this case, each grid value of the target spatial map is multiplied by the corresponding grid value of x (and thus the two spatial maps must match in their spatiality, their spatial bounds, and their grid dimensions). The target spatial map is returned, to allow easy chaining of operations.
– (object<SpatialMap>$)power(ifo<SpatialMap> x)
Raises the spatial map to the power x. One possibility is that x is a singleton integer or float value; in this case, each grid value of the target spatial map is raised to the power x. Another possibility is that x is an integer or float vector/matrix/array of the same dimensions as the target spatial map’s grid; in this case, each grid value of the target spatial map is raised to the power of the corresponding value of x. The third possibility is that x is itself a (singleton) spatial map; in this case, each grid value of the target spatial map is raised to power of the corresponding grid value of x (and thus the two spatial maps must match in their spatiality, their spatial bounds, and their grid dimensions). The target spatial map is returned, to allow easy chaining of operations.
– (float)range(void)
Returns the range of values contained in the spatial map. The result is a float vector of length 2; the first element is the minimum map value, and the second element is the maximum map value.
– (object<SpatialMap>$)rescale([numeric$ min = 0.0], [numeric$ max = 1.0])
Rescales the values of the spatial map to the range [min, max]. By default, the rescaling is to the range [0.0, 1.0]. It is required that min be less than max, and that both be finite. Note that the final range may not be exactly [min, max] due to numerical error. The target spatial map is returned, to allow easy chaining of operations.
– (float)sampleImprovedNearbyPoint(float point, float$ maxDistance, string$ functionType, ...)
This variant of sampleNearbyPoint() samples a Metropolis–Hastings move on the spatial map. See sampleNearbyPoint() for discussion of the basic idea. This method proposes a nearby point drawn from the given kernel. If the drawn point has a larger map value than the original point, the new point is returned. If the drawn point has a smaller map value than the original point, it is returned with a probability equal to the ratio between its map value and the original map value, otherwise the original point is returned. The distribution of individuals that move (or not) to new locations governed by this method will converge upon the map itself, in a similar manner to how MCMC converges upon the posterior distribution (assuming no other forces, such as birth or death, influence the distribution of individuals). Movement governed by this method is “improved” in the sense that individuals will tend to remain where they are unless the new sampled point is an improvement for them – a higher map value.
Note that unlike sampleNearbyPoint(), this method requires that all map values are non-negative.
– (float)sampleNearbyPoint(float point, float$ maxDistance, string$ functionType, ...)
For a spatial point supplied in point, returns a nearby point sampled from a kernel weighted by the spatial map’s values. Only points within the maximum distance of the kernel, maxDistance, will be chosen, and the probability that a given point is chosen will be proportional to the density of the kernel at that point multiplied by the value of the map at that point (interpolated, if interpolation is enabled for the map). Negative values of the map will be treated as zero. The point returned will be within spatial bounds, respecting periodic boundaries if in effect (so there is no need to call pointPeriodic() on the result).
The kernel is specified with a kernel shape, functionType, followed by zero or more ellipsis arguments; see smooth() for further information. For this method, at present only kernel types "f", "l", "e", "n", and "t" are supported, and type "t" is not presently supported for 3D kernels.
This method can be used to find points in the vicinity of individuals that are favorable – possessing more resources, or better environmental conditions, etc. It can also be used to guide the dispersal or foraging behavior of individuals. See sampleImprovedNearbyPoint() for a variant that may be useful for directed movement across a landscape. Note that the algorithm for sampleNearbyPoint() works by rejection sampling, and so will be very inefficient if the maximum value of the map (anywhere, across the entire map) is much larger than the typical value of the map where individuals are. The algorithm for sampleImprovedNearbyPoint() is different, and does not exhibit this performance issue.
– (object<SpatialMap>$)smooth(float$ maxDistance, string$ functionType, ...)
Smooths (or blurs, one could say) the values of the spatial map by convolution with a kernel. The kernel is specified with a maximum distance maxDistance (beyond which the kernel cuts off to a value of zero), a kernel type functionType that should be "f", "l", "e", "n", "c", or "t", and additional parameters in the ellipsis ... that depend upon the kernel type and further specify its shape. The target spatial map is returned, to allow easy chaining of operations.
The kernel specification is similar to that for the setInteractionType() method of InteractionType, but omits the maximum value of the kernel. Specifically, functionType may be "f", in which case no ellipsis arguments should be supplied; "l", similarly with no ellipsis arguments; "e", in which case the ellipsis should supply a numeric$ lambda (rate) parameter for a negative exponential function; "n", in which case the ellipsis should supply a numeric$ sigma (standard deviation) parameter for a Gaussian function; "c", in which case the ellipsis should supply a numeric$ scale parameter for a Cauchy distribution function; or "t", in which case the ellipsis should supply a numeric$ degrees of freedom and a numeric$ scale parameter for a t-distribution function. See the InteractionType class documentation for discussions of these kernel types.
Distance metrics specified to this method, such as maxDistance and the additional kernel shape parameters, are measured in the distance scale of the spatial map – the same distance scale in which the spatial bounds of the map are specified. The operation is performed upon the grid values of the spatial map; distances are internally translated into the scale of the value grid. For non-periodic boundaries, clipping at the edge of the spatial map is done; in a 2D map with no periodic boundaries, for example, the weights of edge and corner grid values are adjusted for their partial (one-half and one-quarter) coverage. For periodic boundaries, the smoothing operation will automatically wrap around based upon the assumption that the grid values at the two connected edges of the periodic boundary have identical values (which they should, since by definition they represent the same position in space).
The density scale of the kernel has no effect and will be normalized; this is the reason that smooth(), unlike InteractionType, does not require specification of the maximum value of the kernel. This normalization prevents the kernel from increasing or decreasing the average spatial map value (apart from possible edge effects).
– (object<SpatialMap>$)subtract(ifo<SpatialMap> x)
Subtracts x from the spatial map. One possibility is that x is a singleton integer or float value; in this case, x is subtracted from each grid value of the target spatial map. Another possibility is that x is an integer or float vector/matrix/array of the same dimensions as the target spatial map’s grid; in this case, each value of x is subtracted from the corresponding grid value of the target spatial map. The third possibility is that x is itself a (singleton) spatial map; in this case, each grid value of x is subtracted from the corresponding grid value of the target spatial map (and thus the two spatial maps must match in their spatiality, their spatial bounds, and their grid dimensions). The target spatial map is returned, to allow easy chaining of operations.
5.16 Class Species
5.16.1 Species properties
avatar => (string$)
The avatar string used to represent this species in SLiMgui. Outside of SLiMgui, this property still exists, but is not used by SLiM. Avatars are typically one-character strings, often using an emoji that symbolizes the species. This property is read-only; its value should be set with the avatar parameter of initializeSpecies().
chromosome => (object<Chromosome>$)
The Chromosome object used by the species.
chromosomeType => (string$)
The type of chromosome being simulated by this species; this will be one of "A", "X", or "Y".
color => (string$)
The color used to display information about this species in SLiMgui. Outside of SLiMgui, this property still exists, but is not used by SLiM. Colors may be specified by name, or with hexadecimal RGB values of the form "#RRGGBB" (see the Eidos manual). This property is read-only; its value should be set with the color parameter of initializeSpecies().
cycle <–> (integer$)
The current cycle count for this species. This counter begins at 1, and increments at the end of every tick in which the species is active. In models with non-overlapping generations, particularly WF models, this can be thought of as a generation counter.
description <–> (string$)
A human-readable string description for the species. By default, this is the empty string, ""; however, it may be set to whatever you wish.
dimensionality => (string$)
The spatial dimensionality of the simulation for this species, as specified in initializeSLiMOptions(). This will be "" (the empty string) for non-spatial simulations (the default), or "x", "xy", or "xyz", for simulations using those spatial dimensions respectively.
genomicElementTypes => (object<GenomicElementType>)
The GenomicElementType objects being used in the species. These are guaranteed to be in sorted order, by their id property.
id => (integer$)
The identifier for this species. Species identifiers are determined by their declaration order in the script; the first declared species is given an id of 0, the second is given an id of 1, and so forth.
mutationTypes => (object<MutationType>)
The MutationType objects being used in the species. These are guaranteed to be in sorted order, by their id property.
mutations => (object<Mutation>)
The Mutation objects that are currently active in the species.
name => (string$)
A human-readable string name for the subpopulation. This is always the declared name of the species, as given in the explicit species declaration in script, and cannot be changed. The name of a species may appear as a label in SLiMgui, and it can be useful in generating output, debugging, and other purposes. See also the description property, which can be changed by the user and used for any purpose.
nucleotideBased => (logical$)
If T, the model for this species is nucleotide-based; if F, it is not. See the discussion of the nucleotideBased parameter to initializeSLiMOptions() for discussion.
periodicity => (string$)
The spatial periodicity of the simulation for this species, as specified in initializeSLiMOptions(). This will be "" (the empty string) for non-spatial simulations and simulations with no periodic spatial dimensions (the default). Otherwise, it will be a string representing the subset of spatial dimensions that have been declared to be periodic, as specified to initializeSLiMOptions().
scriptBlocks => (object<SLiMEidosBlock>)
All registered SLiMEidosBlock objects in the simulation that have been declared with this species as their species specifier (not ticks specifier). These will always be callback blocks; callbacks are species-specific, while other types of blocks are not.
sexEnabled => (logical$)
If T, sex is enabled for this species; if F, individuals are hermaphroditic.
subpopulations => (object<Subpopulation>)
The Subpopulation instances currently defined in the species. These are guaranteed to be in sorted order, by their id property.
substitutions => (object<Substitution>)
A vector of Substitution objects, representing all mutations that have been fixed in this species.
tag <–> (integer$)
A user-defined integer value. The value of tag is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tag is not used by SLiM; it is free for you to use. See also the getValue() and setValue() methods (provided by the Dictionary class; see the Eidos manual), for another way of attaching state to the simulation.
5.16.2 Species methods
– (object<Subpopulation>$)addSubpop(is$ subpopID, integer$ size, [float$ sexRatio = 0.5], [logical$ haploid = F])
Add a new subpopulation with id subpopID and size individuals (see the SLiM manual for further details). The subpopID parameter may be either an integer giving the ID of the new subpopulation, or a string giving the name of the new subpopulation (such as "p5" to specify an ID of 5). Only if sex is enabled for the species, the initial sex ratio may optionally be specified as sexRatio (as the male fraction, M:M+F); if it is not specified, a default of 0.5 is used. The new subpopulation will be defined as a global variable immediately by this method, and will also be returned by this method. Subpopulations added by this method will initially consist of individuals with empty genomes. In order to model subpopulations that split from an already existing subpopulation, use addSubpopSplit().
Only in nonWF models, the haploid parameter may be T; in this case, the second genome of each new individual will be a null genome, rather than an empty genome. For even greater control in nonWF models, you can call addSubpop() with an initial size of 0 and then stock the population with new individuals created however you wish in the next tick’s reproduction() callback.
– (object<Subpopulation>$)addSubpopSplit(is$ subpopID, integer$ size, io<Subpopulation>$ sourceSubpop, [float$ sexRatio = 0.5])
Split off a new subpopulation with id subpopID and size individuals derived from subpopulation sourceSubpop. The subpopID parameter may be either an integer giving the ID of the new subpopulation, or a string giving the name of the new subpopulation (such as "p5" to specify an ID of 5). The sourceSubpop parameter may specify the source subpopulation either as a Subpopulation object or by integer identifier. Only if sex is enabled for the species, the initial sex ratio may optionally be specified as sexRatio (as the male fraction, M:M+F); if it is not specified, a default of 0.5 is used. The new subpopulation will be defined as a global variable immediately by this method, and will also be returned by this method.
Subpopulations added by this method will consist of individuals that are clonal copies of individuals from the source subpopulation, randomly chosen with probabilities proportional to fitness. The fitness of all of these initial individuals is considered to be 1.0, to avoid a doubled round of selection in the initial tick, given that fitness values were already used to choose the individuals to clone. Once this initial set of individuals has mated to produce offspring, the model is effectively of parental individuals in the source subpopulation mating randomly according to fitness, as usual in SLiM, with juveniles migrating to the newly added subpopulation. Effectively, then, then new subpopulation is created empty, and is filled by migrating juveniles from the source subpopulation, in accordance with SLiM’s usual model of juvenile migration.
– (integer$)countOfMutationsOfType(io<MutationType>$ mutType)
Returns the number of mutations that are of the type specified by mutType, out of all of the mutations that are currently active in the species. If you need a vector of the matching Mutation objects, rather than just a count, use -mutationsOfType(). This method is often used to determine whether an introduced mutation is still active (as opposed to being either lost or fixed). This method is provided for speed; it is much faster than the corresponding Eidos code.
– (object<Individual>)individualsWithPedigreeIDs(integer pedigreeIDs, [Nio<Subpopulation> subpops = NULL])
Looks up individuals by pedigree ID, optionally within specific subpopulations. Pedigree tracking must be turned on with initializeSLiMOptions(keepPedigrees=T) to use this method, otherwise an error will result. This method is vectorized; more than one pedigree id may be passed in pedigreeID, in which case the returned vector will contain all of the individuals for which a match was found (in the same order in which they were supplied). If a given id is not found, the returned vector will contain no entry for that id (so the length of the returned vector may not match the length of pedigreeIDs). If none of the given ids were found, the returned vector will be object<Individual>(0), an empty object vector of class Individual. If you have more than one pedigree ID to look up, calling this method just once, in vectorized fashion, may be much faster than calling it once for each ID, due to internal optimizations.
To find individuals within all subpopulations, pass the default of NULL for subpops. If you are interested only in matches within a specific subpopulation, pass that subpopulation for subpops; that will make the search faster. Similarly, if you know that a particular subpopulation is the most likely to contain matches, you should supply that subpopulation first in the subpops vector so that it will be searched first; the supplied subpopulations are searched in order. Subpopulations may be supplied either as integer IDs, or as Subpopulation objects.
– (void)killIndividuals(object<Individual> individuals)
Immediately kills the individuals in individuals. This removes them from their subpopulation and gives them an index value of -1. The Individual objects are not freed immediately, since references to them could still exist in local Eidos variables; instead, the individuals are kept in a temporary “graveyard” until they can be freed safely. It therefore continues to be safe to use them and their genomes, except that accessing their subpopulation property will raise an error since they no longer have a subpopulation.
Note that the indices and order of individuals and genomes in all source subpopulations will change unpredictably as a side effect of this method. All evaluated interactions are invalidated as a side effect of calling this method.
Note that this method is only for use in nonWF models, in which mortality is managed manually by the model script. In WF models, mortality is managed automatically by the SLiM core when the new offspring generation becomes the parental generation and the previous parental generation dies; mortality does not otherwise occur in WF models. In nonWF models, mortality normally occurs during the survival stage of the tick cycle, based upon the fitness values calculated by SLiM, and survival() callbacks can influence the outcome of that survival stage. Calls to killIndividuals(), on the other hand, can be made at any time during first(), early(), or late() events, and the result cannot be modified by survival() callbacks; the given individuals are simply immediately killed. This method therefore provides an alternative, and relatively rarely used, mortality mechanism that is disconnected from fitness.
– (integer)mutationCounts(Nio<Subpopulation> subpops, [No<Mutation> mutations = NULL])
Return an integer vector with the frequency counts of all of the Mutation objects passed in mutations, within the Subpopulation objects in subpops. The subpops argument is required, but you may pass NULL to get population-wide frequency counts. Subpopulations may be supplied either as integer IDs, or as Subpopulation objects. If the optional mutations argument is NULL (the default), frequency counts will be returned for all of the active Mutation objects in the species – the same Mutation objects, and in the same order, as would be returned by the mutations property of sim, in other words.
See the -mutationFrequencies() method to obtain float frequencies instead of integer counts. See also the Genome methods mutationCountsInGenomes() and mutationFrequenciesInGenomes().
– (float)mutationFrequencies(Nio<Subpopulation> subpops, [No<Mutation> mutations = NULL])
Return a float vector with the frequencies of all of the Mutation objects passed in mutations, within the Subpopulation objects in subpops. The subpops argument is required, but you may pass NULL to get population-wide frequencies. Subpopulations may be supplied either as integer IDs, or as Subpopulation objects. If the optional mutations argument is NULL (the default), frequencies will be returned for all of the active Mutation objects in the species – the same Mutation objects, and in the same order, as would be returned by the mutations property of sim, in other words.
See the -mutationCounts() method to obtain integer counts instead of float frequencies. See also the Genome methods mutationCountsInGenomes() and mutationFrequenciesInGenomes().
– (object<Mutation>)mutationsOfType(io<MutationType>$ mutType)
Returns an object vector of all the mutations that are of the type specified by mutType, out of all of the mutations that are currently active in the species. If you just need a count of the matching Mutation objects, rather than a vector of the matches, use -countOfMutationsOfType(). This method is often used to look up an introduced mutation at a later point in the simulation, since there is no way to keep persistent references to objects in SLiM. This method is provided for speed; it is much faster than the corresponding Eidos code.
– (void)outputFixedMutations([Ns$ filePath = NULL], [logical$ append = F])
Output all fixed mutations – all Substitution objects, in other words – in a SLiM native format. If the optional parameter filePath is NULL (the default), output will be sent to Eidos’s output stream. Otherwise, output will be sent to the filesystem path specified by filePath, overwriting that file if append if F, or appending to the end of it if append is T. Mutations which have fixed but have not been turned into Substitution objects – typically because convertToSubstitution has been set to F for their mutation type – are not output; they are still considered to be segregating mutations by SLiM.
In SLiM 3.3 and later, the output format includes the nucleotides associated with any nucleotide-based mutations.
Output is generally done in a late() event, so that the output reflects the state of the simulation at the end of a tick.
– (void)outputFull([Ns$ filePath = NULL], [logical$ binary = F], [logical$ append = F], [logical$ spatialPositions = T], [logical$ ages = T], [logical$ ancestralNucleotides = T], [logical$ pedigreeIDs = F])
Output the state of the entire population. If the optional parameter filePath is NULL (the default), output will be sent to Eidos’s output stream. Otherwise, output will be sent to the filesystem path specified by filePath, overwriting that file if append if F, or appending to the end of it if append is T. When writing to a file, a logical flag, binary, may be supplied as well. If binary is T, 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). The binary file is usually smaller, and in any case will be read much faster than the corresponding text file would be read. 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). If binary is F (the default), a text file will be written.
Beginning with SLiM 2.3, the spatialPositions 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 dimensionality option of initializeSLiMOptions(). If spatialPositions is F, the output will not contain spatial positions, and will be identical to the output generated by SLiM 2.1 and later. If spatialPositions is T, spatial position information will be output if it is available. If the species does not have continuous space enabled, the spatialPositions parameter will be ignored. Positional information may be output for all output destinations – the Eidos output stream, a text file, or a binary file.
Beginning with SLiM 3.0, the ages parameter may be used to control the output of the ages of individuals in nonWF simulations. If ages is F, the output will not contain ages, preserving backward compatibility with the output format of SLiM 2.1 and later. If ages is T, ages will be output for nonWF models. In WF simulations, the ages parameter will be ignored.
Beginning with SLiM 3.3, the ancestralNucleotides parameter may be used to control the output of the ancestral nucleotide sequence in nucleotide-based models. If ancestralNucleotides is F, 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 readPopulationFile(). 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 109 bases long, when saved in text format, or 0.25 GB when saved in binary format). If the model is not nucleotide-based (as enabled with the nucleotideBased parameter to initializeSLiMOptions()), the ancestralNucleotides parameter will be ignored. Note that in nucleotide-based models the output format will always include the nucleotides associated with any nucleotide-based mutations; the ancestralNucleotides flag governs only the ancestral sequence.
Beginning with SLiM 3.5, the pedigreeIDs parameter may be used to request that pedigree IDs be written out (and read in by readFromPopulationFile(), subsequently). This option is turned off (F) by default, to preserve backward compatibility; if it is turned on (T), 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’s optional pedigree tracking has been enabled with initializeSLiMOptions(keepPedigrees=T).
Output is generally done in a late() event, so that the output reflects the state of the simulation at the end of a tick.
– (void)outputMutations(object<Mutation> mutations, [Ns$ filePath = NULL], [logical$ append = F])
Output all of the given mutations. This can be used to output all mutations of a given mutation type, for example. If the optional parameter filePath is NULL (the default), output will be sent to Eidos’s output stream. Otherwise, output will be sent to the filesystem path specified by filePath, overwriting that file if append if F, or appending to the end of it if append is T.
In SLiM 3.3 and later, the output format includes the nucleotides associated with any nucleotide-based mutations.
Output is generally done in a late() event, so that the output reflects the state of the simulation at the end of a tick.
– (integer$)readFromPopulationFile(string$ filePath, [No$ subpopMap = NULL])
Read from a population initialization file, whether in text or binary format as previously specified to outputFull(), and return the tick counter value represented by the file’s contents (i.e., the tick at which the file was generated). Although this is most commonly used to set up initial populations (often in an Eidos event set to run in tick 1, immediately after simulation initialization), it may be called in any early() or late() Eidos event; the current state of all populations in the target species will be wiped and replaced by the state in the file at filePath. All Eidos variables that are of type object and have element type Subpopulation, Genome, Mutation, Individual, or Substitution will be removed as a side effect of this method if they contain any element that belongs to the target species, because those objects will no longer exist in the SLiM simulation; if you want to preserve any of that state, you should output it or save it to a file prior to this call. New symbols will be defined to refer to the new Subpopulation objects loaded from the file.
If the file being read was written by a version of SLiM prior to 2.3, then for backward compatibility fitness values will be calculated immediately for any new subpopulations created by this call, which will trigger the calling of any activated and applicable mutationEffect() and fitnessEffect() callbacks. When reading files written by SLiM 2.3 or later, fitness values are not calculated as a side effect of this call (because the simulation will often need to evaluate interactions or modify other state prior to doing so).
In SLiM 2.3 and later when using the WF model, calling readFromPopulationFile() from any context other than a late() event causes a warning; calling from a late() event is almost always correct in WF models, so that fitness values can be automatically recalculated by SLiM at the usual time in the tick cycle without the need to force their recalculation (see comments on recalculateFitness()).
In SLiM 3.0 when using the nonWF model, calling readFromPopulationFile() from any context other than an early() event causes a warning; calling from an early() event is almost always correct in nonWF models, so that fitness values can be automatically recalculated by SLiM at the usual time in the tick cycle without the need to force their recalculation (see comments on recalculateFitness()).
As of SLiM 2.1, this method changes the tick and cycle counters to the tick and cycle read from the file. If you do not want these counters to be changed, you can change them back after reading, by setting community.tick and sim.cycle to whatever values you wish. Note that restoring a saved past state and running forward again will not yield the same simulation results, because the random number generator’s state will not be the same; to ensure reproducibility from a given time point, setSeed() can be used to establish a new seed value. Any changes made to structure of the species (mutation types, genomic element types, etc.) will not be wiped and re-established by readFromPopulationFile(); this method loads only the population’s state, not the species configuration, so care should be taken to ensure that the species structure meshes coherently with the loaded data. Indeed, state such as the selfing and cloning rates of subpopulations, values set into tag properties, and values set onto objects with setValue() will also be lost, since it is not saved out by outputFull(). Only information saved by outputFull() will be restored; all other state associated with the species – subpopulations, individuals, genomes, mutations, and substitutions – will be lost, and should be re-established by the model if it is still needed.
As of SLiM 2.3, this method will read and restore the spatial positions of individuals if that information is present in the output file and the species has enabled continuous space (see outputFull() for details). If spatial positions are present in the output file but the species has not enabled continuous space (or the number of spatial dimensions does not match), an error will result. If the species has enabled continuous space but spatial positions are not present in the output file, the spatial positions of the individuals read will be undefined, but an error is not raised.
As of SLiM 3.0, this method will read and restore the ages of individuals if that information is present in the output file and the simulation is based upon the nonWF model. If ages are present but the simulation uses a WF model, an error will result; the WF model does not use age information. If ages are not present but the simulation uses a nonWF model, an error will also result; the nonWF model requires age information.
As of SLiM 3.3, this method will restore the nucleotides of nucleotide-based mutations, and will restore the ancestral nucleotide sequence, if that information is present in the output file. Loading an output file that contains nucleotide information in a non-nucleotide-based model, and vice versa, will produce an error.
As of SLiM 3.5, this method will read and restore the pedigree IDs of individuals and genomes if that information is present in the output file (as requested with outputFull(pedigreeIDs=T)) and if SLiM’s optional pedigree tracking has been enabled with initializeSLiMOptions(keepPedigrees=T).
This method can also be used to read tree-sequence (.trees) files saved by treeSeqOutput() or generated by the Python pyslim package. Note that the user metadata for a tree-sequence file can be read separately with the treeSeqMetadata() function. Beginning with SLiM 4, the subpopMap parameter may be supplied to re-order the populations of the input tree sequence when it is loaded in to SLiM. This parameter must have a value that is a Dictionary; the keys of this dictionary should be SLiM population identifiers as string values (e.g., "p2"), and the values should be indexes of populations in the input tree sequence; a key/value pair of "p2", 4 would mean that the fifth population in the input (the one at zero-based index 4) should become p2 on loading into SLiM. If subpopMap is non-NULL, all populations in the tree sequence must be explicitly mapped, even if their index will not change and even if they will not be used by SLiM; the only exception is for unused slots in the population table, which can be explicitly remapped but do not have to be. For instance, suppose we have a tree sequence in which population 0 is unused, population 1 is not a SLiM population (for example, an ancestral population produced by msprime), and population 2 is a SLiM population, and we want to load this in with population 2 as p0 in SLiM. To do this, we could supply a value of Dictionary("p0", 2, "p1", 1, "p2", 0) for subpopMap, or we could leave out slot 0 since it is unused, with Dictionary("p0", 2, "p1", 1). Although this facility cannot be used to remove populations in the tree sequence, note that it may add populations that will be visible when treeSeqOutput() is called (although these will not be SLiM populations); if, in this example, we had used Dictionary("p0", 0, "p1", 1, "p5", 2) and then we wrote the result out with treeSeqOutput(), the resulting tree sequence would have six populations, although three of them would be empty and would not be used by SLiM. The use of subpopMap makes it easier to load simulation data that was generated in Python, since that typically uses an id of 0. The subpopMap parameter may not be used with file formats other than tree-sequence files, at the present time; setting up the correct subpopulation ids is typically easier when working with those other formats. Note the tskit command-line interface can be used, like python3 -m tskit populations file.trees, to find out the number of subpopulations in a tree-sequence file and their IDs.
When loading a tree sequence, a crosscheck of the loaded data will be performed to ensure that the tree sequence was well-formed and was loaded correctly. When running a Release build of SLiM, however, this crosscheck will only occur the first time that readFromPopulationFile() is called to load a tree sequence; subsequent calls will not perform this crosscheck, for greater speed when running models that load saved population state many times (such as models that are conditional on fixation). If you suspect that a tree sequence file might be corrupted or read incorrectly, running a Debug build of SLiM enables crosschecks after every load.
– (void)recalculateFitness([Ni$ tick = NULL])
Force an immediate recalculation of fitness values for all individuals in all subpopulations. Normally fitness values are calculated at a fixed point in each tick, and those values are cached and used until the next recalculation. If simulation parameters are changed in script in a way that affects fitness calculations, and if you wish those changes to take effect immediately rather than taking effect at the next automatic recalculation, you may call recalculateFitness() to force an immediate recalculation and recache.
The optional parameter tick provides the tick for which mutationEffect() and fitnessEffect() callbacks should be selected; if it is NULL (the default), the current tick value for the simulation, community.tick, is used. If you call recalculateFitness() in an early() event in a WF model, you may wish this to be community.tick - 1 in order to utilize the mutationEffect() and fitnessEffect() callbacks for the previous tick, as if the changes that you have made to fitness-influencing parameters were already in effect at the end of the previous tick when the new generation was first created and evaluated (usually it is simpler to just make such changes in a late() event instead, however, in which case calling recalculateFitness() is probably not necessary at all since fitness values will be recalculated immediately afterwards). Regardless of the value supplied for tick here, community.tick inside callbacks will report the true tick number, so if your callbacks consult that parameter in order to create tick-specific fitness effects you will need to handle the discrepancy somehow. (Similar considerations apply for nonWF models that call recalculateFitness() in a late() event, which is also not advisable in general.)
After this call, the fitness values used for all purposes in SLiM will be the newly calculated values. Calling this method will trigger the calling of any enabled and applicable mutationEffect() and fitnessEffect() callbacks, so this is quite a heavyweight operation; you should think carefully about what side effects might result (which is why fitness recalculation does not just occur automatically after changes that might affect fitness values).
– (object<SLiMEidosBlock>$)registerFitnessEffectCallback(Nis$ id, string$ source, [Nio<Subpopulation>$ subpop = NULL], [Ni$ start = NULL], [Ni$ end = NULL])
Register a block of Eidos source code, represented as the string singleton source, as an Eidos fitnessEffect() callback in the current simulation (specific to the target species), with an optional subpopulation subpop (which may be an integer identifier, or NULL, the default, to indicate all subpopulations), and optional start and end ticks all limiting its applicability. The script block will be given identifier id (specified as an integer, or as a string symbolic name such as "s5"); this may be NULL if there is no need to be able to refer to the block later. The registered callback is added to the end of the list of registered SLiMEidosBlock objects, and is active immediately; it may be eligible to execute in the current tick. The new SLiMEidosBlock will be defined as a global variable immediately by this method, and will also be returned by this method.
– (object<SLiMEidosBlock>$)registerMateChoiceCallback(Nis$ id, string$ source, [Nio<Subpopulation>$ subpop = NULL], [Ni$ start = NULL], [Ni$ end = NULL])
Register a block of Eidos source code, represented as the string singleton source, as an Eidos mateChoice() callback in the current simulation (specific to the target species), with optional subpopulation subpop (which may be an integer identifier, or NULL, the default, to indicate all subpopulations) and optional start and end ticks all limiting its applicability. The script block will be given identifier id (specified as an integer, or as a string symbolic name such as "s5"); this may be NULL if there is no need to be able to refer to the block later. The registered callback is added to the end of the list of registered SLiMEidosBlock objects, and is active immediately; it may be eligible to execute in the current tick. The new SLiMEidosBlock will be defined as a global variable immediately by this method, and will also be returned by this method.
– (object<SLiMEidosBlock>$)registerModifyChildCallback(Nis$ id, string$ source, [Nio<Subpopulation>$ subpop = NULL], [Ni$ start = NULL], [Ni$ end = NULL])
Register a block of Eidos source code, represented as the string singleton source, as an Eidos modifyChild() callback in the current simulation (specific to the target species), with optional subpopulation subpop (which may be an integer identifier, or NULL, the default, to indicate all subpopulations) and optional start and end ticks all limiting its applicability. The script block will be given identifier id (specified as an integer, or as a string symbolic name such as "s5"); this may be NULL if there is no need to be able to refer to the block later. The registered callback is added to the end of the list of registered SLiMEidosBlock objects, and is active immediately; it may be eligible to execute in the current tick. The new SLiMEidosBlock will be defined as a global variable immediately by this method, and will also be returned by this method.
– (object<SLiMEidosBlock>$)registerMutationCallback(Nis$ id, string$ source, [Nio<MutationType>$ mutType = NULL], [Nio<Subpopulation>$ subpop = NULL], [Ni$ start = NULL], [Ni$ end = NULL])
Register a block of Eidos source code, represented as the string singleton source, as an Eidos mutation() callback in the current simulation (specific to the target species), with an optional mutation type mutType (which may be an integer mutation type identifier, or NULL, the default, to indicate all mutation types), optional subpopulation subpop (which may also be an integer identifier, or NULL, the default, to indicate all subpopulations), and optional start and end ticks all limiting its applicability. The script block will be given identifier id (specified as an integer, or as a string symbolic name such as "s5"); this may be NULL if there is no need to be able to refer to the block later. The registered callback is added to the end of the list of registered SLiMEidosBlock objects, and is active immediately; it may be eligible to execute in the current tick. The new SLiMEidosBlock will be defined as a global variable immediately by this method, and will also be returned by this method.
– (object<SLiMEidosBlock>$)registerMutationEffectCallback(Nis$ id, string$ source, io<MutationType>$ mutType, [Nio<Subpopulation>$ subpop = NULL], [Ni$ start = NULL], [Ni$ end = NULL])
Register a block of Eidos source code, represented as the string singleton source, as an Eidos mutationEffect() callback in the current simulation (specific to the target species), with a required mutation type mutType (which may be an integer mutation type identifier), optional subpopulation subpop (which may also be an integer identifier, or NULL, the default, to indicate all subpopulations), and optional start and end ticks all limiting its applicability. The script block will be given identifier id (specified as an integer, or as a string symbolic name such as "s5"); this may be NULL if there is no need to be able to refer to the block later. The registered callback is added to the end of the list of registered SLiMEidosBlock objects, and is active immediately; it may be eligible to execute in the current tick. The new SLiMEidosBlock will be defined as a global variable immediately by this method, and will also be returned by this method.
– (object<SLiMEidosBlock>$)registerRecombinationCallback(Nis$ id, string$ source, [Nio<Subpopulation>$ subpop = NULL], [Ni$ start = NULL], [Ni$ end = NULL])
Register a block of Eidos source code, represented as the string singleton source, as an Eidos recombination() callback in the current simulation (specific to the target species), with optional subpopulation subpop (which may be an integer identifier, or NULL, the default, to indicate all subpopulations) and optional start and end ticks all limiting its applicability. The script block will be given identifier id (specified as an integer, or as a string symbolic name such as "s5"); this may be NULL if there is no need to be able to refer to the block later. The registered callback is added to the end of the list of registered SLiMEidosBlock objects, and is active immediately; it may be eligible to execute in the current tick. The new SLiMEidosBlock will be defined as a global variable immediately by this method, and will also be returned by this method.
– (object<SLiMEidosBlock>$)registerReproductionCallback(Nis$ id, string$ source, [Nio<Subpopulation>$ subpop = NULL], [Ns$ sex = NULL], [Ni$ start = NULL], [Ni$ end = NULL])
Register a block of Eidos source code, represented as the string singleton source, as an Eidos reproduction() callback in the current simulation (specific to the target species), with optional subpopulation subpop (which may be an integer identifier, or NULL, the default, to indicate all subpopulations), optional sex-specificity sex (which may be "M" or "F" in sexual species to make the callback specific to males or females respectively, or NULL for no sex-specificity), and optional start and end ticks all limiting its applicability. The script block will be given identifier id (specified as an integer, or as a string symbolic name such as "s5"); this may be NULL if there is no need to be able to refer to the block later. The registered callback is added to the end of the list of registered SLiMEidosBlock objects, and is active immediately; it may be eligible to execute in the current tick. The new SLiMEidosBlock will be defined as a global variable immediately by this method, and will also be returned by this method.
– (object<SLiMEidosBlock>$)registerSurvivalCallback(Nis$ id, string$ source, [Nio<Subpopulation>$ subpop = NULL], [Ni$ start = NULL], [Ni$ end = NULL])
Register a block of Eidos source code, represented as the string singleton source, as an Eidos survival() callback in the current simulation (specific to the target species), with optional subpopulation subpop (which may be an integer identifier, or NULL, the default, to indicate all subpopulations) and optional start and end ticks all limiting its applicability. The script block will be given identifier id (specified as an integer, or as a string symbolic name such as "s5"); this may be NULL if there is no need to be able to refer to the block later. The registered callback is added to the end of the list of registered SLiMEidosBlock objects, and is active immediately; it may be eligible to execute in the current tick. The new SLiMEidosBlock will be defined as a global variable immediately by this method, and will also be returned by this method.
– (void)simulationFinished(void)
Declare the current simulation finished. This method is equivalent to the Community method simulationFinished(), except that this method is only legal to call in single-species models (to provide backward compatibility). It is recommended that new code should call the Community method; this method may be deprecated in the future.
– (void)skipTick(void)
Deactivate the target species for the current tick. This sets the active property of the species to F; it also set the active property of all callbacks that belong to the species (with the species as their species specifier) to F, and sets the active property of all events that are synchronized with the species (with the species as their ticks specifier) to F. The cycle counter for the species will not be incremented at the end of the tick. This method may only be called in first() events, to ensure that species are either active or inactive throughout a given tick.
– (object<Mutation>)subsetMutations([No<Mutation>$ exclude = NULL], [Nio<MutationType>$ mutType = NULL], [Ni$ position = NULL], [Nis$ nucleotide = NULL], [Ni$ tag = NULL], [Ni$ id = NULL])
Returns a vector of mutations subset from the list of all active mutations in the species (as would be provided by the mutations property). The parameters specify constraints upon the subset of mutations that will be returned. Parameter exclude, if non-NULL, may specify a specific mutation that should not be included (typically the focal mutation in some operation). Parameter mutType, if non-NULL, may specify a mutation type for the mutations to be returned (as either a MutationType object or an integer identifier). Parameter position, if non-NULL, may specify a base position for the mutations to be returned. Parameter nucleotide, if non-NULL, may specify a nucleotide for the mutations to be returned (either as a string, "A" / "C" / "G" / "T", or as an integer, 0 / 1 / 2 / 3 respectively). Parameter tag, if non-NULL, may specify a tag value for the mutations to be returned. Parameter id, if non-NULL, may specify a required value for the id property of the mutations to be returned.
This method is shorthand for getting the mutations property of the subpopulation, and then using operator [] to select only mutations with the desired properties; besides being much simpler than the equivalent Eidos code, it is also much faster. Note that if you only need to select on mutation type, the mutationsOfType() method will be even faster.
– (logical$)treeSeqCoalesced(void)
Returns the coalescence state for the recorded tree sequence at the last simplification. The returned value is a logical singleton flag, T to indicate that full coalescence was observed at the last tree-sequence simplification (meaning that there is a single ancestral individual that roots all ancestry trees at all sites along the chromosome – although not necessarily the same ancestor at all sites), or F if full coalescence was not observed. For simple models, reaching coalescence may indicate that the model has reached an equilibrium state, but this may not be true in models that modify the dynamics of the model during execution by changing migration rates, introducing new mutations programmatically, dictating non-random mating, etc., so be careful not to attach more meaning to coalescence than it is due; some models may require burn-in beyond coalescence to reach equilibrium, or may not have an equilibrium state at all. Also note that some actions by a model, such as adding a new subpopulation, may cause the coalescence state to revert from T back to F (at the next simplification), so a return value of T may not necessarily mean that the model is coalesced at the present moment – only that it was coalesced at the last simplification.
This method may only be called if tree sequence recording has been turned on with initializeTreeSeq(); in addition, checkCoalescence=T must have been supplied to initializeTreeSeq(), so that the necessary work is done during each tree-sequence simplification. Since this method does not perform coalescence checking itself, but instead simply returns the coalescence state observed at the last simplification, it may be desirable to call treeSeqSimplify() immediately before treeSeqCoalesced() to obtain up-to-date information. However, the speed penalty of doing this in every tick would be large, and most models do not need this level of precision; usually it is sufficient to know that the model has coalesced, without knowing whether that happened in the current tick or in a recent preceding tick.
– (void)treeSeqOutput(string$ path, [logical$ simplify = T], [logical$ includeModel = T], [No$ metadata = NULL])
Outputs the current tree sequence recording tables to the path specified by path. This method may only be called if tree sequence recording has been turned on with initializeTreeSeq(). If simplify is T (the default), simplification will be done immediately prior to output; this is almost always desirable, unless a model wishes to avoid simplification entirely. (Note that if simplification is not done, then all genomes since the last simplification will be marked as samples in the resulting tree sequence.) A binary tree sequence file will be written to the specified path; a filename extension of .trees is suggested for this type of file.
Normally, the full SLiM script used to generate the tree sequence is written out to the provenance entry of the tree sequence file, to the model subkey of the parameters top-level key. Supplying F for includeModel suppresses output of the full script.
A Dictionary object containing user-generated metadata may be supplied with the metadata parameter. If present, this dictionary will be serialized as JSON and attached to the saved tree sequence under a key named user_metadata, within the SLiM key. If tskit is used to read the tree sequence in Python, this metadata will automatically be deserialized and made available at ts.metadata["SLiM"]["user_metadata"]. This metadata dictionary is not used by SLiM, or by pyslim, tskit, or msprime; you may use it for any purpose you wish. Note that metadata may actually be any subclass of Dictionary, such as a DataFrame. It can even be a Species object such as sim, or a LogFile instance; however, only the keys and values contained by the object’s Dictionary superclass state will be serialized into the metadata (properties of the subclass will be ignored). This metadata dictionary can be recovered from the saved file using the treeSeqMetadata() function.
– (void)treeSeqRememberIndividuals(object<Individual> individuals, [logical$ permanent = T])
Mark the individuals specified by individuals to be kept across tree sequence table simplification. This method may only be called if tree sequence recording has been turned on with initializeTreeSeq(). All currently living individuals are always kept across simplification; this method does not need to be called, and indeed should not be called, for that purpose. Instead, treeSeqRememberIndividuals() allows any individual, including dead individuals, to be kept in the final tree sequence. Typically this would be used, for example, to keep particular individuals that you wanted to be able to trace ancestry back to in later analysis. However, this is not the typical usage pattern for tree sequence recording; most models will not need to call this method.
There are two ways to keep individuals across simplification. If permanent is T (the default), then the specified individuals will be permanently remembered: their genomes will be added to the current sample, and they will always be present in the tree sequence. Permanently remembering a large number of individuals will, of course, markedly increase memory usage and runtime.
Supplying F for permanent will instead mark the individuals only for (temporary) retention: their genomes will not be added to the sample, and they will appear in the final tree sequence only if one of their genomes is retained across simplification. In other words, the rule of thumb for retained individuals is simple: if a genome is kept by simplification, the genome’s corresponding individual is kept also, if it is retained. Note that permanent remembering takes priority; calling this function with permanent=F on an individual that has previously been permanently remembered will not remove it from the sample.
The behavior of simplification for individuals retained with permanent=F depends upon the value of the retainCoalescentOnly flag passed to initializeTreeSeq(); here we will discuss the behavior of that flag in detail. First of all, genomes are always removed by simplification unless they are (a) part of the final generation (i.e., in a living individual when simplification occurs), (b) ancestral to the final generation, (c) a genome of a permanently remembered individual, or (d) ancestral to a permanently remembered individual. If retainCoalescentOnly is T (the default), they are also always removed if they are not a branch point (i.e., a coalescent node or most recent common ancestor) in the tree sequence. In some cases it may be useful to retain a genome and its associated individual when it is simply an intermediate node in the ancestry (i.e., in the middle of a branch). This can be enabled by setting retainCoalescentOnly to F in your call to initializeTreeSeq(). In this case, ancestral genomes that are intermediate (“unary nodes”, in tskit parlance) and are within an individual that has been retained using the permanent=F flag here are kept, along with the retained individual itself. Since setting retainCoalescentOnly to F will prevent the unary nodes for retained individuals from being pruned, simplification may often be unable to prune very much at all from the tree sequence, and memory usage and runtime may increase rapidly. If you are retaining many individuals, this setting should therefore be used only with caution; it is not necessary if you are purely interested in the most recent common ancestors. See the pyslim documentation for further discussion of retaining and remembering individuals and the effects of the retainCoalescentOnly flag.
The metadata (age, location, etc) that are stored in the resulting tree sequence are those values present at either (a) the final generation, if the individual is alive when the tree sequence is output, or (b) the last time that the individual was remembered, if not. Calling treeSeqRememberIndividuals() on an individual that is already remembered will cause the archived information about the remembered individual to be updated to reflect the individual’s current state. A case where this is particularly important is for the spatial location of individuals in continuous-space models. SLiM automatically remembers the individuals that comprise the first generation of any new subpopulation created with addSubpop(), for easy recapitation and other analysis. However, since these first-generation individuals are remembered at the moment they are created, their spatial locations have not yet been set up, and will contain garbage – and those garbage values will be archived in their remembered state. If you need correct spatial locations of first-generation individuals for your post-simulation analysis, you should call treeSeqRememberIndividuals() explicitly on the first generation, after setting spatial locations, to update the archived information with the correct spatial positions.
– (void)treeSeqSimplify(void)
Triggers an immediate simplification of the tree sequence recording tables. This method may only be called if tree sequence recording has been turned on with initializeTreeSeq(). A call to this method will free up memory being used by entries that are no longer in the ancestral path of any individual within the current sample (currently living individuals, in other words, plus those explicitly added to the sample with treeSeqRememberIndividuals()), but it can also take a significant amount of time. Typically calling this method is not necessary; the automatic simplification performed occasionally by SLiM should be sufficient for most models.
5.17 Class Subpopulation
5.17.1 Subpopulation properties
cloningRate => (float)
The fraction of children in the next generation that will be produced by cloning (as opposed to biparental mating). In non-sexual (i.e. hermaphroditic) simulations, this property is a singleton float representing the overall subpopulation cloning rate. In sexual simulations, this property is a float vector with two values: the cloning rate for females (at index 0) and for males (at index 1).
description <–> (string$)
A human-readable string description for the subpopulation. By default, this is the empty string, ""; however, it may be set to whatever you wish. When tree-sequence recording is enabled, description is persisted in the subpopulation’s metadata in tree-sequence output.
firstMaleIndex => (integer$)
The index of the first male individual in the subpopulation. The genomes vector is sorted into females first and males second; firstMaleIndex gives the position of the boundary between those sections. Note, however, that there are two genomes per diploid individual, and the firstMaleIndex is not premultiplied by 2; you must multiply it by 2 before using it to decide whether a given index into genomes is a genome for a male or a female. The firstMaleIndex property is also the number of females in the subpopulation, given this design. For non-sexual (i.e. hermaphroditic) simulations, this property has an undefined value and should not be used.
fitnessScaling <–> (float$)
A float scaling factor applied to the fitness of all individuals in this subpopulation (i.e., the fitness value computed for each individual will be multiplied by this value). This is primarily of use in nonWF models, where fitness is absolute, rather than in WF models, where fitness is relative (and thus a constant factor multiplied into the fitness of every individual will make no difference); however, it may be used in either type of model. This provides a simple, fast way to modify the fitness of all individuals in a subpopulation; conceptually it is similar to returning the same fitness effect for all individuals in the subpopulation from a fitnessEffect() callback, but without the complexity and performance overhead of implementing such a callback. To scale the fitness of individuals by different (individual-specific) factors, see the fitnessScaling property of Individual.
The value of fitnessScaling is reset to 1.0 every tick, so that any scaling factor set lasts for only a single tick. This reset occurs immediately after fitness values are calculated, in both WF and nonWF models.
genomes => (object<Genome>)
All of the genomes contained by the subpopulation; there are two genomes per diploid individual.
genomesNonNull => (object<Genome>)
All of the genomes contained by the subpopulation, as with the genomes property, if all of them are not null genomes; any null genomes present are excluded from the returned vector. This is a convenience shorthand, sometimes useful in models that involve null genomes.
id => (integer$)
The identifier for this subpopulation; for subpopulation p3, for example, this is 3.
immigrantSubpopFractions => (float)
The expected value of the fraction of children in the next generation that are immigrants arriving from particular subpopulations.
immigrantSubpopIDs => (integer)
The identifiers of the particular subpopulations from which immigrants will arrive in the next generation.
individualCount => (integer$)
The number of individuals in the subpopulation; one-half of the number of genomes.
individuals => (object<Individual>)
All of the individuals contained by the subpopulation. Each individual is diploid and thus contains two Genome objects. See the sampleIndividuals() and subsetIndividuals() for fast ways to get a subset of the individuals in a subpopulation.
lifetimeReproductiveOutput => (integer)
If pedigree tracking is turned on with initializeSLiMOptions(keepPedigrees=T), lifetimeReproductiveOutput contains the value of the Individual property reproductiveOutput for all individuals in the subpopulation that died in the last viability/survival tick cycle stage (or, for WF models, immediately after reproduction). This allows access to the lifetime reproductive output of individuals in the subpopulation at the end of their lives. If pedigree tracking is not on, this property is unavailable.
lifetimeReproductiveOutputF => (integer)
If pedigree tracking is turned on with initializeSLiMOptions(keepPedigrees=T), lifetimeReproductiveOutputF contains the value of the Individual property reproductiveOutput for all female individuals in the subpopulation that died in the last viability/survival tick cycle stage (or, for WF models, immediately after reproduction). This property is undefined if separate sexes have not been enabled, or if pedigree tracking is not on.
lifetimeReproductiveOutputM => (integer)
If pedigree tracking is turned on with initializeSLiMOptions(keepPedigrees=T), lifetimeReproductiveOutputM contains the value of the Individual property reproductiveOutput for all male individuals in the subpopulation that died in the last viability/survival tick cycle stage (or, for WF models, immediately after reproduction). This property is undefined if separate sexes have not been enabled, or if pedigree tracking is not on.
name <–> (string$)
A human-readable string name for the subpopulation. By default, this is the subpopulation’s symbol as a string; for subpopulation p3, for example, name defaults to "p3". However, it may be set to whatever you wish except that subpopulation names must be unique across time (two different subpopulations may not both have the name "foo", even if they never exist at the same time). A subpopulation’s name may appear as a label in SLiMgui, and it can be useful in generating output, debugging, and other purposes. When tree-sequence recording is enabled, name is persisted in the subpopulation’s metadata in tree-sequence output, and can then be used in Python to identify the subpopulation; if you plan to take advantage of that feature, name should follow the syntax of Python identifiers: starting with a letter or underscore [a-zA-Z_], followed by letters, digits, or underscores [a-zA-Z0-9_], without spaces, hyphens, or other characters.
selfingRate => (float$)
The expected value of the fraction of children in the next generation that will be produced by selfing (as opposed to biparental mating). Selfing is only possible in non-sexual (i.e. hermaphroditic) simulations; for sexual simulations this property always has a value of 0.0.
sexRatio => (float$)
For sexual simulations, the sex ratio for the subpopulation. This is defined, in SLiM, as the fraction of the subpopulation that is male; in other words, it is actually the M:(M+F) ratio. For non-sexual (i.e. hermaphroditic) simulations, this property has an undefined value and should not be used.
spatialMaps => (object<SpatialMap>)
The spatial maps that are currently added to the subpopulation.
spatialBounds => (float)
The spatial boundaries of the subpopulation. The length of the spatialBounds property depends upon the spatial dimensionality declared with initializeSLiMOptions(). If the spatial dimensionality is zero (as it is by default), the value of this property is float(0) (a zero-length float vector). Otherwise, minimums are supplied for each coordinate used by the dimensionality of the simulation, followed by maximums for each. In other words, if the declared dimensionality is "xy", the spatialBounds property will contain values (x0, y0, x1, y1); bounds for the z coordinate will not be included in that case, since that coordinate is not used in the simulation’s dimensionality. This property cannot be set, but the setSpatialBounds() method may be used to achieve the same thing.
species => (object<Species>$)
The species to which the target object belongs.
tag <–> (integer$)
A user-defined integer value. The value of tag is initially undefined, and it is an error to try to read it; if you wish it to have a defined value, you must arrange that yourself by explicitly setting its value prior to using it elsewhere in your code. The value of tag is not used by SLiM; it is free for you to use. See also the getValue() and setValue() methods (provided by the Dictionary class; see the Eidos manual), for another way of attaching state to subpopulations.
5.17.2 Subpopulation methods
– (object<Individual>)addCloned(object<Individual>$ parent, [integer$ count = 1], [logical$ defer = F])
Generates a new offspring individual from the given parent by clonal reproduction, queues it for addition to the target subpopulation, and returns it. The new offspring will not be visible as a member of the target subpopulation until the end of the offspring generation tick cycle stage. The subpopulation of parent will be used to locate applicable mutation() and modifyChild() callbacks governing the generation of the offspring individual.
Beginning in SLiM 4.1, the count parameter dictates how many offspring will be generated (previously, exactly one offspring was generated). Each offspring is generated independently, based upon the given parameters. The returned vector contains all generated offspring, except those that were rejected by a modifyChild() callback. If all offspring are rejected, object<Individual>(0) is returned, which is a zero-length object vector of class Individual; note that this is a change in behavior from earlier versions, which would return NULL.
Beginning in SLiM 4.1, passing T for defer will defer the generation of the genomes of the produced offspring until the end of the reproduction phase. Genome generation can only be deferred if there are no active mutation() callbacks; otherwise, an error will result. Furthermore, when genome generation is deferred the mutations of the genomes of the generated offspring may not be accessed until reproduction is complete (whether from a modifyChild() callback or otherwise). There is little or no advantage to deferring genome generation when running single-threaded; in that case, the default of F for defer is generally preferable since it has fewer restrictions. When running multi-threaded, deferring genome generation allows that task to be done in parallel (which is the reason this option exists).
Also beginning in SLiM 4.1, in spatial models the spatial position of the offspring will be inherited (i.e., copied) from parent; more specifically, the x property will be inherited in all spatial models (1D/2D/3D), the y property in 2D/3D models, and the z property in 3D models. Properties not inherited will be left uninitialized, as they were prior to SLiM 4.1. The parent’s spatial position is probably not desirable in itself; the intention here is to make it easy to model the natal dispersal of all the new offspring for a given tick with a single vectorized call to deviatePositions() / pointDeviated().
Note that this method is only for use in nonWF models. See addCrossed() for further general notes on the addition of new offspring individuals.
– (object<Individual>)addCrossed(object<Individual>$ parent1, object<Individual>$ parent2, [Nfs$ sex = NULL], [integer$ count = 1], [logical$ defer = F])
Generates a new offspring individual from the given parents by biparental sexual reproduction, queues it for addition to the target subpopulation, and returns it. The new offspring will not be visible as a member of the target subpopulation until the end of the offspring generation tick cycle stage. Attempting to use a newly generated offspring individual as a mate, or to reference it as a member of the target subpopulation in any other way, will result in an error. In most models the returned individual is not used, but it is provided for maximal generality and flexibility.
The new offspring individual is generated from parent1 and parent2 by crossing them. In sexual models parent1 must be female and parent2 must be male; in hermaphroditic models, parent1 and parent2 are unrestricted. If parent1 and parent2 are the same individual in a hermaphroditic model, that parent self-fertilizes, or “selfs”, to generate the offspring sexually (note this is not the same as clonal reproduction). Such selfing is considered “incidental” by addCrossed(), however; if the preventIncidentalSelfing flag of initializeSLiMOptions() is T, supplying the same individual for parent1 and parent2 is an error (you must check for and prevent incidental selfing if you set that flag in a nonWF model). If non-incidental selfing is desired, addSelfed() should be used instead.
The sex parameter specifies the sex of the offspring. A value of NULL means “make the default choice”; in non-sexual models it is the only legal value for sex, and does nothing, whereas in sexual models it causes male or female to be chosen with equal probability. A value of "M" or "F" for sex specifies that the offspring should be male or female, respectively. Finally, a float value from 0.0 to 1.0 for sex provides the probability that the offspring will be male; a value of 0.0 will produce a female, a value of 1.0 will produce a male, and for intermediate values SLiM will draw the sex of the offspring randomly according to the specified probability. Unless you wish the bias the sex ratio of offspring, the default value of NULL should generally be used.
Note that any defined, active, and applicable recombination(), mutation(), and modifyChild() callbacks will be called as a side effect of calling this method, before this method even returns. For recombination() and mutation() callbacks, the subpopulation of the parent that is generating a given gamete is used; for modifyChild() callbacks the situation is more complex. In most biparental mating events, parent1 and parent2 will belong to the same subpopulation, and modifyChild() callbacks for that subpopulation will be used, just as in WF models. In certain models (such as models of pollen flow and broadcast spawning), however, biparental mating may occur between parents that are not from the same subpopulation; that is legal in nonWF models, and in that case, modifyChild() callbacks for the subpopulation of parent1 are used (since that is the maternal parent).
If the modifyChild() callback process results in rejection of the proposed child, a new offspring individual is not be generated. To force the generation of an offspring individual from a given pair of parents, you could loop until addCrossed() succeeds, but note that if your modifyChild() callback rejects all proposed children from those particular parents, your model will then hang, so care must be taken with this approach. Usually, nonWF models do not force generation of offspring in this manner; rejection of a proposed offspring by a modifyChild() callback typically represents a phenomenon such as post-mating reproductive isolation or lethal genetic incompatibilities that would reduce the expected litter size, so the default behavior is typically desirable.
Beginning in SLiM 4.1, the count parameter dictates how many offspring will be generated (previously, exactly one offspring was generated). Each offspring is generated independently, based upon the given parameters. The returned vector contains all generated offspring, except those that were rejected by a modifyChild() callback. If all offspring are rejected, object<Individual>(0) is returned, which is a zero-length object vector of class Individual; note that this is a change in behavior from earlier versions, which would return NULL.
Beginning in SLiM 4.1, passing T for defer will defer the generation of the genomes of the produced offspring until the end of the reproduction phase. Genome generation can only be deferred if there are no active mutation() or recombination() callbacks; otherwise, an error will result. Furthermore, when genome generation is deferred the mutations of the genomes of the generated offspring may not be accessed until reproduction is complete (whether from a modifyChild() callback or otherwise). There is little or no advantage to deferring genome generation when running single-threaded; in that case, the default of F for defer is generally preferable since it has fewer restrictions. When running multi-threaded, deferring genome generation allows that task to be done in parallel (which is the reason this option exists).
Also beginning in SLiM 4.1, in spatial models the spatial position of the offspring will be inherited (i.e., copied) from parent1; more specifically, the x property will be inherited in all spatial models (1D/2D/3D), the y property in 2D/3D models, and the z property in 3D models. Properties not inherited will be left uninitialized, as they were prior to SLiM 4.1. The parent’s spatial position is probably not desirable in itself; the intention here is to make it easy to model the natal dispersal of all the new offspring for a given tick with a single vectorized call to deviatePositions() / pointDeviated().
Note that this method is only for use in nonWF models, in which offspring generation is managed manually by the model script; in such models, addCrossed() must be called only from reproduction() callbacks, and may not be called at any other time. In WF models, offspring generation is managed automatically by the SLiM core.
– (object<Individual>)addEmpty([Nfs$ sex = NULL], [Nl$ genome1Null = NULL], [Nl$ genome2Null = NULL], [integer$ count = 1])
Generates a new offspring individual with empty genomes (i.e., containing no mutations), queues it for addition to the target subpopulation, and returns it. The new offspring will not be visible as a member of the target subpopulation until the end of the offspring generation tick cycle stage. No recombination() or mutation() callbacks will be called. The target subpopulation will be used to locate applicable modifyChild() callbacks governing the generation of the offspring individual (unlike the other addX() methods, because there is no parental individual to reference). The offspring is considered to have no parents for the purposes of pedigree tracking. The sex parameter is treated as in addCrossed().
By default – when genome1Null and genome2Null are both NULL – null genomes will be generated instead of empty genomes only in sex-chromosome simulations, where the sex chromosome that is not being simulated is represented by a null genome; otherwise, empty genomes rather than null genomes will be created. This default behavior can be changed by passing T or F for genome1Null or genome2Null, which will force the corresponding offspring genome to be null (T) or non-null (F). The behavior in sex-chromosome simulations cannot be changed, since the presence of null genomes there is dictated by sex, but T or F may be passed as long as it matches what SLiM would do anyway. In all other simulations there is little point in passing F (since that would be the default behavior anyway), but passing T can be used to make one or both genomes be null genomes, which can be useful for, e.g., modeling haploids (for which, by convention, the second genome is usually a null genome in SLiM).
Beginning in SLiM 4.1, the count parameter dictates how many offspring will be generated (previously, exactly one offspring was generated). Each offspring is generated independently, based upon the given parameters. The returned vector contains all generated offspring, except those that were rejected by a modifyChild() callback. If all offspring are rejected, object<Individual>(0) is returned, which is a zero-length object vector of class Individual; note that this is a change in behavior from earlier versions, which would return NULL.
Note that this method is only for use in nonWF models. See addCrossed() for further general notes on the addition of new offspring individuals.
– (object<Individual>)addRecombinant(No<Genome>$ strand1, No<Genome>$ strand2, Ni breaks1, No<Genome>$ strand3, No<Genome>$ strand4, Ni breaks2, [Nfs$ sex = NULL], [No<Individual>$ parent1 = NULL], [No<Individual>$ parent2 = NULL], [logical$ randomizeStrands = F], [integer$ count = 1], [logical$ defer = F])
Generates a new offspring individual from the given parental genomes with the specified crossover breakpoints, queues it for addition to the target subpopulation, and returns it. The new offspring will not be visible as a member of the target subpopulation until the end of the offspring generation tick cycle stage. The target subpopulation will be used to locate applicable mutation() and modifyChild() callbacks governing the generation of the offspring individual (unlike the other addX() methods, because there are potentially up to four parental individuals to reference); recombination() callbacks will not be called by this method. This method is an advanced feature; most models will use addCrossed(), addSelfed(), or addCloned() instead.
This method supports several possible configurations for strand1, strand2, and breaks1 (and the same applies for strand3, strand4, and breaks2). If strand1 and strand2 are both NULL, the corresponding genome in the generated offspring will be empty, as from addEmpty(), with no parental genomes and no added mutations; in this case, breaks1 must be NULL or zero-length. If strand1 is non-NULL but strand2 is NULL, the corresponding genome in the generated offspring will be a clonal copy of strand1 with mutations added, as from addCloned(); in this case, breaks1 must similarly be NULL or zero-length. If strand1 and strand2 are both non-NULL, the corresponding genome in the generated offspring will result from recombination between strand1 and strand2 with mutations added, as from addCrossed(), with strand1 being the initial copy strand; copying will switch between strands at each breakpoint in breaks1, which must be non-NULL but need not be sorted or uniqued (SLiM will sort and unique the supplied breakpoints internally). (It is not currently legal for strand1 to be NULL and strand2 non-NULL; that variant may be assigned some meaning in future.) Again, this discussion applies equally to strand3, strand4, and breaks2, mutatis mutandis. Note that when new mutations are generated by addRecombinant(), their subpopID property will be the id of the offspring’s subpopulation, since the parental subpopulation is ambiguous; this behavior differs from the other add...() methods.
The sex parameter is interpreted exactly as in addCrossed(); see that method for discussion. If the offspring sex is specified in any way (i.e., if sex is non-NULL), the strands provided must be compatible with the sex chosen. If the offspring sex is not specified (i.e., if sex is NULL), the sex will be inferred from the strands provided where possible (when modeling an X or Y chromosome), or will be chosen randomly otherwise (when modeling autosomes); it will not be inferred from the sex of the individuals possessing the parental strands, even when the reproductive mode is essentially clonal from a single parent, since such inference would be ambiguous in the general case. When modeling the X or Y, strand1 and strand2 must be X genomes (or NULL), and strand3 and strand4 must both be X genomes or both be Y genomes (or NULL).
By default, the offspring is considered to have no parents for the purposes of pedigree tracking, since there may be more than two “parents” in the general case. If pedigree tracking of parentage is desired, parent1 and/or parent2 may be passed to explicitly establish particular individuals as the parents of the offspring for purposes of pedigree tracking. In this case, if only one of parent1 and parent2 is non-NULL, that individual will be set as both of the parents of the offspring, mirroring the way that parentage is tracked for other cases such as addCloned() and addSelfed(). It is not required for parent1 or parent2 to actually be a genetic parent of the offspring at all, although typically they would be.
If randomizeStrands is F (the default), strand1 will be the initial copy strand when generating the first gamete to form the offspring, and strand3 will be the initial copy strand when generating the second gamete. If randomizeStrands is T, then if strand1 and strand2 are both non-NULL, 50% of the time they will be swapped, making strand2 the initial copy strand for the first gamete; and similarly, if strand3 and strand4 are both non-NULL, 50% of the time they will be swapped, making strand4 the initial copy strand for the second gamete. This is probably usually the desired behavior, to avoid an inheritance bias due to a lack of randomization in the initial copy strand, so passing T for randomizeStrands is recommended unless you specifically desire otherwise. It is not the default behavior only for reasons of backward compatibility.
These semantics allow several uses for addRecombinant(). When all strands are non-NULL, it is similar to addCrossed() except that the recombination breakpoints are specified explicitly, allowing very precise offspring generation without having to override SLiM’s breakpoint generation with a recombination() callback. When only strand1 and strand3 are supplied, it is very similar to addCloned(), creating a clonal offspring, except that the two parental genomes need not belong to the same individual (whatever that might mean biologically). Supplying only strand1 is useful for modeling clonally reproducing haploids; the second genome of every offspring will be kept empty and will not receive new mutations. For a model of clonally reproducing haploids that undergo horizontal gene transfer (HGT), supplying only strand1 and strand2 will allow HGT from strand2 to replace segments of an otherwise clonal copy of strand1, while the second genome of the generated offspring will again be kept empty; this could be useful for modeling bacterial conjugation, for example. Other variations are also possible.
The value of the meanParentAge property of the generated offspring is calculated from the mean parent age of each of its two genomes (whether they turn out to be null genomes or not); that may be an average of two values (if both offspring genomes have at least one parent), a single value (if one offspring genome has no parent), or no values (if both offspring genomes have no parent, in which case 0.0 results). The mean parent age of a given offspring genome is the mean of the ages of the parents of the two strands used to generate that offspring genome; if one strand is NULL then the mean parent age for that offspring genome is the age of the parent of the non-NULL strand, while if both strands are NULL then that offspring genome is parentless and is not used in the final calculation. In other words, if one offspring genome has two parents with ages A and B, and the other offspring genome has one parent with age C, the meanParentAge of the offspring will be (A+B+C+C) / 4, not (A+B+C) / 3.
Note that gene conversion tracts are not explicitly supported by this method; the breaks vectors provide crossover breakpoints, which may be used to implement crossovers or simple gene conversion tracts. There is no way to specify complex gene conversion tracts with heteroduplex mismatch repair.
Beginning in SLiM 4.1, the count parameter dictates how many offspring will be generated (previously, exactly one offspring was generated). Each offspring is generated independently, based upon the given parameters. The returned vector contains all generated offspring, except those that were rejected by a modifyChild() callback. If all offspring are rejected, object<Individual>(0) is returned, which is a zero-length object vector of class Individual; note that this is a change in behavior from earlier versions, which would return NULL.
Beginning in SLiM 4.1, passing T for defer will defer the generation of the genomes of the produced offspring until the end of the reproduction phase. Genome generation can only be deferred if there are no active mutation() callbacks; otherwise, an error will result. Furthermore, when genome generation is deferred the mutations of the genomes of the generated offspring may not be accessed until reproduction is complete (whether from a modifyChild() callback or otherwise). There is little or no advantage to deferring genome generation when running single-threaded; in that case, the default of F for defer is generally preferable since it has fewer restrictions. When running multi-threaded, deferring genome generation allows that task to be done in parallel (which is the reason this option exists).
Also beginning in SLiM 4.1, in spatial models the spatial position of the offspring will be inherited (i.e., copied) from parent1; more specifically, the x property will be inherited in all spatial models (1D/2D/3D), the y property in 2D/3D models, and the z property in 3D models. Properties not inherited will be left uninitialized, as they were prior to SLiM 4.1. The parent’s spatial position is probably not desirable in itself; the intention here is to make it easy to model the natal dispersal of all the new offspring for a given tick with a single vectorized call to deviatePositions() / pointDeviated(). If parent1 is NULL (the default), parent2 will be used; if it is also NULL, no spatial position will be inherited.
Note that this method is only for use in nonWF models. See addCrossed() for further general notes on the addition of new offspring individuals.
– (object<Individual>)addSelfed(object<Individual>$ parent, [integer$ count = 1], [logical$ defer = F])
Generates a new offspring individual from the given parent by selfing, queues it for addition to the target subpopulation, and returns it. The new offspring will not be visible as a member of the target subpopulation until the end of the offspring generation tick cycle stage. The subpopulation of parent will be used to locate applicable mutation(), recombination(), and modifyChild() callbacks governing the generation of the offspring individual.
Since selfing requires that parent act as a source of both a male and a female gamete, this method may be called only in hermaphroditic models; calling it in sexual models will result in an error. This method represents a non-incidental selfing event, so the preventIncidentalSelfing flag of initializeSLiMOptions() has no effect on this method (in contrast to the behavior of addCrossed(), where selfing is assumed to be incidental).
Beginning in SLiM 4.1, the count parameter dictates how many offspring will be generated (previously, exactly one offspring was generated). Each offspring is generated independently, based upon the given parameters. The returned vector contains all generated offspring, except those that were rejected by a modifyChild() callback. If all offspring are rejected, object<Individual>(0) is returned, which is a zero-length object vector of class Individual; note that this is a change in behavior from earlier versions, which would return NULL.
Beginning in SLiM 4.1, passing T for defer will defer the generation of the genomes of the produced offspring until the end of the reproduction phase. Genome generation can only be deferred if there are no active mutation() or recombination() callbacks; otherwise, an error will result. Furthermore, when genome generation is deferred the mutations of the genomes of the generated offspring may not be accessed until reproduction is complete (whether from a modifyChild() callback or otherwise). There is little or no advantage to deferring genome generation when running single-threaded; in that case, the default of F for defer is generally preferable since it has fewer restrictions. When running multi-threaded, deferring genome generation allows that task to be done in parallel (which is the reason this option exists).
Also beginning in SLiM 4.1, in spatial models the spatial position of the offspring will be inherited (i.e., copied) from parent; more specifically, the x property will be inherited in all spatial models (1D/2D/3D), the y property in 2D/3D models, and the z property in 3D models. Properties not inherited will be left uninitialized, as they were prior to SLiM 4.1. The parent’s spatial position is probably not desirable in itself; the intention here is to make it easy to model the natal dispersal of all the new offspring for a given tick with a single vectorized call to deviatePositions() / pointDeviated().
Note that this method is only for use in nonWF models. See addCrossed() for further general notes on the addition of new offspring individuals.
– (void)addSpatialMap(object<SpatialMap>$ map)
Adds the given SpatialMap object, map, to the subpopulation. (The spatial map would have been previously created with a call to defineSpatialMap() on a different subpopulation; addSpatialMap() can then be used to add that existing spatial map with other subpopulations, sharing the map between subpopulations.) If the map is already added to the target subpopulation, this method does nothing; if a different map with the same name is already added to the subpopulation, an error results (because map names must be unique within each subpopulation). The map being added must be compatible with the target subpopulation; in particular, the spatial bounds utilized by the map must exactly match the corresponding spatial bounds for the subpopulation, and the dimensionality of the subpopulation must encompass the spatiality of the map. For example, if the map has a spatiality of "xz" then the subpopulation must have a dimensionality of "xyz" so that it encompasses both "x" and "z", and the subpopulation’s spatial bounds for "x" and "z" must match those for the map (but the spatial bounds for "y" are unimportant, since the map does not use that dimension).
Adding a map to a subpopulation is not strictly necessary, at present; one may query a SpatialMap object directly using mapValue(), regarding points in a subpopulation, without the map actually having been added to that subpopulation. However, it is a good idea to use addSpatialMap(), both for its compatibility check that prevents unnoticed scripting errors, and because it ensures correct display of the model in SLiMgui.
– (float)cachedFitness(Ni indices)
The fitness values calculated for the individuals at the indices given are returned. If NULL is passed, fitness values for all individuals in the subpopulation are returned. The fitness values returned are cached values; mutationEffect() and fitnessEffect() callbacks are therefore not called as a side effect of this method. It is always an error to call cachedFitness() from inside a mutationEffect() or fitnessEffect() callback, since fitness values are in the middle of being set up. In WF models, it is also an error to call cachedFitness() from a late() event, because fitness values for the new offspring generation have not yet been calculated and are undefined. In nonWF models, the population may be a mixture of new and old individuals, so instead, NAN will be returned as the fitness of any new individuals whose fitness has not yet been calculated. When new subpopulations are first created with addSubpop() or addSubpopSplit(), the fitness of all of the newly created individuals is considered to be 1.0 until fitness values are recalculated.
– (void)configureDisplay([Nf center = NULL], [Nf$ scale = NULL], [Ns$ color = NULL])
This method customizes the display of the subpopulation in SLiMgui’s Population Visualization graph. When this method is called by a model running outside SLiMgui, it will do nothing except type-checking and bounds-checking its arguments. When called by a model running in SLiMgui, the position, size, and color of the subpopulation’s displayed circle can be controlled as specified below.
The center parameter sets the coordinates of the center of the subpopulation’s displayed circle; it must be a float vector of length two, such that center[0] provides the x-coordinate and center[1] provides the y-coordinate. The square central area of the Population Visualization occupies scaled coordinates in [0,1] for both x and y, so the values in center must be within those bounds. If a value of NULL is provided, SLiMgui’s default center will be used (which currently arranges subpopulations in a circle).
The scale parameter sets a scaling factor to be applied to the radius of the subpopulation’s displayed circle. The default radius used by SLiMgui is a function of the subpopulation’s number of individuals; this default radius is then multiplied by scale. If a value of NULL is provided, the default radius will be used; this is equivalent to supplying a scale of 1.0. Typically the same scale value should be used by all subpopulations, to scale all of their circles up or down uniformly, but that is not required.
The color parameter sets the color to be used for the displayed subpopulation’s circle. Colors may be specified by name, or with hexadecimal RGB values of the form "#RRGGBB" (see the Eidos manual). If color is NULL or the empty string, "", SLiMgui’s default (fitness-based) color will be used.
– (object<SpatialMap>$)defineSpatialMap(string$ name, string$ spatiality, numeric values, [logical$ interpolate = F], [Nif valueRange = NULL], [Ns colors = NULL])
Defines a spatial map for the subpopulation; see the SpatialMap documentation regarding this class. The new map is automatically added to the subpopulation; addSpatialMap() does not need to be called. (That method is for sharing the map with additional subpopulations, beyond the one for which the map was originally defined.) The new SpatialMap object is returned, and may be retained permanently using defineConstant() or defineGlobal() for convenience.
The name of the map is given by name, and can be used to identify it. The map uses the spatial dimensions referenced by spatiality, which must be a subset of the dimensions defined for the simulation in initializeSLiMOptions(). Spatiality "x" is permitted for dimensionality "x"; spatiality "x", "y", or "xy" for dimensionality "xy"; and spatiality "x", "y", "z", "xy", "yz", "xz", or "xyz" for dimensionality "xyz". The spatial map is defined by a grid of values supplied in parameter values. That grid of values is aligned with the spatial bounds of the subpopulation, as described in more detail below; the spatial map is therefore coupled to those spatial bounds, and can only be used in subpopulations that match those particular spatial bounds (to avoid stretching or shrinking the map). The remaining optional parameters are described below.
Note that the semantics of this method changed in SLiM 3.5; in particular, the gridSize parameter was removed, and the interpretation of the values parameter changed as described below. Existing code written prior to SLiM 3.5 will produce an error, due to the removed gridSize parameter, and must be revised carefully to obtain the same result, even if NULL had been passed for gridSize previously.
Beginning in SLiM 3.5, the values parameter must be a vector/matrix/array with the number of dimensions appropriate for the declared spatiality of the map; for example, a map with spatiality "x" would require a (one-dimensional) vector, spatiality "xy" would require a (two-dimensional) matrix, and a map with spatiality of "xyz" would require a three-dimensional array. (See the Eidos manual for discussion of vectors, matrices, and arrays.) The data in values is interpreted in such a way that a two-dimensional matrix of values, with (0, 0) at upper left and values by column, is transformed into the format expected by SLiM, with (0, 0) at lower left and values by row; in other words, the two-dimensional matrix as it prints in the Eidos console will match the appearance of the two-dimensional spatial map as seen in SLiMgui. This is a change in behavior from versions prior to SLiM 3.5; it ensures that images loaded from disk with the Eidos class Image can be used directly as spatial maps, achieving the expected orientation, with no need for transposition or flipping. If the spatial map is a three-dimensional array, it is read as successive z-axis “planes”, each of which is a two-dimensional matrix that is treated as described above.
Moving on to the other parameters of defineSpatialMap(): if interpolate is F, values across the spatial map are not interpolated; the value at a given point is equal to the nearest value defined by the grid of values specified. If interpolate is T, values across the spatial map will be interpolated (using linear, bilinear, or trilinear interpolation as appropriate) to produce spatially continuous variation in values. In either case, the corners of the value grid are exactly aligned with the corners of the spatial boundaries of the subpopulation as specified by setSpatialBounds(), and the value grid is then stretched across the spatial extent of the subpopulation in such a manner as to produce equal spacing between the values along each dimension. The setting of interpolation only affects how values between these grid points are calculated: by nearest-neighbor, or by linear interpolation. Interpolation of spatial maps with periodic boundaries is not handled specially; to ensure that the edges of a periodic spatial map join smoothly, simply ensure that the grid values at the edges of the map are identical, since they will be coincident after periodic wrapping. Note that cubic/bicubic interpolation is generally smoother than linear/bilinear interpolation, with fewer artifacts, but it is substantially slower to calculate; use the interpolate() method of SpatialMap to precalculate an interpolated map using cubic/bucubic interpolation.
The valueRange and colors parameters travel together; either both are unspecified, or both are specified. They control how map values will be transformed into colors, by SLiMgui and by the mapColor() method. The valueRange parameter establishes the color-mapped range of spatial map values, as a vector of length two specifying a minimum and maximum; this does not need to match the actual range of values in the map. The colors parameter then establishes the corresponding colors for values within the interval defined by valueRange: values less than or equal to valueRange[0] will map to colors[0], values greater than or equal to valueRange[1] will map to the last colors value, and intermediate values will shade continuously through the specified vector of colors, with interpolation between adjacent colors to produce a continuous spectrum. This is much simpler than it sounds in this description; see the recipes in chapter 15 for an illustration of its use.
Note that at present, SLiMgui will only display spatial maps of spatiality "x", "y", or "xy"; the color-mapping parameters will simply be ignored by SLiMgui for other spatiality values (even if the spatiality is a superset of these values; SLiMgui will not attempt to display an "xyz" spatial map, for example, since it has no way to choose which 2D slice through the xyz space it ought to display). The mapColor() method will return translated color strings for any spatial map, however, even if SLiMgui is unable to display the spatial map. If there are multiple spatial maps that SLiMgui is capable of displaying, it choose one for display by default, but other maps may be selected from the action menu on the individuals view (by clicking on the button with the gear icon).
– (void)deviatePositions(No<Individual> individuals, string$ boundary, numeric$ maxDistance, string$ functionType, ...)
Deviates the spatial positions of the individuals supplied in individuals, using the provided boundary condition and dispersal kernel. If individuals is NULL, the positions of all individuals in the target subpopulation are deviated. This method is essentially a more efficient shorthand for getting the spatial positions of individuals from the spatialPosition property, deviating those positions with pointDeviated(), and setting the deviated positions back into individuals with the setSpatialPosition() method. The boundary condition boundary must be one of "none", "periodic", "reflecting", "stopping", or "reprising", and the spatial kernel type functionType must be one of "f", "l", "e", "n", or "t", with the ellipsis parameters ... supplying kernel configuration parameters appropriate for that kernel type; see pointDeviated() for further details.
– (void)outputMSSample(integer$ sampleSize, [logical$ replace = T], [string$ requestedSex = "*"], [Ns$ filePath = NULL], [logical$ append = F], [logical$ filterMonomorphic = F])
Output a random sample from the subpopulation in MS format. Positions in the output will span the interval [0,1]. A sample of genomes (not entire individuals, note) of size sampleSize from the subpopulation will be output. The sample may be done either with or without replacement, as specified by replace; the default is to sample with replacement. A particular sex of individuals may be requested for the sample, for simulations in which sex is enabled, by passing "M" or "F" for requestedSex; passing "*", the default, indicates that genomes from individuals should be selected randomly, without respect to sex. If the sampling options provided by this method are not adequate, see the outputMS() method of Genome for a more flexible low-level option.
If the optional parameter filePath is NULL (the default), output will be sent to Eidos’s output stream. Otherwise, output will be sent to the filesystem path specified by filePath, overwriting that file if append if F, or appending to the end of it if append is T.
If filterMonomorphic is F (the default), all mutations that are present in the sample will be included in the output. This means that some mutations may be included that are actually monomorphic within the sample (i.e., that exist in every sampled genome, and are thus apparently fixed). These may be filtered out with filterMonomorphic = T if desired; note that this option means that some mutations that do exist in the sampled genomes might not be included in the output, simply because they exist in every sampled genome.
See outputSample() and outputVCFSample() for other output formats. Output is generally done in a late() event, so that the output reflects the state of the simulation at the end of a tick.
– (void)outputSample(integer$ sampleSize, [logical$ replace = T], [string$ requestedSex = "*"], [Ns$ filePath = NULL], [logical$ append = F])
Output a random sample from the subpopulation in SLiM’s native format. A sample of genomes (not entire individuals, note) of size sampleSize from the subpopulation will be output. The sample may be done either with or without replacement, as specified by replace; the default is to sample with replacement. A particular sex of individuals may be requested for the sample, for simulations in which sex is enabled, by passing "M" or "F" for requestedSex; passing "*", the default, indicates that genomes from individuals should be selected randomly, without respect to sex. If the sampling options provided by this method are not adequate, see the output() method of Genome for a more flexible low-level option.
If the optional parameter filePath is NULL (the default), output will be sent to Eidos’s output stream. Otherwise, output will be sent to the filesystem path specified by filePath, overwriting that file if append if F, or appending to the end of it if append is T.
See outputMSSample() and outputVCFSample() for other output formats. Output is generally done in a late() event, so that the output reflects the state of the simulation at the end of a tick.
– (void)outputVCFSample(integer$ sampleSize, [logical$ replace = T], [string$ requestedSex = "*"], [logical$ outputMultiallelics = T], [Ns$ filePath = NULL], [logical$ append = F], [logical$ simplifyNucleotides = F], [logical$ outputNonnucleotides = T])
Output a random sample from the subpopulation in VCF format. A sample of individuals (not genomes, note – unlike the outputSample() and outputMSSample() methods) of size sampleSize from the subpopulation will be output. The sample may be done either with or without replacement, as specified by replace; the default is to sample with replacement. A particular sex of individuals may be requested for the sample, for simulations in which sex is enabled, by passing "M" or "F" for requestedSex; passing "*", the default, indicates that genomes from individuals should be selected randomly, without respect to sex. If the sampling options provided by this method are not adequate, see the outputVCF() method of Genome for a more flexible low-level option.
If the optional parameter filePath is NULL (the default), output will be sent to Eidos’s output stream. Otherwise, output will be sent to the filesystem path specified by filePath, overwriting that file if append if F, or appending to the end of it if append is T.
The parameters outputMultiallelics, simplifyNucleotides, and outputNonnucleotides affect the format of the output produced; see the reference documentation for further discussion.
See outputMSSample() and outputSample() for other output formats. Output is generally done in a late() event, so that the output reflects the state of the simulation at the end of a tick.
– (float)pointDeviated(integer$ n, float point, string$ boundary, numeric$ maxDistance, string$ functionType, ...)
Returns a vector containing n points that are derived from point by adding a deviation drawn from a dispersal kernel (specified by maxDistance, functionType, and the ellipsis parameters ..., as detailed below) and then applying a boundary condition specified by boundary. This method therefore performs the steps of a simple dispersal algorithm in a single vectorized call. See deviatePositions() for an even more efficient approach.
The parameter point may contain a single point which is deviated and bounded n independent times, or may contain n points each of which is deviated and bounded. In any case, each point in point should match the dimensionality of the model – one element in a 1D model, two elements in a 2D model, or three elements in a 3D model. This method should not be called in a non-spatial model.
The dispersal kernel is specified similarly to other kernel-based methods, such as setInteractionFunction() and smooth(). For pointDeviated(), functionType may be "f" with no ellipsis arguments ... to use a flat kernel out to maxDistance; "l" with no ellipsis arguments for a kernel that decreases linearly from the center to zero at maxDistance; "e", in which case the ellipsis should supply a numeric$ lambda (rate) parameter for a negative exponential function; "n", in which case the ellipsis should supply a numeric$ sigma (standard deviation) parameter for a Gaussian function; or "t", in which case the ellipsis should supply a numeric$ degrees of freedom and a numeric$ scale parameter for a t-distribution function. The Cauchy ("c") kernel is not supported by pointDeviated() since it is not well-behaved for this purpose, and the Student’s t ("t") kernel is not allowed in 3D models at present simply because it hasn’t been implemented. See the InteractionType class documentation for more detailed discussion of the available kernel types and their parameters and probability distribution functions.
The random points returned from this method are drawn from the probability distribution that is radially symmetric and has density proportional to the kernel – in other words, at distance r the density is proportional to the kernel type referred to by functionType. (Said another way, the shape of the cross-section through the probability density function is given by the kernel.) For instance, the value of the type "e" (exponential) kernel with rate a at r is proportional to exp(−ar), and so in 2D, the probability density that this method with kernel type "e" draws from has density proportional to p(x, y) = exp(−a sqrt(x2 + y2)), since r = sqrt(x2 + y2) is the distance. Note that the distribution of the distance is not given by the kernel except in 1D: in the type "e" example, the distribution of the distance in 1D is exponential, while in 2D it has density proportional to r exp(−ar) (i.e., Gamma with shape parameter 1). For another example, the value of the type "n" (Normal) kernel at r with standard deviation 1 is proportional to exp(−r2 / 2), and so the density is proportional to p(x, y) = exp(−(x2 + y2) / 2). This is the standard bivariate Normal, and equivalent to drawing independent Normals for the x and y directions; however, the Normal is the only distribution for which independent draws along each axis will result in a radially symmetric distribution. The distribution of the distance in 2D with type "n" is proportional to r exp(−r2 / 2), i.e., Rayleigh.
The boundary condition must be one of "none", "periodic", "reflecting", "stopping", or "reprising". For "none", no boundary condition is enforced; the deviated points are simply returned as is. For "periodic", "reflecting", and "stopping", the boundary condition is enforced just as it is by the pointPeriodic(), pointReflected(), and pointStopped() methods; see their documentation for further details. For "reprising", if the deviated point is out of bounds a new deviated point will be chosen, based upon the same original point, until a point inside bounds is obtained. Note that absorbing boundaries (for which being out-of-bounds is lethal) would be implemented in script; this method cannot enforce them.
Note that for the typical usage case, in which point comes from the spatialPosition property for a vector of individuals, and the result is then set back onto the same vector of individuals using the setSpatialPosition() method, the deviatePositions() method provides an even more efficient alternative.
– (logical)pointInBounds(float point)
Returns T if point is inside the spatial boundaries of the subpopulation, F otherwise. For example, for a simulation with "xy" dimensionality, if point contains exactly two values constituting an (x,y) point, the result will be T if and only if ((point[0]>=x0) & (point[0]<=x1) & (point[1]>=y0) & (point[1]<=y1)) given spatial bounds (x0, y0, x1, y1). This method is useful for implementing absorbing or reprising boundary conditions. This may only be called in simulations for which continuous space has been enabled with initializeSLiMOptions().
The length of point must be an exact multiple of the dimensionality of the simulation; in other words, point may contain values comprising more than one point. In this case, a logical vector will be returned in which each element is T if the corresponding point in point is inside the spatial boundaries of the subpopulation, F otherwise.
– (float)pointPeriodic(float point)
Returns a revised version of point that has been brought inside the periodic spatial boundaries of the subpopulation (as specified by the periodicity parameter of initializeSLiMOptions()) by wrapping around periodic spatial boundaries. In brief, if a coordinate of point lies beyond a periodic spatial boundary, that coordinate is wrapped around the boundary, so that it lies inside the spatial extent by the same magnitude that it previously lay outside, but on the opposite side of the space; in effect, the two edges of the periodic spatial boundary are seamlessly joined. This is done iteratively until all coordinates lie inside the subpopulation’s periodic boundaries. Note that non-periodic spatial boundaries are not enforced by this method; they should be enforced using pointReflected(), pointStopped(), or some other means of enforcing boundary constraints (which can be used after pointPeriodic() to bring the remaining coordinates into bounds; coordinates already brought into bounds by pointPeriodic() will be unaffected by those calls). This method is useful for implementing periodic boundary conditions. This may only be called in simulations for which continuous space and at least one periodic spatial dimension have been enabled with initializeSLiMOptions().
The length of point must be an exact multiple of the dimensionality of the simulation; in other words, point may contain values comprising more than one point. In this case, each point will be processed as described above and a new vector containing all of the processed points will be returned.
– (float)pointReflected(float point)
Returns a revised version of point that has been brought inside the spatial boundaries of the subpopulation by reflection. In brief, if a coordinate of point lies beyond a spatial boundary, that coordinate is reflected across the boundary, so that it lies inside the boundary by the same magnitude that it previously lay outside the boundary. This is done iteratively until all coordinates lie inside the subpopulation’s boundaries. This method is useful for implementing reflecting boundary conditions. This may only be called in simulations for which continuous space has been enabled with initializeSLiMOptions().
The length of point must be an exact multiple of the dimensionality of the simulation; in other words, point may contain values comprising more than one point. In this case, each point will be processed as described above and a new vector containing all of the processed points will be returned.
– (float)pointStopped(float point)
Returns a revised version of point that has been brought inside the spatial boundaries of the subpopulation by clamping. In brief, if a coordinate of point lies beyond a spatial boundary, that coordinate is set to exactly the position of the boundary, so that it lies on the edge of the spatial boundary. This method is useful for implementing stopping boundary conditions. This may only be called in simulations for which continuous space has been enabled with initializeSLiMOptions().
The length of point must be an exact multiple of the dimensionality of the simulation; in other words, point may contain values comprising more than one point. In this case, each point will be processed as described above and a new vector containing all of the processed points will be returned.
– (float)pointUniform([integer$ n = 1])
Returns a new point (or points, for n > 1) generated from uniform draws for each coordinate, within the spatial boundaries of the subpopulation. The returned vector will contain n points, each comprised of a number of coordinates equal to the dimensionality of the simulation, so it will be of total length n*dimensionality. This may only be called in simulations for which continuous space has been enabled with initializeSLiMOptions().
– (void)removeSpatialMap(so<SpatialMap>$ map)
Removes the SpatialMap object specified by map from the subpopulation. The parameter map may be either a SpatialMap object, or a string name for spatial map. The map must have been added to the subpopulation with addSpatialMap(); if it has not been, an error results. Removing spatial maps that are no longer in use is optional in most cases. It is generally a good idea because it might decrease SLiM’s memory footprint; also, it avoids an error if the subpopulation’s spatial bounds are changed (see setSpatialBounds()).
– (void)removeSubpopulation(void)
Removes this subpopulation from the model. The subpopulation is immediately removed from the list of active subpopulations, and the symbol representing the subpopulation is undefined. The subpopulation object itself remains unchanged until children are next generated (at which point it is deallocated), but it is no longer part of the simulation and should not be used.
Note that this method is only for use in nonWF models, in which there is a distinction between a subpopulation being empty and a subpopulation being removed from the simulation; an empty subpopulation may be re-colonized by migrants, whereas as a removed subpopulation no longer exists at all. WF models do not make this distinction; when a subpopulation is empty it is automatically removed. WF models should therefore call setSubpopulationSize(0) instead of this method; setSubpopulationSize() is the standard way for WF models to change the subpopulation size, including to a size of 0.
– (object<Individual>)sampleIndividuals(integer$ size, [logical$ replace = F], [No<Individual>$ exclude = NULL], [Ns$ sex = NULL], [Ni$ tag = NULL], [Ni$ minAge = NULL], [Ni$ maxAge = NULL], [Nl$ migrant = NULL], [Nl$ tagL0 = NULL], [Nl$ tagL1 = NULL], [Nl$ tagL2 = NULL], [Nl$ tagL3 = NULL], [Nl$ tagL4 = NULL])
Returns a vector of individuals, of size less than or equal to parameter size, sampled from the individuals in the target subpopulation. Sampling is done without replacement if replace is F (the default), or with replacement if replace is T. The remaining parameters specify constraints upon the pool of individuals that will be considered candidates for the sampling. Parameter exclude, if non-NULL, may specify a specific individual that should not be considered a candidate (typically the focal individual in some operation). Parameter sex, if non-NULL, may specify a sex ("M" or "F") for the individuals to be drawn, in sexual models. Parameter tag, if non-NULL, may specify a tag property value for the individuals to be drawn. Parameters minAge and maxAge, if non-NULL, may specify a minimum or maximum age for the individuals to be drawn, in nonWF models. Parameter migrant, if non-NULL, may specify a required value for the migrant property of the individuals to be drawn (so T will require that individuals be migrants, F will require that they not be). Finally, parameters tagL0, tagL1, tagL2, tagL3, and tagL4, if non-NULL, may specify a required value (T or F) for the corresponding properties (tagL0, tagL1, tagL2, tagL3, and tagL4) of the individuals to be drawn. Note that if any tag/tagL parameter is specified as non-NULL, that tag/tagL property must have a defined value for every individual in the subpopulation, otherwise an error may result (although this requirement will not necessarily be checked comprehensively by this method in every invocation). If the candidate pool is smaller than the requested sample size, all eligible candidates will be returned (in randomized order); the result will be a zero-length vector if no eligible candidates exist (unlike sample()).
This method is similar to getting the individuals property of the subpopulation, using operator [] to select only individuals with the desired properties, and then using sample() to sample from that candidate pool. However, besides being much simpler than the equivalent Eidos code, it is also much faster, and it does not fail if less than the full sample size is available. See subsetIndividuals() for a similar method that returns a full subset, rather than a sample.
– (void)setCloningRate(numeric rate)
Set the cloning rate of this subpopulation. The rate is changed to rate, which should be between 0.0 and 1.0, inclusive (see the SLiM manual for further details). Clonal reproduction can be enabled in both non-sexual (i.e. hermaphroditic) and sexual simulations. In non-sexual simulations, rate must be a singleton value representing the overall clonal reproduction rate for the subpopulation. In sexual simulations, rate may be either a singleton (specifying the clonal reproduction rate for both sexes) or a vector containing two numeric values (the female and male cloning rates specified separately, at indices 0 and 1 respectively). During mating and offspring generation, the probability that any given offspring individual will be generated by cloning – by asexual reproduction without gametes or meiosis – will be equal to the cloning rate (for its sex, in sexual simulations) set in the parental (not the offspring!) subpopulation.
– (void)setMigrationRates(io<Subpopulation> sourceSubpops, numeric rates)
Set the migration rates to this subpopulation from the subpopulations in sourceSubpops to the corresponding rates specified in rates; in other words, rates gives the expected fractions of the children in this subpopulation that will subsequently be generated from parents in the subpopulations sourceSubpops (see the SLiM manual for further details). This method will only set the migration fractions from the subpopulations given; migration rates from other subpopulations will be left unchanged (explicitly set a zero rate to turn off migration from a given subpopulation). The type of sourceSubpops may be either integer, specifying subpopulations by identifier, or object, specifying subpopulations directly.
– (void)setSelfingRate(numeric$ rate)
Set the selfing rate of this subpopulation. The rate is changed to rate, which should be between 0.0 and 1.0, inclusive (see the SLiM manual for further details). Selfing can only be enabled in non-sexual (i.e. hermaphroditic) simulations. During mating and offspring generation, the probability that any given offspring individual will be generated by selfing – by self-fertilization via gametes produced by meiosis by a single parent – will be equal to the selfing rate set in the parental (not the offspring!) subpopulation.
– (void)setSexRatio(float$ sexRatio)
Set the sex ratio of this subpopulation to sexRatio. As defined in SLiM, this is actually the fraction of the subpopulation that is male; in other words, the M:(M+F) ratio. This will take effect when children are next generated; it does not change the current subpopulation state. Unlike the selfing rate, the cloning rate, and migration rates, the sex ratio is deterministic: SLiM will generate offspring that exactly satisfy the requested sex ratio (within integer roundoff limits).
– (void)setSpatialBounds(numeric bounds)
Set the spatial boundaries of the subpopulation to bounds. This method may be called only for simulations in which continuous space has been enabled with initializeSLiMOptions(). The length of bounds must be double the spatial dimensionality, so that it supplies both minimum and maximum values for each coordinate. More specifically, for a dimensionality of "x", bounds should supply (x0, x1) values; for dimensionality "xy" it should supply (x0, y0, x1, y1) values; and for dimensionality "xyz" it should supply (x0, y0, z0, x1, y1, z1) (in that order). These boundaries will be used by SLiMgui to calibrate the display of the subpopulation, and will be used by methods such as pointInBounds(), pointReflected(), pointStopped(), and pointUniform(). The default spatial boundaries for all subpopulations span the interval [0,1] in each dimension. Spatial dimensions that are periodic (as established with the periodicity parameter to initializeSLiMOptions()) must have a minimum coordinate value of 0.0 (a restriction that allows the handling of periodicity to be somewhat more efficient). The current spatial bounds for the subpopulation may be obtained through the spatialBounds property.
The spatial bounds of a subpopulation are shared with any SpatialMap objects added to the subpopulation. For this reason, once a spatial map has been added to a subpopulation, the spatial bounds of the subpopulation can no longer be changed (because it would stretch or shrink the associated spatial map, which does not seem to make physical sense). The bounds for a subpopulation should therefore be configured before any spatial maps are added to it. If those bounds do need to change subsequently, any associated spatial maps must first be removed with removeSpatialMap(), to ensure model consistency.
– (void)setSubpopulationSize(integer$ size)
Set the size of this subpopulation to size individuals (see the SLiM manual for further details). This will take effect when children are next generated; it does not change the current subpopulation state. Setting a subpopulation to a size of 0 does have some immediate effects that serve to disconnect it from the simulation: the subpopulation is removed from the list of active subpopulations, the subpopulation is removed as a source of migration for all other subpopulations, and the symbol representing the subpopulation is undefined. In this case, the subpopulation itself remains unchanged until children are next generated (at which point it is deallocated), but it is no longer part of the simulation and should not be used.
– (string)spatialMapColor(string$ name, numeric value)
This method has been deprecated, and may be removed in a future release of SLiM. In SLiM 4.1 and later, use the SpatialMap method mapColor() instead, and see that method’s documentation. (This method differs only in taking a name parameter, which is used to look up the spatial map from those that have been added to the subpopulation.)
– (object<Image>$)spatialMapImage(string$ name, [Ni$ width = NULL], [Ni$ height = NULL], [logical$ centers = F], [logical$ color = T])
This method has been deprecated, and may be removed in a future release of SLiM. In SLiM 4.1 and later, use the SpatialMap method mapImage() instead, and see that method’s documentation. (This method differs only in taking a name parameter, which is used to look up the spatial map from those that have been added to the subpopulation.)
– (float)spatialMapValue(so<SpatialMap>$ map, float point)
Looks up the spatial map specified by map, and uses its mapping machinery (as defined by the gridSize, values, and interpolate parameters to defineSpatialMap()) to translate the coordinates of point into a corresponding map value. The parameter map may specify the map either as a SpatialMap object, or by its string name; in either case, the map must have been added to the subpopulation. The length of point must be equal to the spatiality of the spatial map; in other words, for a spatial map with spatiality "xz", point must be of length 2, specifying the x and z coordinates of the point to be evaluated. Interpolation will automatically be used if it was enabled for the spatial map. Point coordinates are clamped into the range defined by the spatial boundaries, even if the spatial boundaries are periodic; use pointPeriodic() to wrap the point coordinates first if desired. See the documentation for defineSpatialMap() for information regarding the details of value mapping.
Beginning in SLiM 3.3, point may contain more than one point to be looked up. In this case, the length of point must be an exact multiple of the spatiality of the spatial map; for a spatial map with spatiality "xz", for example, the length of point must be an exact multiple of 2, and successive pairs of elements from point (elements 0 and 1, then elements 2 and 3, etc.) will be taken as the x and z coordinates of the points to be evaluated. This allows spatialMapValue() to be used in a vectorized fashion.
The mapValue() method of SpatialMap provides the same functionality directly on the SpatialMap class; spatialMapValue() is provided on Subpopulation partly for backward compatibility, but also for convenience in some usage cases.
– (object<Individual>)subsetIndividuals([No<Individual>$ exclude = NULL], [Ns$ sex = NULL], [Ni$ tag = NULL], [Ni$ minAge = NULL], [Ni$ maxAge = NULL], [Nl$ migrant = NULL], [Nl$ tagL0 = NULL], [Nl$ tagL1 = NULL], [Nl$ tagL2 = NULL], [Nl$ tagL3 = NULL], [Nl$ tagL4 = NULL])
Returns a vector of individuals subset from the individuals in the target subpopulation. The parameters specify constraints upon the subset of individuals that will be returned. Parameter exclude, if non-NULL, may specify a specific individual that should not be included (typically the focal individual in some operation). Parameter sex, if non-NULL, may specify a sex ("M" or "F") for the individuals to be returned, in sexual models. Parameter tag, if non-NULL, may specify a tag property value for the individuals to be returned. Parameters minAge and maxAge, if non-NULL, may specify a minimum or maximum age for the individuals to be returned, in nonWF models. Parameter migrant, if non-NULL, may specify a required value for the migrant property of the individuals to be returned (so T will require that individuals be migrants, F will require that they not be). Finally, parameters tagL0, tagL1, tagL2, tagL3, and tagL4, if non-NULL, may specify a required value (T or F) for the corresponding properties (tagL0, tagL1, tagL2, tagL3, and tagL4) of the individuals to be returned. Note that if any tag/tagL parameter is specified as non-NULL, that tag/tagL property must have a defined value for every individual in the subpopulation, otherwise an error may result (although this requirement will not necessarily be checked comprehensively by this method in every invocation).
This method is shorthand for getting the individuals property of the subpopulation, and then using operator [] to select only individuals with the desired properties; besides being much simpler than the equivalent Eidos code, it is also much faster. See sampleIndividuals() for a similar method that returns a sample taken from a chosen subset of individuals.
– (void)takeMigrants(object<Individual> migrants)
Immediately moves the individuals in migrants to the target subpopulation (removing them from their previous subpopulation). Individuals in migrants that are already in the target subpopulation are unaffected. Note that the indices and order of individuals and genomes in both the target and source subpopulations will change unpredictably as a side effect of this method.
Note that this method is only for use in nonWF models, in which migration is managed manually by the model script. In WF models, migration is managed automatically by the SLiM core based upon the migration rates set for each subpopulation with setMigrationRates().
5.18 Class Substitution
5.18.1 Substitution properties
id => (integer$)
The identifier for this mutation. Each mutation created during a run receives an immutable identifier that will be unique across the duration of the run, and that identifier is carried over to the Substitution object when the mutation fixes.
fixationTick => (integer$)
The tick in which this mutation fixed.
mutationType => (object<MutationType>$)
The MutationType from which this mutation was drawn.
nucleotide <–> (string$)
A string representing the nucleotide associated with this mutation; this will be "A", "C", "G", or "T". If the mutation is not nucleotide-based, this property is unavailable.
nucleotideValue <–> (integer$)
An integer representing the nucleotide associated with this mutation; this will be 0 (A), 1 (C), 2 (G), or 3 (T). If the mutation is not nucleotide-based, this property is unavailable.
originTick => (integer$)
The tick in which this mutation arose.
position => (integer$)
The position in the chromosome of this mutation.
selectionCoeff => (float$)
The selection coefficient of the mutation, drawn from the distribution of fitness effects of its MutationType.
subpopID <–> (integer$)
The identifier of the subpopulation in which this mutation arose. This value is carried over from the Mutation object directly; if a “tag” value was used in the Mutation object, that value will carry over to the corresponding Substitution object. The subpopID in Substitution is a read-write property to allow it to be used as a “tag” in the same way, if the origin subpopulation identifier is not needed.
tag <–> (integer$)
A user-defined integer value. The value of tag is carried over automatically from the original Mutation object. Apart from that, the value of tag is not used by SLiM; it is free for you to use.
5.18.2 Substitution methods