├── tests ├── extra_recipes │ ├── .gitignore │ ├── check_trees.py │ ├── Recipe 17.8 - Starting a hermaphroditic WF model with a coalescent history III.py │ ├── Recipe 17.8 - Starting a hermaphroditic WF model with a coalescent history I.py │ ├── Recipe 18.13 - Tree-sequence recording and nucleotide-based models I.txt │ ├── Recipe 17.2 - Overlaying neutral mutations.py │ ├── Recipe 17.7 - Analyzing selection coefficients in Python with tskit II.py │ ├── Recipe 17.1 - A minimal tree-seq model.txt │ ├── Recipe 17.7 - Analyzing selection coefficients in Python with tskit I.txt │ ├── Recipe 17.10 - Adding a neutral burn-in after simulation with recapitation I.txt │ ├── Recipe 17.4 - Detecting the dip in diversity (analyzing tree heights in Python) I.txt │ ├── Recipe 18.13 - Tree-sequence recording and nucleotide-based models II.py │ ├── Recipe 17.8 - Starting a hermaphroditic WF model with a coalescent history II.txt │ ├── Recipe 17.3 - Simulation conditional upon fixation of a sweep, preserving ancestry I.txt │ ├── Recipe 17.5 - Mapping admixture (analyzing ancestry in Python) II.py │ ├── Recipe 17.3 - Simulation conditional upon fixation of a sweep, preserving ancestry II.txt │ ├── Recipe 17.9 - Starting a sexual nonWF model with a coalescent history II.txt │ ├── Recipe 17.5 - Mapping admixture (analyzing ancestry in Python) I.txt │ ├── Recipe 18.13 - Tree-sequence recording and nucleotide-based models III.py │ ├── Recipe 17.10 - Adding a neutral burn-in after simulation with recapitation II.py │ ├── Recipe 17.4 - Detecting the dip in diversity (analyzing tree heights in Python) II.py │ └── Recipe 17.9 - Starting a sexual nonWF model with a coalescent history I.py ├── test_recipes │ ├── recipe_WF.v3.0.trees │ ├── recipe_WF.v3.2.trees │ ├── recipe_WF.v3.4.trees │ ├── recipe_WF.v3.5.trees │ ├── recipe_WF.v3.6.trees │ ├── recipe_WF.v3.7.trees │ ├── recipe_WF.v3.3.1.trees │ ├── recipe_WF.v4.2.2.trees │ ├── recipe_WF_X.v4.2.2.trees │ ├── recipe_WF_Y.v4.2.2.trees │ ├── recipe_nonWF.v3.0.trees │ ├── recipe_nonWF.v3.2.trees │ ├── recipe_nonWF.v3.4.trees │ ├── recipe_nonWF.v3.5.trees │ ├── recipe_nonWF.v3.6.trees │ ├── recipe_nonWF.v3.7.trees │ ├── recipe_nonWF.v3.3.1.trees │ ├── recipe_nonWF.v4.2.2.trees │ ├── recipe_WF.v3.5_and_v3.6.trees │ ├── recipe_long_WF.slim │ ├── recipe_init_mutated_WF.slim │ ├── recipe_long_nucleotides.slim │ ├── recipe_old_nonWF.slim │ ├── recipe_long_nonWF.slim │ ├── recipe_resettable_WF.slim │ ├── recipe_nonWF_nonstacked.slim │ ├── recipe_starts_later.slim │ ├── recipe_with_metadata.slim │ ├── recipe_init_mutated_nonWF.slim │ ├── make_v3_test_additions.py │ ├── restart_and_run_nonWF.slim │ ├── restart_and_run_WF.slim │ ├── recipe_resettable_nonWF.slim │ ├── restart_nucleotides_nonWF.slim │ ├── reset_nonWF.slim │ ├── restart_WF.slim │ ├── reset_WF.slim │ ├── restart_nonWF.slim │ ├── restart_nucleotides_WF.slim │ ├── restart_and_remove_subpop_nonWF.slim │ ├── restart_msprime.slim │ ├── restart_nucleotides_WF_chromosomes.slim │ ├── restart_multispecies_WF.slim │ ├── restart_multispecies_nonWF.slim │ ├── recipe_mutation_spectrum.slim │ ├── recipe_WF.slim │ ├── recipe_WF_early_late.slim │ ├── recipe_WF_first_late.slim │ ├── recipe_WF_late_early.slim │ ├── recipe_WF_late_first.slim │ ├── recipe_WF_late_late.slim │ ├── recipe_WF_early_early.slim │ ├── recipe_WF_early_first.slim │ ├── recipe_WF_first_early.slim │ ├── recipe_WF_first_first.slim │ ├── recipe_roots.slim │ ├── recipe_nucleotides_WF.slim │ ├── recipe_WF_migration.slim │ ├── recipe_nonWF.slim │ ├── recipe_nonWF_early_early.slim │ ├── recipe_nonWF_early_first.slim │ ├── recipe_nonWF_early_late.slim │ ├── recipe_nonWF_first_early.slim │ ├── recipe_nonWF_first_first.slim │ ├── recipe_nonWF_first_late.slim │ ├── recipe_nonWF_late_early.slim │ ├── recipe_nonWF_late_first.slim │ ├── recipe_nonWF_late_late.slim │ ├── recipe_record_everyone_WF_early.slim │ ├── recipe_record_everyone_WF_first.slim │ ├── recipe_record_everyone_WF_late.slim │ ├── recipe_nonWF_H.slim │ ├── recipe_nucleotides_plus_others.slim │ ├── recipe_nucleotides_nonWF.slim │ ├── recipe_nonWF_X.slim │ ├── recipe_nonWF_Y.slim │ ├── recipe_retain_everyone_WF_late.slim │ ├── recipe_nonWF_selfing.slim │ ├── recipe_record_everyone_nonWF_late.slim │ ├── recipe_record_everyone_nonWF_early.slim │ ├── recipe_record_everyone_nonWF_first.slim │ ├── recipe_retain_everyone_nonWF_late.slim │ ├── recipe_remember_and_retain.slim │ ├── recipe_H-_chromosome.slim │ ├── recipe_WF_H.slim │ ├── recipe_WF_HF.slim │ ├── recipe_WF_HM.slim │ ├── recipe_WF_W.slim │ ├── recipe_WF_X.slim │ ├── recipe_WF_Z.slim │ └── recipe_WF_Y.slim ├── benchmark │ ├── metadata.slim │ ├── metadata.sh │ └── annotation.sh └── README.md ├── docs ├── favicon.ico ├── _static │ ├── pedigrees.ink.svg.md5 │ ├── phylo.pdf │ ├── phylo.png │ ├── pedigree0.png │ ├── pedigree01.png │ ├── pedigree1.png │ ├── pedigree2.png │ ├── pedigree_hap.png │ ├── annotate_genome.png │ ├── annotated_p_vs_s.png │ ├── pedigree_mutate.png │ ├── pedigree_remember.png │ ├── pedigree_simplify.png │ ├── pedigree_recapitate.png │ ├── recomb_rates.tsv │ ├── phylo.tsv │ └── export-layers-svg.sh ├── annotate_genome.pdf ├── annotated_p_vs_s.pdf ├── .gitignore ├── rapid_adaptation.slim ├── selection.slim ├── _toc.yml ├── build.sh ├── example_sim.slim ├── Makefile ├── reload_annotated.slim ├── neutral_restart.slim ├── migrants.slim ├── generation_time.slim ├── neutral_nucleotide_restart.slim ├── installation.md ├── util.py ├── introduction.md ├── phylo_bgs.slim ├── _config.yml ├── vignette_space.slim └── development.md ├── .codecov.yml ├── .gitignore ├── pyslim ├── _version.py ├── util.py └── provenance.py ├── LICENSE ├── README.md ├── .github └── workflows │ └── docs.yml └── pyproject.toml /tests/extra_recipes/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.png 3 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/docs/favicon.ico -------------------------------------------------------------------------------- /docs/_static/pedigrees.ink.svg.md5: -------------------------------------------------------------------------------- 1 | 88eeb297d3a4a3836bb14594e7d3231a pedigrees.ink.svg 2 | -------------------------------------------------------------------------------- /docs/_static/phylo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/docs/_static/phylo.pdf -------------------------------------------------------------------------------- /docs/_static/phylo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/docs/_static/phylo.png -------------------------------------------------------------------------------- /docs/annotate_genome.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/docs/annotate_genome.pdf -------------------------------------------------------------------------------- /docs/annotated_p_vs_s.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/docs/annotated_p_vs_s.pdf -------------------------------------------------------------------------------- /docs/_static/pedigree0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/docs/_static/pedigree0.png -------------------------------------------------------------------------------- /docs/_static/pedigree01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/docs/_static/pedigree01.png -------------------------------------------------------------------------------- /docs/_static/pedigree1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/docs/_static/pedigree1.png -------------------------------------------------------------------------------- /docs/_static/pedigree2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/docs/_static/pedigree2.png -------------------------------------------------------------------------------- /docs/_static/pedigree_hap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/docs/_static/pedigree_hap.png -------------------------------------------------------------------------------- /docs/_static/annotate_genome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/docs/_static/annotate_genome.png -------------------------------------------------------------------------------- /docs/_static/annotated_p_vs_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/docs/_static/annotated_p_vs_s.png -------------------------------------------------------------------------------- /docs/_static/pedigree_mutate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/docs/_static/pedigree_mutate.png -------------------------------------------------------------------------------- /docs/_static/pedigree_remember.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/docs/_static/pedigree_remember.png -------------------------------------------------------------------------------- /docs/_static/pedigree_simplify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/docs/_static/pedigree_simplify.png -------------------------------------------------------------------------------- /docs/_static/pedigree_recapitate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/docs/_static/pedigree_recapitate.png -------------------------------------------------------------------------------- /docs/_static/recomb_rates.tsv: -------------------------------------------------------------------------------- 1 | end_position rate(cM/Mb) 2 | 15000000 3.2 3 | 50000000 2.5 4 | 85000000 0.25 5 | 99999999 2.8 6 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF.v3.0.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_WF.v3.0.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF.v3.2.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_WF.v3.2.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF.v3.4.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_WF.v3.4.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF.v3.5.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_WF.v3.5.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF.v3.6.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_WF.v3.6.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF.v3.7.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_WF.v3.7.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF.v3.3.1.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_WF.v3.3.1.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF.v4.2.2.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_WF.v4.2.2.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_X.v4.2.2.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_WF_X.v4.2.2.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_Y.v4.2.2.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_WF_Y.v4.2.2.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF.v3.0.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_nonWF.v3.0.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF.v3.2.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_nonWF.v3.2.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF.v3.4.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_nonWF.v3.4.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF.v3.5.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_nonWF.v3.5.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF.v3.6.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_nonWF.v3.6.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF.v3.7.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_nonWF.v3.7.trees -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | spatial_sim_individuals.txt 3 | spatial_sim_genotypes.vcf 4 | example_snps.vcf 5 | sims.make 6 | example_sim.vcf 7 | -------------------------------------------------------------------------------- /docs/_static/phylo.tsv: -------------------------------------------------------------------------------- 1 | child parent popsize edgelen 2 | root 500 2000 3 | C root 50 250 4 | I root 100 200 5 | B I 70 50 6 | A I 40 50 7 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF.v3.3.1.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_nonWF.v3.3.1.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF.v4.2.2.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_nonWF.v4.2.2.trees -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF.v3.5_and_v3.6.trees: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tskit-dev/pyslim/HEAD/tests/test_recipes/recipe_WF.v3.5_and_v3.6.trees -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: 4 | python-tests: 5 | target: 95% 6 | flags: 7 | - python_tests 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | __pycache__ 3 | *.trees 4 | pyslim.egg-info/ 5 | build/ 6 | dist/ 7 | *.pyc 8 | .DS_Store 9 | .coverage 10 | htmlcov 11 | out.pedigree 12 | -------------------------------------------------------------------------------- /pyslim/_version.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | pyslim_version = '1.1.0' 3 | slim_file_version = '0.9' 4 | # other file versions that require no modification 5 | compatible_slim_file_versions = ['0.9'] 6 | -------------------------------------------------------------------------------- /tests/extra_recipes/check_trees.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import tskit 5 | 6 | treefile = sys.argv[1] 7 | 8 | ts = tskit.load(treefile) 9 | print(f"The file '{treefile}' has {ts.num_trees} trees relating {ts.num_individuals} individuals " 10 | f"with {ts.num_mutations} mutations at {ts.num_sites} sites.") 11 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.8 - Starting a hermaphroditic WF model with a coalescent history III.py: -------------------------------------------------------------------------------- 1 | # Keywords: Python, tree-sequence recording, tree sequence recording 2 | 3 | import tskit 4 | 5 | ts = tskit.load("recipe_17.8_II.trees").simplify() 6 | 7 | for tree in ts.trees(): 8 | for root in tree.roots: 9 | print(tree.time(root)) 10 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.8 - Starting a hermaphroditic WF model with a coalescent history I.py: -------------------------------------------------------------------------------- 1 | # Keywords: Python, tree-sequence recording, tree sequence recording 2 | 3 | import msprime, pyslim 4 | 5 | ts = msprime.sim_ancestry(samples=5000, population_size=5000, sequence_length=1e8, 6 | recombination_rate=1e-8) 7 | slim_ts = pyslim.annotate(ts, model_type="WF", tick=1) 8 | slim_ts.dump("recipe_17.8.trees") 9 | -------------------------------------------------------------------------------- /docs/rapid_adaptation.slim: -------------------------------------------------------------------------------- 1 | initialize() { 2 | initializeTreeSeq(); 3 | initializeMutationRate(1e-8); 4 | initializeMutationType("m1", 0.5, "e", 0.1); 5 | initializeGenomicElementType("g1", m1, 1.0); 6 | initializeGenomicElement(g1, 0, 99999999); 7 | initializeRecombinationRate(1e-8); 8 | } 9 | 10 | 1 early() { 11 | sim.addSubpop("p1", 10000); 12 | } 13 | 14 | 20 late() { 15 | sim.treeSeqOutput("rapid_adaptation.trees"); 16 | } 17 | -------------------------------------------------------------------------------- /docs/selection.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | initializeSLiMModelType("WF"); 4 | initializeTreeSeq(); 5 | initializeMutationRate(1e-6); 6 | initializeMutationType("m1", 0.5, "e", -0.1); 7 | initializeMutationType("m2", 0.5, "e", 0.5); 8 | initializeGenomicElementType("g1", c(m1, m2), c(0.9, 0.1)); 9 | initializeGenomicElement(g1, 0, 1e6-1); 10 | initializeRecombinationRate(1e-8); 11 | } 12 | 13 | 1 early() { 14 | sim.addSubpop("p1", 1000); 15 | } 16 | 17 | 1000 early() { 18 | sim.treeSeqOutput("selection.trees"); 19 | } 20 | -------------------------------------------------------------------------------- /docs/_toc.yml: -------------------------------------------------------------------------------- 1 | format: jb-book 2 | root: introduction 3 | parts: 4 | - caption: Getting started 5 | chapters: 6 | - file: overview 7 | - file: installation 8 | - caption: Using pyslim 9 | chapters: 10 | - file: tutorial 11 | - file: vignette_space 12 | - file: vignette_continuing 13 | - file: vignette_coalescent_diversity 14 | - file: vignette_parallel_phylo 15 | - file: time_units 16 | - file: metadata 17 | - file: previous_versions 18 | - caption: pyslim reference 19 | chapters: 20 | - file: python_api 21 | - caption: Miscellaneous 22 | chapters: 23 | - file: development 24 | -------------------------------------------------------------------------------- /docs/build.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | 3 | # Jupyter-build doesn't have an option to automatically show the 4 | # saved reports, which makes it difficult to debug the reasons for 5 | # build failures in CI. This is a simple wrapper to handle that. 6 | 7 | REPORTDIR=_build/html/reports 8 | 9 | # TODO add -n for nitpick mode. 10 | jupyter-book build -W --keep-going . 11 | RETVAL=$? 12 | if [ $RETVAL -ne 0 ]; then 13 | if [ -e $REPORTDIR ]; then 14 | echo "Error occured; showing saved reports" 15 | cat $REPORTDIR/* 16 | fi 17 | else 18 | # Clear out any old reports 19 | rm -f $REPORTDIR/* 20 | fi 21 | exit $RETVAL 22 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_long_WF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | initializeTreeSeq(timeUnit="generations"); 6 | initializeMutationRate(1e-2); 7 | initializeMutationType("m1", 0.5, "f", -0.1); 8 | initializeGenomicElementType("g1", m1, 1.0); 9 | initializeGenomicElement(g1, 0, 99); 10 | initializeRecombinationRate(1e-2); 11 | } 12 | 13 | 1 early() { 14 | sim.addSubpop("p1", 10); 15 | } 16 | 17 | 500 late() { 18 | sim.treeSeqOutput(TREES_FILE); 19 | catn("Done."); 20 | sim.simulationFinished(); 21 | } 22 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 18.13 - Tree-sequence recording and nucleotide-based models I.txt: -------------------------------------------------------------------------------- 1 | // Keywords: nucleotide-based, nucleotide sequence, sequence-based mutation rate 2 | 3 | initialize() { 4 | defineConstant("L", 1e5); 5 | initializeSLiMOptions(nucleotideBased=T); 6 | initializeTreeSeq(); 7 | initializeAncestralNucleotides(randomNucleotides(L)); 8 | initializeMutationTypeNuc("m1", 0.5, "f", 0.0); 9 | initializeGenomicElementType("g1", m1, 1.0, mmJukesCantor(1e-6)); 10 | initializeGenomicElement(g1, 0, L-1); 11 | initializeRecombinationRate(1e-6); 12 | } 13 | 1 early() { sim.addSubpop("p1", 1000); } 14 | 1000 late() { sim.treeSeqOutput("recipe_nucleotides.trees"); } 15 | -------------------------------------------------------------------------------- /tests/benchmark/metadata.slim: -------------------------------------------------------------------------------- 1 | // set up a simple neutral simulation 2 | initialize() { 3 | initializeMutationRate(1e-6); 4 | initializeTreeSeq(); 5 | 6 | // m1 mutation type: neutral 7 | initializeMutationType("m1", 0.5, "n", 0.0, 0.00001); 8 | 9 | // g1 genomic element type: uses m1 for all mutations 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | 12 | // uniform chromosome of length 100 kb with uniform recombination 13 | initializeGenomicElement(g1, 0, 999999); 14 | initializeRecombinationRate(1e-8); 15 | } 16 | 17 | // create a population of 500 individuals 18 | 1 { 19 | sim.addSubpop("p1", 5000); 20 | } 21 | 22 | 23 | 2000 late() { sim.treeSeqOutput('metadata.trees'); } 24 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.2 - Overlaying neutral mutations.py: -------------------------------------------------------------------------------- 1 | # Keywords: Python, tree-sequence recording, tree sequence recording 2 | 3 | # This is a Python recipe, to be run after the section 17.1 recipe 4 | 5 | import tskit, msprime 6 | 7 | ts = tskit.load("./recipe_17.1.trees") 8 | ts = ts.simplify() 9 | 10 | ## EDIT FOR TESTING 11 | asserted = False 12 | try: 13 | for t in ts.trees(): 14 | assert t.num_roots == 1, "not coalesced! on segment {} to {}".format(t.interval[0], t.interval[1]) 15 | except AssertionError: 16 | asserted = True 17 | 18 | assert asserted 19 | 20 | mutated = msprime.sim_mutations(ts, rate=1e-7, random_seed=1, keep=True) 21 | mutated.dump("./recipe_17.1_overlaid.trees") 22 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.7 - Analyzing selection coefficients in Python with tskit II.py: -------------------------------------------------------------------------------- 1 | # Keywords: Python, tree-sequence recording, tree sequence recording 2 | 3 | import tskit 4 | 5 | ts = tskit.load("recipe_17.7.trees") 6 | 7 | # selection coefficients of all selected mutations 8 | coeffs = [] 9 | for mut in ts.mutations(): 10 | md = mut.metadata 11 | sel = [x["selection_coeff"] for x in md["mutation_list"]] 12 | if any([s != 0 for s in sel]): 13 | coeffs += sel 14 | 15 | b = [x for x in coeffs if x > 0] 16 | d = [x for x in coeffs if x < 0] 17 | 18 | print("Beneficial: " + str(len(b)) + ", mean " + str(sum(b) / len(b))) 19 | print("Deleterious: " + str(len(d)) + ", mean " + str(sum(d) / len(d))) 20 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.1 - A minimal tree-seq model.txt: -------------------------------------------------------------------------------- 1 | // Keywords: tree-sequence recording, tree sequence recording 2 | 3 | initialize() { 4 | initializeTreeSeq(); 5 | initializeMutationRate(0); 6 | initializeMutationType("m1", 0.5, "f", 0.0); 7 | initializeGenomicElementType("g1", m1, 1.0); 8 | initializeGenomicElement(g1, 0, 1e8-1); 9 | initializeRecombinationRate(1e-8); 10 | } 11 | 1 early() { 12 | sim.addSubpop("p1", 500); 13 | } 14 | 5000 late() { 15 | sim.treeSeqOutput("./recipe_17.1.trees"); 16 | } 17 | 18 | // Section 17.2's recipe, which is a Python script that overlays 19 | // neutral mutations onto the .trees file saved here, may be found in 20 | // the Recipes archive downloadable at https://messerlab.org/slim/ 21 | -------------------------------------------------------------------------------- /docs/example_sim.slim: -------------------------------------------------------------------------------- 1 | initialize() { 2 | initializeSLiMModelType("nonWF"); 3 | initializeSex("A"); 4 | initializeTreeSeq(); 5 | initializeMutationRate(0.0); 6 | initializeMutationType("m1", 0.5, "f", 0.0); 7 | initializeGenomicElementType("g1", m1, 1.0); 8 | initializeGenomicElement(g1, 0, 1e8-1); 9 | initializeRecombinationRate(1e-8); 10 | defineConstant("K", 1000); 11 | } 12 | 13 | reproduction(p1, "F") { 14 | subpop.addCrossed(individual, 15 | subpop.sampleIndividuals(1, sex="M")); 16 | } 17 | 18 | 1 early() { 19 | sim.addSubpop("p1", K); 20 | } 21 | 22 | early() { 23 | p1.fitnessScaling = K / p1.individualCount; 24 | } 25 | 26 | 1000 late() { 27 | sim.treeSeqOutput("example_sim.trees"); 28 | } 29 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.7 - Analyzing selection coefficients in Python with tskit I.txt: -------------------------------------------------------------------------------- 1 | // Keywords: tree-sequence recording, tree sequence recording 2 | 3 | initialize() { 4 | initializeTreeSeq(); 5 | initializeMutationRate(1e-10); 6 | initializeMutationType("m1", 0.5, "g", 0.1, 0.1); 7 | initializeMutationType("m2", 0.5, "g", -0.1, 0.1); 8 | initializeGenomicElementType("g1", c(m1, m2), c(1.0, 1.0)); 9 | initializeGenomicElement(g1, 0, 1e8-1); 10 | initializeRecombinationRate(1e-8); 11 | } 12 | 1 early() { 13 | sim.addSubpop("p1", 500); 14 | } 15 | 20000 late() { sim.treeSeqOutput("./recipe_17.7.trees"); } 16 | 17 | // Part II of this recipe, which is a Python script, may be found in 18 | // the Recipes archive downloadable at https://messerlab.org/slim/ 19 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_init_mutated_WF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | initializeTreeSeq(timeUnit="generations"); 6 | initializeMutationType("m1", 0.5, "f", -0.1); 7 | initializeGenomicElementType("g1", m1, 1.0); 8 | initializeGenomicElement(g1, 0, 99); 9 | initializeMutationRate(0.0); 10 | initializeRecombinationRate(0.0); 11 | } 12 | 13 | 1 early() { 14 | sim.addSubpop("p1", 10); 15 | for (k in seqLen(length(p1.haplosomes))) { 16 | genome = p1.haplosomes[k]; 17 | genome.addNewMutation(m1, 0.0, k); 18 | } 19 | } 20 | 21 | 10 late() { 22 | sim.treeSeqOutput(TREES_FILE); 23 | catn("Done."); 24 | sim.simulationFinished(); 25 | } 26 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_long_nucleotides.slim: -------------------------------------------------------------------------------- 1 | // Based on Example 18.1 2 | 3 | initialize() { 4 | setSeed(23); 5 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 6 | defineConstant("L", 1e2); 7 | initializeSLiMOptions(keepPedigrees=T, nucleotideBased=T); 8 | initializeTreeSeq(); 9 | initializeAncestralNucleotides(randomNucleotides(L)); 10 | initializeMutationTypeNuc("m1", 0.5, "f", 0.0); 11 | initializeGenomicElementType("g1", m1, 1.0, mmJukesCantor(4e-6)); 12 | initializeGenomicElement(g1, 0, L-1); 13 | initializeRecombinationRate(1e-2); 14 | } 15 | 16 | 1 early() { 17 | sim.addSubpop("p1", 10); 18 | } 19 | 20 | 100000 late() { 21 | sim.treeSeqOutput(TREES_FILE); 22 | catn("Done."); 23 | sim.simulationFinished(); 24 | } 25 | 26 | // too big for pedigree output 27 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Need to set PYTHONPATH so that we pick up the local pyslim 3 | PYPATH=${PWD}/.. 4 | PYSLIM_VERSION:=$(shell PYTHONPATH=${PYPATH} \ 5 | python3 -c 'import pyslim; print(pyslim.__version__.split("+")[0])') 6 | 7 | dev: prereqs 8 | if (cd _static && md5sum -c pedigrees.ink.svg.md5 | grep -l "FAILED"); then echo "remaking figures with inkscape"; $(MAKE) -C _static; else echo "not remaking figures"; fi 9 | PYTHONPATH=${PYPATH} ./build.sh 10 | 11 | dist: prereqs 12 | @echo Building distribution for pyslim version ${PYSLIM_VERSION} 13 | sed -i s/__PYSLIM_VERSION__/${PYSLIM_VERSION}/g _config.yml 14 | $(MAKE) -C _static 15 | PYTHONPATH=${PYPATH} ./build.sh 16 | 17 | clean: 18 | rm -fR _build 19 | rm -f *.trees 20 | 21 | example_sim.trees : example_sim.slim 22 | slim -s 23 $< 23 | 24 | prereqs: example_sim.trees 25 | -------------------------------------------------------------------------------- /docs/reload_annotated.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | // must define L 4 | initializeSLiMModelType("WF"); 5 | initializeTreeSeq(timeUnit="generations"); 6 | initializeMutationRate(c(0.03e-8, 0.003e-8, 0.03e-8), 7 | c(3000000, 6000000, 9000000) - 1); 8 | initializeMutationType("m1", 0.5, "f", 0.0); 9 | initializeMutationType("m2", 0.5, "e", 0.01); 10 | initializeGenomicElementType("g1", m2, 1.0); 11 | initializeGenomicElement(g1, 0, L-1); 12 | initializeRecombinationRate(1e-8); 13 | } 14 | 15 | 1 late() { 16 | sim.readFromPopulationFile("vignette_annotated.init.trees"); 17 | sim.treeSeqRememberIndividuals(p0.individuals); 18 | } 19 | 20 | 100 late() { 21 | catn("Done."); 22 | sim.treeSeqOutput("vignette_annotated.trees"); 23 | sim.simulationFinished(); 24 | } 25 | 26 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_old_nonWF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | initializeSLiMModelType("nonWF"); 6 | initializeTreeSeq(); 7 | initializeMutationRate(1e-4); 8 | initializeMutationType("m1", 0.5, "f", 0.0); 9 | initializeGenomicElementType("g1", m1, 1.0); 10 | initializeGenomicElement(g1, 0, 99); 11 | initializeRecombinationRate(1e-4); 12 | } 13 | 14 | reproduction() { 15 | if (community.tick % 1000 == 0) { 16 | offspring = subpop.addSelfed(individual); 17 | individual.fitnessScaling = 0.0; 18 | } 19 | } 20 | 21 | 1 early() { 22 | sim.addSubpop("p1", 2); 23 | } 24 | 25 | 300000 first() { 26 | sim.treeSeqOutput(TREES_FILE); 27 | catn("Done."); 28 | sim.simulationFinished(); 29 | } 30 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_long_nonWF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | initializeSLiMModelType("nonWF"); 6 | initializeTreeSeq(); 7 | initializeMutationRate(1e-2); 8 | initializeMutationType("m1", 0.5, "f", -0.001); 9 | initializeGenomicElementType("g1", m1, 1.0); 10 | initializeGenomicElement(g1, 0, 99); 11 | initializeRecombinationRate(1e-2); 12 | defineConstant("K", 20); 13 | } 14 | 15 | reproduction() { 16 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 17 | } 18 | 19 | 1 early() { 20 | sim.addSubpop("p1", K); 21 | } 22 | 23 | early() { 24 | p1.fitnessScaling = K / p1.individualCount; 25 | } 26 | 27 | 500 late() { 28 | sim.treeSeqOutput(TREES_FILE); 29 | catn("Done."); 30 | sim.simulationFinished(); 31 | } 32 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | Install the dependencies using 2 | 3 | ``` 4 | pip3 install -r requirements/CI/requirements.txt 5 | ``` 6 | 7 | SLiM recipes used for testing are in `test_recipes/`: the specifications for which 8 | tests to run on them are specified in `recipe_specs.py` 9 | 10 | To run the entire test suite: 11 | 12 | ``` 13 | python3 -m pytest 14 | ``` 15 | 16 | To restrict to individual tests, the syntax is: 17 | 18 | ``` 19 | python3 -m pytest tests/test_tree_sequence.py::test_slim_generation 20 | ``` 21 | 22 | 23 | To restrict to specific recipes in the `test_recipes` dir, the syntax is: 24 | 25 | ``` 26 | python3 -m pytest -k recipe_nonWF.slim 27 | ``` 28 | 29 | Note that this can be combined with restricting to specific tests, and the value 30 | following the `-k` is treated as a match, so e.g. `-k recipe_WF` will match all recipes 31 | containing the string `recipe_WF` -------------------------------------------------------------------------------- /tests/test_recipes/recipe_resettable_WF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | initializeSLiMOptions(keepPedigrees=T); 6 | initializeTreeSeq(timeUnit="generations"); 7 | initializeMutationRate(1e-2); 8 | initializeMutationType("m1", 0.5, "f", -0.1); 9 | initializeGenomicElementType("g1", m1, 1.0); 10 | initializeGenomicElement(g1, 0, 99); 11 | initializeRecombinationRate(1e-2); 12 | } 13 | 14 | 1 early() { 15 | sim.addSubpop("p1", 10); 16 | } 17 | 18 | 3 late() { 19 | sim.treeSeqRememberIndividuals(sample(p1.individuals, 7)); 20 | defineGlobal("METADATA", Dictionary()); 21 | METADATA.setValue("reset_tick", community.tick); 22 | } 23 | 24 | 10 late() { 25 | sim.treeSeqOutput(TREES_FILE, metadata=METADATA); 26 | catn("Done."); 27 | sim.simulationFinished(); 28 | } 29 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF_nonstacked.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(24); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | initializeSLiMModelType("nonWF"); 6 | initializeSLiMOptions(keepPedigrees=T); 7 | initializeTreeSeq(); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | m1.mutationStackPolicy = "l"; 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 early() { 22 | sim.addSubpop("p1", 10); 23 | } 24 | 25 | early() { 26 | p1.fitnessScaling = K / p1.individualCount; 27 | } 28 | 29 | 10 late() { 30 | sim.treeSeqOutput(TREES_FILE); 31 | catn("Done."); 32 | sim.simulationFinished(); 33 | } 34 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_starts_later.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | initializeSLiMModelType("nonWF"); 6 | initializeSLiMOptions(keepPedigrees=T); 7 | initializeTreeSeq(); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | defineConstant("K", 10); 14 | } 15 | 16 | reproduction() { 17 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 18 | } 19 | 20 | // Roots of trees will not be at tick=1! 21 | 10 early() { 22 | sim.addSubpop("p1", 10); 23 | } 24 | 25 | early() { 26 | p1.fitnessScaling = K / p1.individualCount; 27 | } 28 | 29 | 25 late() { 30 | sim.treeSeqOutput(TREES_FILE); 31 | catn("Done."); 32 | sim.simulationFinished(); 33 | } 34 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_with_metadata.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | initializeTreeSeq(); 6 | initializeMutationRate(1e-2); 7 | initializeMutationType("m1", 0.5, "f", -0.1); 8 | initializeGenomicElementType("g1", m1, 1.0); 9 | initializeGenomicElement(g1, 0, 99); 10 | initializeRecombinationRate(1e-2); 11 | } 12 | 13 | 1 early() { 14 | sim.addSubpop("p1", 10); 15 | p1.name = "first_population"; 16 | p1.description = "i'm the first population"; 17 | sim.addSubpop("p3", 10); 18 | p3.name = "other_population"; 19 | p3.description = "i'm the other population"; 20 | 21 | } 22 | 23 | 10 late() { 24 | // metadata!! 25 | d = Dictionary(); 26 | d.setValue("hello", "world"); 27 | d.setValue("pi", c(3, 1, 4, 1, 5, 9)); 28 | sim.treeSeqOutput(TREES_FILE, metadata=d); 29 | catn("Done."); 30 | sim.simulationFinished(); 31 | } 32 | -------------------------------------------------------------------------------- /docs/neutral_restart.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | initializeSLiMModelType("nonWF"); 4 | initializeTreeSeq(); 5 | initializeMutationRate(1e-8); 6 | initializeMutationType("m0", 0.5, "f", 0.0); 7 | initializeGenomicElementType("g1", m0, 1.0); 8 | initializeGenomicElement(g1, 0, 1e6-1); 9 | initializeRecombinationRate(1e-8); 10 | defineConstant("K", 1000); 11 | } 12 | 13 | reproduction(p1) { 14 | subpop.addCrossed(individual, 15 | subpop.sampleIndividuals(1)); 16 | } 17 | 18 | 1 early() { 19 | sim.readFromPopulationFile("initialize_nonWF.trees"); 20 | catn("Loaded " + length(sim.subpopulations) 21 | + " populations from a file; now in generation " + sim.cycle); 22 | catn("Population sizes: " + paste(sim.subpopulations.individualCount)); 23 | } 24 | 25 | 2: early() { 26 | p0.fitnessScaling = K / p0.individualCount; 27 | } 28 | 29 | 10 early() { 30 | sim.treeSeqOutput("nonWF_restart.trees"); 31 | catn("Done."); 32 | sim.simulationFinished(); 33 | } 34 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_init_mutated_nonWF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | initializeSLiMModelType("nonWF"); 6 | initializeTreeSeq(); 7 | initializeMutationType("m1", 0.5, "f", -0.1); 8 | initializeGenomicElementType("g1", m1, 1.0); 9 | initializeGenomicElement(g1, 0, 99); 10 | initializeMutationRate(0.0); 11 | initializeRecombinationRate(0.0); 12 | defineConstant("K", 10); 13 | } 14 | 15 | reproduction() { 16 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 17 | } 18 | 19 | 2: early() { 20 | p1.fitnessScaling = K / p1.individualCount; 21 | } 22 | 23 | 1 late() { 24 | sim.addSubpop("p1", 10); 25 | for (k in seqLen(length(p1.haplosomes))) { 26 | genome = p1.haplosomes[k]; 27 | genome.addNewMutation(m1, 0.0, k); 28 | } 29 | } 30 | 31 | 10 late() { 32 | sim.treeSeqOutput(TREES_FILE); 33 | catn("Done."); 34 | sim.simulationFinished(); 35 | } 36 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.10 - Adding a neutral burn-in after simulation with recapitation I.txt: -------------------------------------------------------------------------------- 1 | // Keywords: tree-sequence recording, tree sequence recording 2 | 3 | initialize() { 4 | initializeTreeSeq(simplificationRatio=INF); 5 | initializeMutationRate(0); 6 | initializeMutationType("m2", 0.5, "f", 1.0); 7 | m2.convertToSubstitution = F; 8 | initializeGenomicElementType("g1", m2, 1); 9 | initializeGenomicElement(g1, 0, 1e6 - 1); 10 | initializeRecombinationRate(3e-10); 11 | } 12 | 1 late() { 13 | sim.addSubpop("p1", 1e5); 14 | } 15 | 100 late() { 16 | sample(p1.genomes, 1).addNewDrawnMutation(m2, 5e5); 17 | } 18 | 100:10000 late() { 19 | mut = sim.mutationsOfType(m2); 20 | if (mut.size() != 1) 21 | stop(sim.cycle + ": LOST"); 22 | else if (sum(sim.mutationFrequencies(NULL, mut)) == 1.0) 23 | { 24 | sim.treeSeqOutput("recipe_17.10_decap.trees"); 25 | sim.simulationFinished(); 26 | } 27 | } 28 | 29 | // Part II of this recipe, which is a Python script, may be found in 30 | // the Recipes archive downloadable at https://messerlab.org/slim/ 31 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.4 - Detecting the dip in diversity (analyzing tree heights in Python) I.txt: -------------------------------------------------------------------------------- 1 | // Keywords: tree-sequence recording, tree sequence recording 2 | 3 | initialize() { 4 | defineConstant("N", 100); // pop size 5 | defineConstant("L", 1e8); // total chromosome length 6 | defineConstant("L0", 200e3); // between genes 7 | defineConstant("L1", 1e3); // gene length 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-7); 10 | initializeRecombinationRate(1e-8, L-1); 11 | initializeMutationType("m2", 0.5, "g", -(5/N), 1.0); 12 | initializeGenomicElementType("g2", m2, 1.0); 13 | 14 | for (start in seq(from=L0, to=L-(L0+L1), by=(L0+L1))) 15 | initializeGenomicElement(g2, start, (start+L1)-1); 16 | } 17 | 1 early() { 18 | sim.addSubpop("p1", N); 19 | community.rescheduleScriptBlock(s1, 10*N, 10*N); 20 | } 21 | s1 10 late() { 22 | sim.treeSeqOutput("./recipe_17.4.trees"); 23 | } 24 | 25 | // Part II of this recipe, which is a Python script, may be found in 26 | // the Recipes archive downloadable at https://messerlab.org/slim/ 27 | -------------------------------------------------------------------------------- /tests/test_recipes/make_v3_test_additions.py: -------------------------------------------------------------------------------- 1 | import tskit, pyslim 2 | 3 | """ 4 | Takes an old tree sequence and update the metadata *without* properly updating 5 | the top-level metadata. 6 | """ 7 | 8 | ts = tskit.load("recipe_WF.v3.5.trees") 9 | tables = ts.dump_tables() 10 | 11 | tables.populations.clear() 12 | tables.populations.metadata_schema = pyslim.slim_metadata_schemas['population'] 13 | for p in ts.populations(): 14 | tables.populations.append(p) 15 | 16 | tables.individuals.clear() 17 | tables.individuals.metadata_schema = pyslim.slim_metadata_schemas['individual'] 18 | d = pyslim.default_slim_metadata("individual") 19 | for i in ts.individuals(): 20 | d.update(i.metadata) 21 | ii = i.replace(metadata=d) 22 | tables.individuals.append(ii) 23 | 24 | tables.mutations.clear() 25 | tables.mutations.metadata_schema = pyslim.slim_metadata_schemas['mutation'] 26 | d = pyslim.default_slim_metadata("mutation") 27 | for m in ts.mutations(): 28 | tables.mutations.append(m) 29 | 30 | ts = tables.tree_sequence() 31 | ts.dump("recipe_WF.v3.5_and_v3.6.trees") 32 | -------------------------------------------------------------------------------- /docs/migrants.slim: -------------------------------------------------------------------------------- 1 | initialize() { 2 | initializeSLiMModelType("nonWF"); 3 | initializeSex("A"); 4 | initializeTreeSeq(); 5 | initializeMutationRate(0.0); 6 | initializeMutationType("m1", 0.5, "f", 0.0); 7 | initializeGenomicElementType("g1", m1, 1.0); 8 | initializeGenomicElement(g1, 0, 1e8-1); 9 | initializeRecombinationRate(1e-8); 10 | defineConstant("K", 1000); 11 | } 12 | 13 | reproduction(NULL, "F") { 14 | subpop.addCrossed(individual, 15 | subpop.sampleIndividuals(1, sex="M")); 16 | } 17 | 18 | 19 | 1 early() { 20 | sim.addSubpop("p1", K); 21 | sim.addSubpop("p2", K); 22 | } 23 | 24 | early() { 25 | num_migrants = rpois(2, 0.01 * c(p1.individualCount, p2.individualCount)); 26 | migrants1 = sample(p1.individuals, num_migrants[0]); 27 | migrants2 = sample(p2.individuals, num_migrants[1]); 28 | p2.takeMigrants(migrants1); 29 | p1.takeMigrants(migrants2); 30 | p1.fitnessScaling = K / p1.individualCount; 31 | p2.fitnessScaling = K / p2.individualCount; 32 | } 33 | 34 | 1000 late() { 35 | sim.treeSeqOutput("migrants.trees"); 36 | } 37 | -------------------------------------------------------------------------------- /tests/test_recipes/restart_and_run_nonWF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | // as well as any bespoke TREES_FILE for output, you need to define: 6 | // TREES_IN = path to trees to initialise 7 | initializeSLiMModelType("nonWF"); 8 | initializeSLiMOptions(dimensionality="xy"); 9 | initializeTreeSeq(); 10 | initializeMutationRate(1e-2); 11 | initializeMutationType("m1", 0.5, "f", -0.1); 12 | initializeGenomicElementType("g1", m1, 1.0); 13 | initializeGenomicElement(g1, 0, 99); 14 | initializeRecombinationRate(1e-2); 15 | if (!exists("SUBPOP_MAP")) defineConstant("SUBPOP_MAP", NULL); 16 | } 17 | 18 | 1 early() { 19 | if (STAGE == "early") { 20 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 21 | } 22 | } 23 | 24 | 1 late() { 25 | if (STAGE == "late") { 26 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 27 | } 28 | } 29 | 30 | 20 early() { 31 | catn("Done."); 32 | sim.treeSeqOutput(TREES_FILE, simplify=F); 33 | sim.simulationFinished(); 34 | } 35 | -------------------------------------------------------------------------------- /docs/generation_time.slim: -------------------------------------------------------------------------------- 1 | initialize() { 2 | initializeSLiMModelType("nonWF"); 3 | initializeSex("A"); 4 | initializeTreeSeq(); 5 | initializeMutationRate(2e-8); 6 | initializeMutationType("m1", 0.5, "f", 0.0); 7 | initializeGenomicElementType("g1", m1, 1.0); 8 | initializeGenomicElement(g1, 0, 1e8-1); 9 | initializeRecombinationRate(1e-8); 10 | defineConstant("K", 1000); 11 | defineGlobal("GENTIME", rep(NAN, 100)); 12 | } 13 | 14 | reproduction(p1, "F") { 15 | for (k in seqLen(rpois(1, individual.age))) { 16 | mate = subpop.sampleIndividuals(1, sex="M"); 17 | offspring = subpop.addCrossed(individual, mate); 18 | } 19 | } 20 | 21 | 1 early() { 22 | sim.addSubpop("p1", K); 23 | } 24 | 25 | early() { 26 | p1.fitnessScaling = K / p1.individualCount; 27 | } 28 | 29 | 1: late() { 30 | // this should happen *after* mortality (so, in late()) 31 | GENTIME[community.tick - 1] = mean(p1.individuals.meanParentAge); 32 | } 33 | 34 | 100 late() { 35 | sim.treeSeqOutput( 36 | "generation_time.trees", 37 | metadata=Dictionary("generation_times", GENTIME) 38 | ); 39 | catn("Done! Mean generation time " + mean(GENTIME[50:99])); 40 | } 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-2025 tskit developers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 18.13 - Tree-sequence recording and nucleotide-based models II.py: -------------------------------------------------------------------------------- 1 | # Keywords: Python, nucleotide-based, nucleotide sequence, sequence-based mutation rate 2 | 3 | import tskit, pyslim 4 | import numpy as np 5 | 6 | ts = tskit.load("recipe_nucleotides.trees") 7 | 8 | M = [[0 for _ in pyslim.NUCLEOTIDES] for _ in pyslim.NUCLEOTIDES] 9 | for mut in ts.mutations(): 10 | mut_list = mut.metadata["mutation_list"] 11 | k = np.argmax([u["slim_time"] for u in mut_list]) 12 | derived_nuc = mut_list[k]["nucleotide"] 13 | if mut.parent == -1: 14 | acgt = ts.reference_sequence.data[int(ts.site(mut.site).position)] 15 | parent_nuc = pyslim.NUCLEOTIDES.index(acgt) 16 | else: 17 | parent_mut = ts.mutation(mut.parent) 18 | assert(parent_mut.site == mut.site) 19 | parent_nuc = parent_mut.metadata["mutation_list"][0]["nucleotide"] 20 | M[parent_nuc][derived_nuc] += 1 21 | 22 | print("{}\t{}\t{}".format('ancestral', 'derived', 'count')) 23 | for j, a in enumerate(pyslim.NUCLEOTIDES): 24 | for k, b in enumerate(pyslim.NUCLEOTIDES): 25 | print("{}\t{}\t{}".format(a, b, M[j][k])) 26 | -------------------------------------------------------------------------------- /tests/test_recipes/restart_and_run_WF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | // as well as any bespoke TREES_FILE for output, you need to define: 6 | // TREES_IN = path to trees to initialise 7 | initializeSLiMOptions(dimensionality="xy"); 8 | initializeTreeSeq(timeUnit="generations"); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | if (!exists("SUBPOP_MAP")) defineConstant("SUBPOP_MAP", NULL); 15 | } 16 | 17 | // output immediately! Nothing should have changed. 18 | 1 early() { 19 | if (STAGE == "early") { 20 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 21 | } 22 | } 23 | 1 late() { 24 | if (STAGE == "late") { 25 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 26 | } 27 | } 28 | 29 | 20 early() { 30 | catn("Done."); 31 | sim.treeSeqOutput(TREES_FILE, simplify=F); 32 | sim.simulationFinished(); 33 | } 34 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_resettable_nonWF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | initializeSLiMModelType("nonWF"); 6 | initializeSLiMOptions(keepPedigrees=T); 7 | initializeTreeSeq(); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | defineConstant("K", 10); 14 | } 15 | 16 | reproduction() { 17 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 18 | } 19 | 20 | 1 early() { 21 | sim.addSubpop("p1", 10); 22 | } 23 | 24 | early() { 25 | p1.fitnessScaling = K / p1.individualCount; 26 | } 27 | 28 | 3 late() { 29 | inds = sample(p1.individuals, 7); 30 | sim.treeSeqRememberIndividuals(inds); 31 | sim.killIndividuals(inds); 32 | defineGlobal("METADATA", Dictionary()); 33 | METADATA.setValue("reset_tick", community.tick); 34 | } 35 | 36 | 10 late() { 37 | sim.treeSeqOutput(TREES_FILE, metadata=METADATA); 38 | catn("Done."); 39 | sim.simulationFinished(); 40 | } 41 | -------------------------------------------------------------------------------- /tests/test_recipes/restart_nucleotides_nonWF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(25); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | // as well as any bespoke TREES_FILE for output, you need to define: 6 | // TREES_IN = path to trees to initialise 7 | defineConstant("L", 1e2); 8 | initializeSLiMModelType("nonWF"); 9 | initializeSLiMOptions(keepPedigrees=T, nucleotideBased=T); 10 | initializeTreeSeq(); 11 | initializeAncestralNucleotides(paste0(rep("A", L))); 12 | initializeMutationTypeNuc("m1", 0.5, "f", 0.0); 13 | initializeGenomicElementType("g1", m1, 1.0, mmJukesCantor(4e-2)); 14 | initializeGenomicElement(g1, 0, L-1); 15 | initializeRecombinationRate(1e-2); 16 | if (!exists("SUBPOP_MAP")) defineConstant("SUBPOP_MAP", NULL); 17 | } 18 | 19 | 1 late() { 20 | // output immediately! Nothing should have changed. 21 | md = treeSeqMetadata(TREES_IN, userData=F).getValue("SLiM").getValue("user_metadata"); 22 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 23 | sim.treeSeqOutput(TREES_FILE, simplify=F, metadata=md); 24 | } 25 | 26 | 2 early() { 27 | catn("Done."); 28 | sim.simulationFinished(); 29 | } 30 | 31 | -------------------------------------------------------------------------------- /docs/_static/export-layers-svg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # CC-BY https://answers.launchpad.net/inkscape/+question/48164 3 | # $1 is the file to extract layers from 4 | # $2: are the layers to always include 5 | # 6 | # needs xmlstarlet 7 | # 8 | # Notes: 9 | # - doesn't deal with spaces in object names 10 | 11 | if ! command -v "xmlstarlet" &>/dev/null || ! command -v 'inkscape' &>/dev/null; 12 | then 13 | echo >&2 "can't find xmlstarlet and/or inkscape, not regenerating SVG-derived figures" 14 | exit 0 15 | fi 16 | 17 | TMPFILE=$(mktemp /tmp/output.XXXXXXXXX).svg 18 | cp $1 $TMPFILE 19 | 20 | YESLAYERS=${*:2} 21 | ALLLAYERS=$(xmlstarlet sel -t -m "//*[@inkscape:groupmode=\"layer\"]" -v "concat(@inkscape:label,' ')" $TMPFILE|sort -Vr) 22 | NOLAYERS=$(comm -1 -3 <(echo $YESLAYERS|tr ' ' '\n'|sort) <(echo $ALLLAYERS|tr ' ' '\n'|sort)) 23 | 24 | for layer in $NOLAYERS 25 | do 26 | id=$(xmlstarlet sel -t -m "//*[@inkscape:label=\"$layer\"]" -v "@id" $TMPFILE) 27 | xmlstarlet ed -S -L -d "//*[@id=\"$id\"]" $TMPFILE 28 | done 29 | 30 | # --export-area-drawing will crop to visible 31 | inkscape --export-area-drawing --export-type="svg" --export-filename=- $TMPFILE 32 | 33 | [ -f $TMPFILE ] && rm $TMPFILE 34 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.8 - Starting a hermaphroditic WF model with a coalescent history II.txt: -------------------------------------------------------------------------------- 1 | // Keywords: tree-sequence recording, tree sequence recording 2 | 3 | // Part I of this recipe, which is a Python script, may be found in 4 | // the Recipes archive downloadable at https://messerlab.org/slim/ 5 | 6 | initialize() { 7 | initializeTreeSeq(); 8 | initializeMutationRate(0); 9 | initializeMutationType("m1", 0.5, "f", 0.0); 10 | initializeMutationType("m2", 0.5, "f", 0.1); 11 | initializeGenomicElementType("g1", m2, 1.0); 12 | initializeGenomicElement(g1, 0, 1e8-1); 13 | initializeRecombinationRate(1e-8); 14 | } 15 | 1 late() { 16 | sim.readFromPopulationFile("recipe_17.8.trees"); 17 | target = sample(sim.subpopulations.genomes, 1); 18 | target.addNewDrawnMutation(m2, 10000); 19 | } 20 | 1: late() { 21 | if (sim.mutationsOfType(m2).size() == 0) { 22 | print(sim.substitutions.size() ? "FIXED" else "LOST"); 23 | sim.treeSeqOutput("recipe_17.8_II.trees"); 24 | sim.simulationFinished(); 25 | } 26 | } 27 | 2000 early() { sim.simulationFinished(); } 28 | 29 | // Part III of this recipe, which is a Python script, may be found in 30 | // the Recipes archive downloadable at https://messerlab.org/slim/ 31 | -------------------------------------------------------------------------------- /docs/neutral_nucleotide_restart.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | initializeSLiMModelType("nonWF"); 4 | initializeSLiMOptions(nucleotideBased=T); 5 | // we must generate ancestral nucleotides, but they will be unused, 6 | // replaced by the reference sequence in the .trees file loaded below 7 | initializeAncestralNucleotides(randomNucleotides(1e6)); 8 | initializeTreeSeq(); 9 | initializeMutationTypeNuc("m0", 0.5, "f", 0.0); 10 | initializeGenomicElementType("g1", m0, 1.0, mmJukesCantor(1e-7)); 11 | initializeGenomicElement(g1, 0, 1e6-1); 12 | initializeRecombinationRate(1e-8); 13 | defineConstant("K", 1000); 14 | } 15 | 16 | reproduction(p1) { 17 | subpop.addCrossed(individual, 18 | subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 early() { 22 | sim.readFromPopulationFile("initialize_nonWF_nuc.trees"); 23 | catn("Loaded " + length(sim.subpopulations) 24 | + " populations from a file; now in generation " + sim.cycle); 25 | catn("Population sizes: " + paste(sim.subpopulations.individualCount)); 26 | } 27 | 28 | 2: early() { 29 | p0.fitnessScaling = K / p0.individualCount; 30 | } 31 | 32 | 10 early() { 33 | catn("Done."); 34 | sim.simulationFinished(); 35 | } 36 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.3 - Simulation conditional upon fixation of a sweep, preserving ancestry I.txt: -------------------------------------------------------------------------------- 1 | // Keywords: tree-sequence recording, tree sequence recording, conditional sweep 2 | 3 | initialize() { 4 | initializeMutationRate(1e-7); 5 | initializeMutationType("m1", 0.5, "f", 0.0); 6 | initializeMutationType("m2", 0.5, "g", -0.01, 1.0); // deleterious 7 | initializeMutationType("m3", 1.0, "f", 0.05); // introduced 8 | initializeGenomicElementType("g1", c(m1, m2), c(0.9, 0.1)); 9 | initializeGenomicElement(g1, 0, 99999); 10 | initializeRecombinationRate(1e-8); 11 | } 12 | 1 early() { 13 | defineConstant("simID", getSeed()); 14 | sim.addSubpop("p1", 500); 15 | } 16 | 1000 late() { 17 | target = sample(p1.genomes, 1); 18 | target.addNewDrawnMutation(m3, 10000); 19 | sim.outputFull("/tmp/slim_" + simID + ".txt"); 20 | } 21 | 1000:100000 late() { 22 | if (sim.countOfMutationsOfType(m3) == 0) { 23 | if (sum(sim.substitutions.mutationType == m3) == 1) { 24 | cat(simID + ": FIXED\n"); 25 | sim.simulationFinished(); 26 | } else { 27 | cat(simID + ": LOST - RESTARTING\n"); 28 | 29 | sim.readFromPopulationFile("/tmp/slim_" + simID + ".txt"); 30 | setSeed(rdunif(1, 0, asInteger(2^62) - 1)); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.5 - Mapping admixture (analyzing ancestry in Python) II.py: -------------------------------------------------------------------------------- 1 | # Keywords: Python, tree-sequence recording, tree sequence recording 2 | 3 | # This is a Python recipe; note that it runs the SLiM model internally, below 4 | 5 | import subprocess, tskit 6 | import matplotlib.pyplot as plt 7 | import numpy as np 8 | 9 | # Run the SLiM model and load the resulting .trees file 10 | #subprocess.check_output(["slim", "-m", "-s", "0", "./recipe_17.5.slim"]) 11 | ts = tskit.load("./recipe_17.5.trees") 12 | 13 | # Load the .trees file and assess true local ancestry 14 | breaks = np.zeros(ts.num_trees + 1) 15 | ancestry = np.zeros(ts.num_trees + 1) 16 | for tree in ts.trees(): 17 | subpop_sum, subpop_weights = 0, 0 18 | for root in tree.roots: 19 | leaves_count = tree.num_samples(root) - 1 # subtract one for the root, which is a sample 20 | subpop_sum += tree.population(root) * leaves_count 21 | subpop_weights += leaves_count 22 | breaks[tree.index] = tree.interval[0] 23 | ancestry[tree.index] = subpop_sum / subpop_weights 24 | breaks[-1] = ts.sequence_length 25 | ancestry[-1] = ancestry[-2] 26 | 27 | # Make a simple plot 28 | plt.plot(breaks, ancestry) 29 | # plt.show() 30 | plt.savefig("./recipe_17.5.png") 31 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.3 - Simulation conditional upon fixation of a sweep, preserving ancestry II.txt: -------------------------------------------------------------------------------- 1 | // Keywords: tree-sequence recording, tree sequence recording, conditional sweep 2 | 3 | initialize() { 4 | initializeTreeSeq(); 5 | initializeMutationRate(1e-8); 6 | initializeMutationType("m2", 0.5, "g", -0.01, 1.0); // deleterious 7 | initializeMutationType("m3", 1.0, "f", 0.05); // introduced 8 | initializeGenomicElementType("g1", m2, 1.0); 9 | initializeGenomicElement(g1, 0, 99999); 10 | initializeRecombinationRate(1e-8); 11 | } 12 | 1 early() { 13 | defineConstant("simID", getSeed()); 14 | sim.addSubpop("p1", 500); 15 | } 16 | 1000 late() { 17 | target = sample(p1.genomes, 1); 18 | target.addNewDrawnMutation(m3, 10000); 19 | sim.treeSeqOutput("/tmp/slim_" + simID + ".trees"); 20 | } 21 | 1000:100000 late() { 22 | if (sim.countOfMutationsOfType(m3) == 0) { 23 | if (sum(sim.substitutions.mutationType == m3) == 1) { 24 | cat(simID + ": FIXED\n"); 25 | sim.treeSeqOutput("slim_" + simID + "_FIXED.trees"); 26 | sim.simulationFinished(); 27 | } else { 28 | cat(simID + ": LOST - RESTARTING\n"); 29 | 30 | sim.readFromPopulationFile("/tmp/slim_" + simID + ".trees"); 31 | setSeed(rdunif(1, 0, asInteger(2^62) - 1)); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.9 - Starting a sexual nonWF model with a coalescent history II.txt: -------------------------------------------------------------------------------- 1 | // Keywords: nonWF, non-Wright-Fisher, sexual, tree-sequence recording, tree sequence recording, reproduction() 2 | 3 | // Part I of this recipe, which is a Python script, may be found in 4 | // the Recipes archive downloadable at https://messerlab.org/slim/ 5 | 6 | initialize() { 7 | initializeSLiMModelType("nonWF"); 8 | initializeTreeSeq(); 9 | initializeSex("A"); 10 | initializeMutationRate(0); 11 | initializeMutationType("m1", 0.5, "f", 0.0); 12 | initializeMutationType("m2", 0.5, "f", 0.1); 13 | m2.convertToSubstitution=T; 14 | initializeGenomicElementType("g1", m2, 1.0); 15 | initializeGenomicElement(g1, 0, 1e8-1); 16 | initializeRecombinationRate(1e-8); 17 | } 18 | reproduction(NULL, "F") { 19 | subpop.addCrossed(individual, subpop.sampleIndividuals(1, sex="M")); 20 | } 21 | 1 early() { 22 | sim.readFromPopulationFile("recipe_17.9.trees"); 23 | } 24 | early() { 25 | p0.fitnessScaling = 5000 / p0.individualCount; 26 | } 27 | 1: late() { 28 | if (sim.mutationsOfType(m2).size() == 0) { 29 | print(sim.substitutions.size() ? "FIXED" else "LOST"); 30 | sim.treeSeqOutput("recipe_17.9_II.trees"); 31 | sim.simulationFinished(); 32 | } 33 | } 34 | 2000 early() { sim.simulationFinished(); } 35 | -------------------------------------------------------------------------------- /tests/test_recipes/reset_nonWF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 4 | // as well as any bespoke TREES_FILE for output, you need to define: 5 | // TREES_IN = path to trees to initialise 6 | initializeSLiMModelType("nonWF"); 7 | initializeTreeSeq(); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | } 14 | 15 | // output immediately, and record state 16 | 1 early() { 17 | if (STAGE == "early") { 18 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 19 | sim.treeSeqOutput(TREES_FILE, simplify=F, 20 | metadata=Dictionary( 21 | "tick", community.tick, 22 | "individuals", sim.subpopulations.individuals.pedigreeID 23 | )); 24 | } 25 | } 26 | 27 | 1 late() { 28 | if (STAGE == "late") { 29 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 30 | sim.treeSeqOutput(TREES_FILE, simplify=F, 31 | metadata=Dictionary( 32 | "tick", community.tick, 33 | "individuals", sim.subpopulations.individuals.pedigreeID 34 | )); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /docs/installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | jupytext: 3 | text_representation: 4 | extension: .md 5 | format_name: myst 6 | format_version: 0.12 7 | jupytext_version: 1.9.1 8 | kernelspec: 9 | display_name: Python 3 10 | language: python 11 | name: python3 12 | --- 13 | 14 | (sec_installation)= 15 | 16 | # Installation 17 | 18 | Pyslim can be installed using the standard [pip](https://pypi.org/project/pyslim/) distribution method: 19 | 20 | ```bash 21 | python3 -m pip install pyslim 22 | ``` 23 | 24 | To install a [different version](https://pypi.org/project/pyslim/#history), e.g., 25 | the 1.0 beta release whose version string is "1.0b1", just append this, like: 26 | 27 | ```bash 28 | python3 -m pip install pyslim==1.0b1 29 | ``` 30 | 31 | Alternatively, you can install from source as described in [](sec_development). 32 | 33 | 34 | ## Troubleshooting 35 | 36 | If you find a bug in ``pyslim`` or want to suggest an improvement, please 37 | [open an issue](https://github.com/tskit-dev/pyslim/issues) on our github page. 38 | If you have a question about using tree sequences, 39 | please ask it at [the tskit discussion page](https://github.com/tskit-dev/tskit/discussions). 40 | Finally, questions about SLiM should be directed to 41 | [the SLiM mailing list](https://groups.google.com/forum/#!forum/slim-discuss). 42 | -------------------------------------------------------------------------------- /tests/test_recipes/restart_WF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | // as well as any bespoke TREES_FILE for output, you need to define: 6 | // TREES_IN = path to trees to initialise 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | if (!exists("SUBPOP_MAP")) defineConstant("SUBPOP_MAP", NULL); 14 | } 15 | 16 | // output immediately! Nothing should have changed. 17 | 1 early() { 18 | if (STAGE == "early") { 19 | md = treeSeqMetadata(TREES_IN, userData=F).getValue("SLiM").getValue("user_metadata"); 20 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 21 | sim.treeSeqOutput(TREES_FILE, simplify=F, metadata=md); 22 | } 23 | } 24 | 1 late() { 25 | if (STAGE == "late") { 26 | md = treeSeqMetadata(TREES_IN, userData=F).getValue("SLiM").getValue("user_metadata"); 27 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 28 | sim.treeSeqOutput(TREES_FILE, simplify=F, metadata=md); 29 | } 30 | } 31 | 32 | 20 early() { 33 | catn("Done."); 34 | sim.simulationFinished(); 35 | } 36 | -------------------------------------------------------------------------------- /tests/test_recipes/reset_WF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | // as well as any bespoke TREES_FILE for output, you need to define: 6 | // TREES_IN = path to trees to initialise 7 | // STAGE 8 | initializeSLiMOptions(keepPedigrees=T); 9 | initializeTreeSeq(timeUnit="generations"); 10 | initializeMutationRate(1e-2); 11 | initializeMutationType("m1", 0.5, "f", -0.1); 12 | initializeGenomicElementType("g1", m1, 1.0); 13 | initializeGenomicElement(g1, 0, 99); 14 | initializeRecombinationRate(1e-2); 15 | } 16 | 17 | // output immediately, and record state 18 | 1 early() { 19 | if (STAGE == "early") { 20 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 21 | sim.treeSeqOutput(TREES_FILE, simplify=F, 22 | metadata=Dictionary( 23 | "tick", community.tick, 24 | "individuals", sim.subpopulations.individuals.pedigreeID 25 | )); 26 | } 27 | } 28 | 29 | 1 late() { 30 | if (STAGE == "late") { 31 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 32 | sim.treeSeqOutput(TREES_FILE, simplify=F, 33 | metadata=Dictionary( 34 | "tick", community.tick, 35 | "individuals", sim.subpopulations.individuals.pedigreeID 36 | )); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /docs/util.py: -------------------------------------------------------------------------------- 1 | def pp(x): 2 | ''' 3 | Hacky way to pretty-print nested dict __repr__'s 4 | ''' 5 | if not isinstance(x, str): 6 | x = x.__repr__() 7 | delims = {"'" : "'", '"' : '"', "(" : ")", "[" : "]"} 8 | out = [] 9 | indent = [0] 10 | inside = [] 11 | prefix = 0 12 | name = True 13 | for a in x: 14 | if prefix == 0 and a == " ": 15 | continue 16 | if a == "}": 17 | prefix = 0 18 | out.append("\n" + " " * (sum(indent) - 1)) 19 | indent = indent[:-1] 20 | else: 21 | prefix += 1 22 | out.append(a) 23 | if a == '{': 24 | indent.append(min(prefix, 4)) 25 | prefix = 0 26 | out.append("\n" + " " * sum(indent)) 27 | inside = [] 28 | if len(inside) > 0 and inside[-1] in delims: 29 | if a == delims[inside[-1]]: 30 | inside = inside[:-1] 31 | else: 32 | if a in delims: 33 | inside.append(a) 34 | if name: 35 | if a == ':': 36 | name = False 37 | else: 38 | if a == ',': 39 | name = True 40 | prefix = 0 41 | out.append("\n" + " " * sum(indent)) 42 | out = "".join(out) 43 | print(out) 44 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.5 - Mapping admixture (analyzing ancestry in Python) I.txt: -------------------------------------------------------------------------------- 1 | // Keywords: tree-sequence recording, tree sequence recording, migration, dispersal 2 | 3 | initialize() { 4 | defineConstant("L", 1e8); 5 | initializeTreeSeq(); 6 | initializeMutationRate(0); 7 | initializeMutationType("m1", 0.5, "f", 0.1); 8 | initializeGenomicElementType("g1", m1, 1.0); 9 | initializeGenomicElement(g1, 0, L-1); 10 | initializeRecombinationRate(1e-8); 11 | } 12 | 1 late() { 13 | sim.addSubpop("p1", 500); 14 | sim.addSubpop("p2", 500); 15 | sim.treeSeqRememberIndividuals(sim.subpopulations.individuals); 16 | 17 | p1.genomes.addNewDrawnMutation(m1, asInteger(L * 0.2)); 18 | p2.genomes.addNewDrawnMutation(m1, asInteger(L * 0.8)); 19 | 20 | sim.addSubpop("p3", 1000); 21 | p3.setMigrationRates(c(p1, p2), c(0.5, 0.5)); 22 | } 23 | 2 late() { 24 | p3.setMigrationRates(c(p1, p2), c(0.0, 0.0)); 25 | p1.setSubpopulationSize(0); 26 | p2.setSubpopulationSize(0); 27 | } 28 | 2: late() { 29 | if (sim.mutationsOfType(m1).size() == 0) 30 | { 31 | sim.treeSeqOutput("./recipe_17.5.trees"); 32 | sim.simulationFinished(); 33 | } 34 | } 35 | 10000 late() { 36 | stop("Did not reach fixation of beneficial alleles."); 37 | } 38 | 39 | // Part II of this recipe, which is a Python script, may be found in 40 | // the Recipes archive downloadable at https://messerlab.org/slim/ 41 | -------------------------------------------------------------------------------- /tests/test_recipes/restart_nonWF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | // as well as any bespoke TREES_FILE for output, you need to define: 6 | // TREES_IN = path to trees to initialise 7 | initializeSLiMModelType("nonWF"); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | if (!exists("SUBPOP_MAP")) defineConstant("SUBPOP_MAP", NULL); 15 | } 16 | 17 | // output immediately! Nothing should have changed. 18 | 1 early() { 19 | if (STAGE == "early") { 20 | md = treeSeqMetadata(TREES_IN, userData=F).getValue("SLiM").getValue("user_metadata"); 21 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 22 | sim.treeSeqOutput(TREES_FILE, simplify=F, metadata=md); 23 | } 24 | } 25 | 26 | 1 late() { 27 | if (STAGE == "late") { 28 | md = treeSeqMetadata(TREES_IN, userData=F).getValue("SLiM").getValue("user_metadata"); 29 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 30 | sim.treeSeqOutput(TREES_FILE, simplify=F, metadata=md); 31 | } 32 | } 33 | 34 | 20 early() { 35 | catn("Done."); 36 | sim.simulationFinished(); 37 | } 38 | -------------------------------------------------------------------------------- /pyslim/util.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | import numpy as np 3 | 4 | def unique_labels_by_group(group, label, minlength=0): 5 | ''' 6 | Given an array of integers ("group") from -1 and up and an array of integer 7 | "labels" of the same length, returns a logical value for each distinct 8 | value of ``group``, except for -1, indicating if all the entries of 9 | ``label`` that correspond to that value of ``group`` are identical. The 10 | return value will be of length at least ``minlength``. 11 | 12 | In other words, if the result is ``x``, then 13 | ``x[j]`` is ``len(set(label[group == j])) <= 1``. 14 | ''' 15 | warnings.warn( 16 | "The unique_labels_by_group( ) method is no longer used in pyslim, " 17 | "so is now deprecated. Please copy the source code for your own use " 18 | "if you wish to keep using it.", 19 | FutureWarning, 20 | ) 21 | w = label.astype("float64") 22 | n = np.bincount(1 + group, minlength=minlength + 1) 23 | x = np.bincount(1 + group, weights=w, minlength=minlength + 1) 24 | with np.errstate(divide='ignore', invalid='ignore'): 25 | xm = x/n 26 | xm[n == 0] = 0 27 | w -= xm[1 + group] 28 | gw = np.bincount(1 + group, weights=np.abs(w), minlength=minlength + 1)[1:] 29 | # after subtracting groupwise means, should be all zero 30 | return np.abs(gw) < 1e-7 31 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 18.13 - Tree-sequence recording and nucleotide-based models III.py: -------------------------------------------------------------------------------- 1 | # Keywords: Python, nucleotide-based, nucleotide sequence, sequence-based mutation rate 2 | 3 | import tskit, pyslim 4 | import numpy as np 5 | 6 | ts = tskit.load("recipe_nucleotides.trees") 7 | slim_gen = ts.metadata["SLiM"]["tick"] 8 | 9 | M = np.zeros((4,4,4,4), dtype='int') 10 | for mut in ts.mutations(): 11 | pos = ts.site(mut.site).position 12 | # skip mutations at the end of the sequence 13 | if pos > 0 and pos < ts.sequence_length - 1: 14 | mut_list = mut.metadata["mutation_list"] 15 | k = np.argmax([u["slim_time"] for u in mut_list]) 16 | derived_nuc = mut_list[k]["nucleotide"] 17 | left_nuc = pyslim.nucleotide_at(ts, mut.node, pos - 1, time = mut.time + 1.0) 18 | right_nuc = pyslim.nucleotide_at(ts, mut.node, pos + 1, time = mut.time + 1.0) 19 | parent_nuc = pyslim.nucleotide_at(ts, mut.node, pos, time = mut.time + 1.0) 20 | M[left_nuc, parent_nuc, right_nuc, derived_nuc] += 1 21 | 22 | print("{}\t{}\t{}".format('ancestral', 'derived', 'count')) 23 | for j0, a0 in enumerate(pyslim.NUCLEOTIDES): 24 | for j1, a1 in enumerate(pyslim.NUCLEOTIDES): 25 | for j2, a2 in enumerate(pyslim.NUCLEOTIDES): 26 | for k, b in enumerate(pyslim.NUCLEOTIDES): 27 | print("{}{}{}\t{}{}{}\t{}".format(a0, a1, a2, a0, b, a2, 28 | M[j0, j1, j2, k])) 29 | -------------------------------------------------------------------------------- /docs/introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | jupytext: 3 | text_representation: 4 | extension: .md 5 | format_name: myst 6 | format_version: 0.12 7 | jupytext_version: 1.9.1 8 | kernelspec: 9 | display_name: Python 3 10 | language: python 11 | name: python3 12 | --- 13 | 14 | (sec_introduction)= 15 | 16 | # Introduction 17 | 18 | This is the documentation for pyslim, a Python API 19 | for reading and modifying {ref}`tskit` tree sequence files 20 | produced by [SLiM](https://messerlab.org/slim/), 21 | or modifying files produced by other programs (e.g., 22 | {ref}`msprime`, 23 | [fwdpy11](https://fwdpy11.readthedocs.io/en/stable/pages/tsoverview.html), 24 | and [tsinfer](https://tsinfer.readthedocs.io/)) for use in SLiM. 25 | 26 | SLiM can read and write *tree sequences*, which store genetic genealogies 27 | for entire populations. These can be used to efficiently encode both the state of the 28 | population at various points during a simulation *as well as* the complete genomic 29 | ancestry. Furthermore, SLiM can "load" a saved tree sequence 30 | file to recreate the exact state of the population at the time it was saved. 31 | To do this, SLiM stores some additional information in the basic 32 | tree sequence file. 33 | 34 | First, you probably want to read the {ref}`sec_overview` 35 | for a description of what (and *who*) 36 | SLiM records in the tree sequence. 37 | Next, the {ref}`sec_tutorial` walks through the common workflows. 38 | -------------------------------------------------------------------------------- /tests/benchmark/metadata.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | SETUP=" 5 | import tskit, pyslim 6 | ts = tskit.load('benchmark/metadata.trees') 7 | pts = pyslim.load('benchmark/metadata.trees') 8 | tables = ts.tables 9 | tables.individuals.metadata_schema = tskit.MetadataSchema(None) 10 | tables.nodes.metadata_schema = tskit.MetadataSchema(None) 11 | tables.mutations.metadata_schema = tskit.MetadataSchema(None) 12 | nts = tables.tree_sequence() 13 | 14 | def tskit_fn(ts): 15 | pid = [ind.metadata['pedigree_id'] for ind in ts.individuals()] 16 | sid = [n.metadata['slim_id'] for n in ts.nodes()] 17 | s = [m.metadata['mutation_list'][0]['selection_coeff'] for m in ts.mutations()] 18 | return 0 19 | 20 | def pyslim_fn(ts): 21 | pid = [ind.metadata.pedigree_id for ind in pts.individuals()] 22 | sid = [n.metadata.slim_id for n in pts.nodes()] 23 | s = [m.metadata[0].selection_coeff for m in pts.mutations()] 24 | return 0 25 | 26 | def decode_fn(ts): 27 | pid = [pyslim.decode_individual(ind.metadata).pedigree_id for ind in nts.individuals()] 28 | sid = [pyslim.decode_node(n.metadata).slim_id for n in nts.nodes()] 29 | s = [pyslim.decode_mutation(m.metadata)[0].selection_coeff for m in nts.mutations()] 30 | return 0 31 | " 32 | 33 | echo "tskit:" 34 | python3 -m timeit -s "$SETUP" "tskit_fn(ts)" 35 | 36 | echo "pyslim:" 37 | python3 -m timeit -s "$SETUP" "pyslim_fn(ts)" 38 | 39 | echo "pyslim decode:" 40 | python3 -m timeit -s "$SETUP" "decode_fn(nts)" 41 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.10 - Adding a neutral burn-in after simulation with recapitation II.py: -------------------------------------------------------------------------------- 1 | # Keywords: Python, tree-sequence recording, tree sequence recording 2 | 3 | import tskit, pyslim 4 | import numpy as np 5 | import matplotlib.pyplot as plt 6 | 7 | # Load the .trees file 8 | ts = tskit.load("recipe_17.10_decap.trees") # no simplify! 9 | 10 | # Calculate tree heights, giving uncoalesced sites the maximum time 11 | def tree_heights(ts): 12 | heights = np.zeros(ts.num_trees + 1) 13 | for tree in ts.trees(): 14 | if tree.num_roots > 1: # not fully coalesced 15 | heights[tree.index] = ts.metadata['SLiM']['tick'] 16 | else: 17 | children = tree.children(tree.root) 18 | real_root = tree.root if len(children) > 1 else children[0] 19 | heights[tree.index] = tree.time(real_root) 20 | heights[-1] = heights[-2] # repeat the last entry for plotting with step 21 | return heights 22 | 23 | # Plot tree heights before recapitation 24 | breakpoints = list(ts.breakpoints()) 25 | heights = tree_heights(ts) 26 | plt.step(breakpoints, heights, where='post') 27 | plt.show() 28 | 29 | # Recapitate! 30 | recap = pyslim.recapitate(ts, ancestral_Ne=1e5, recombination_rate=3e-10, random_seed=1) 31 | recap.dump("recipe_17.10_recap.trees") 32 | 33 | # Plot the tree heights after recapitation 34 | breakpoints = list(recap.breakpoints()) 35 | heights = tree_heights(recap) 36 | plt.step(breakpoints, heights, where='post') 37 | plt.show() 38 | 39 | -------------------------------------------------------------------------------- /docs/phylo_bgs.slim: -------------------------------------------------------------------------------- 1 | // The following constants need to be defined: 2 | // - outfile: path to save the tree sequence of the simulation. 3 | // - popsize: population size. 4 | // - num_gens: run simulation for num_gens ticks. 5 | // - infile: a string with path to tree sequence to start from; optional. 6 | initialize() 7 | { 8 | initializeSLiMModelType("WF"); 9 | initializeTreeSeq(timeUnit="generations"); 10 | initializeMutationRate(1e-8); 11 | initializeMutationType("m1", 0.5, "f", -0.01); 12 | initializeGenomicElementType("g1", m1, 0.1); 13 | initializeGenomicElement(g1, 0, 1e6-1); 14 | initializeRecombinationRate(1e-9); 15 | } 16 | 17 | 1 late() { 18 | // if no input tree sequence is provided, then start a subpopulation 19 | if (infile == "") { 20 | p = sim.addSubpop("p1", popsize); 21 | } else { 22 | // reloading must happen in late() 23 | sim.readFromPopulationFile(infile); 24 | parent = sim.subpopulations[0]; 25 | p = sim.addSubpopSplit(max(sim.subpopulations.id) + 1, popsize, parent); 26 | parent.setSubpopulationSize(0); 27 | } 28 | p.name = popname; 29 | } 30 | 31 | // schedule the end of the simulation 32 | 1 late() { 33 | finaltick = num_gens + community.tick; 34 | community.rescheduleScriptBlock(s0, ticks=finaltick); 35 | } 36 | 37 | // event that saves the tree sequence 38 | s0 1000 late() { 39 | sim.treeSeqRememberIndividuals(sim.subpopulations.individuals); 40 | sim.treeSeqOutput(outfile); 41 | } 42 | -------------------------------------------------------------------------------- /tests/test_recipes/restart_nucleotides_WF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(25); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | // as well as any bespoke TREES_FILE for output, you need to define: 6 | // TREES_IN = path to trees to initialise 7 | defineConstant("L", 1e2); 8 | initializeSLiMOptions(keepPedigrees=T, nucleotideBased=T); 9 | initializeTreeSeq(timeUnit="generations"); 10 | if (exists("CHROM_TYPE")) { 11 | if (CHROM_TYPE == "X" | CHROM_TYPE == "Y" | CHROM_TYPE == "Z" | CHROM_TYPE == "W" 12 | | CHROM_TYPE == "HF" | CHROM_TYPE == "HM") { 13 | initializeSex(); 14 | } 15 | } 16 | initializeMutationTypeNuc("m1", 0.5, "f", 0.0); 17 | initializeMutationTypeNuc("m2", 0.5, "n", 0.0, 0.1); 18 | initializeGenomicElementType("g1", m1, 1.0, mmJukesCantor(4e-2)); 19 | if (exists("CHROM_TYPE")) { 20 | initializeChromosome(1, L, type=CHROM_TYPE, symbol=CHROM_TYPE); 21 | } 22 | initializeAncestralNucleotides(paste0(rep("A", L))); 23 | initializeGenomicElement(g1, 0, L-1); 24 | initializeRecombinationRate(1e-2); 25 | if (!exists("SUBPOP_MAP")) defineConstant("SUBPOP_MAP", NULL); 26 | } 27 | 28 | 1 late() { 29 | // output immediately! Nothing should have changed. 30 | md = treeSeqMetadata(TREES_IN, userData=F).getValue("SLiM").getValue("user_metadata"); 31 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 32 | sim.treeSeqOutput(TREES_FILE, simplify=F, metadata=md); 33 | } 34 | 35 | 2 early() { 36 | catn("Done."); 37 | sim.simulationFinished(); 38 | } 39 | -------------------------------------------------------------------------------- /tests/benchmark/annotation.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SETUP_SETUP=" 4 | import msprime 5 | 6 | def setup(): 7 | ts = msprime.simulate( 8 | 2000, 9 | Ne=1000, 10 | length=1e8, 11 | discrete_genome=True, 12 | recombination_rate=1e-8) 13 | ts.dump('to_annotate.trees') 14 | return 0 15 | " 16 | 17 | SETUP=" 18 | import pyslim, tskit 19 | ts = tskit.load('to_annotate.trees') 20 | 21 | def pyslim_fn(ts): 22 | tables = ts.tables 23 | pyslim.annotate_defaults_tables(tables, model_type='WF', slim_generation=1) 24 | return 0 25 | 26 | def tskit_fn(ts): 27 | tables = ts.tables 28 | dmd = {} 29 | for k in ('node', 'individual', 'population'): 30 | md = pyslim.default_slim_metadata(k) 31 | ms = pyslim.slim_metadata_schemas[k] 32 | dmd[k] = ms.validate_and_encode_row(md) 33 | 34 | pop_md = [b'' for _ in tables.populations] 35 | for p in set(tables.nodes.population): 36 | pop_md[p] = dmd['population'] 37 | tables.populations.packset_metadata(pop_md) 38 | 39 | node_md = [b'' if (n.flags & 1) else dmd['node'] for n in tables.nodes] 40 | tables.nodes.packset_metadata(node_md) 41 | 42 | ind_md = [dmd['individual']] * tables.individuals.num_rows 43 | tables.individuals.packset_metadata(ind_md) 44 | return 0 45 | 46 | " 47 | echo "setup:" 48 | python3 -m timeit -s "$SETUP_SETUP" "setup()" 49 | 50 | echo "tskit:" 51 | python3 -m timeit -s "$SETUP" "tskit_fn(ts)" 52 | 53 | echo "pyslim:" 54 | python3 -m timeit -s "$SETUP" "pyslim_fn(ts)" 55 | -------------------------------------------------------------------------------- /tests/test_recipes/restart_and_remove_subpop_nonWF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | // as well as any bespoke TREES_FILE for output, you need to define: 6 | // TREES_IN = path to trees to initialise 7 | initializeSLiMModelType("nonWF"); 8 | initializeSLiMOptions(dimensionality="xy"); 9 | initializeTreeSeq(); 10 | initializeMutationRate(1e-2); 11 | initializeMutationType("m1", 0.5, "f", -0.1); 12 | initializeGenomicElementType("g1", m1, 1.0); 13 | initializeGenomicElement(g1, 0, 99); 14 | initializeRecombinationRate(1e-2); 15 | if (!exists("SUBPOP_MAP")) defineConstant("SUBPOP_MAP", NULL); 16 | } 17 | 18 | 1 early() { 19 | if (STAGE == "early") { 20 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 21 | community.rescheduleScriptBlock(s1, community.tick + 1); 22 | community.rescheduleScriptBlock(s2, community.tick + 10); 23 | } 24 | } 25 | 26 | 1 late() { 27 | if (STAGE == "late") { 28 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 29 | community.rescheduleScriptBlock(s1, ticks=community.tick + 2); 30 | community.rescheduleScriptBlock(s2, ticks=community.tick + 10); 31 | } 32 | } 33 | 34 | s1 10 early() { 35 | old_pops = sim.subpopulations; 36 | p = sim.addSubpop("p0", 0); 37 | p.takeMigrants(old_pops.individuals); 38 | old_pops.removeSubpopulation(); 39 | } 40 | 41 | s2 20 early() { 42 | catn("Done."); 43 | sim.treeSeqOutput(TREES_FILE); 44 | sim.simulationFinished(); 45 | } 46 | -------------------------------------------------------------------------------- /tests/test_recipes/restart_msprime.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | // as well as any bespoke TREES_FILE for output, you need to define: 6 | // TREES_IN = path to trees to initialise 7 | // L = sequence length 8 | // SEX = A, X, Y or not defined 9 | // WF = T or F 10 | if (WF) { 11 | initializeSLiMModelType("WF"); 12 | } else { 13 | initializeSLiMModelType("nonWF"); 14 | } 15 | initializeTreeSeq(timeUnit=WF ? "generations" else "ticks"); 16 | initializeMutationRate(1/L); 17 | initializeMutationType("m0", 0.5, "f", 0.0); 18 | initializeMutationType("m1", 0.5, "f", -0.1); 19 | initializeMutationType("m2", 0.5, "f", 0.0); 20 | initializeGenomicElementType("g1", m1, 1.0); 21 | initializeGenomicElement(g1, 0, L-1); 22 | initializeRecombinationRate(1/L); 23 | if (exists("SEX")) { 24 | catn("SEX: " + SEX); 25 | initializeSex(SEX); 26 | } 27 | if (!exists("SUBPOP_MAP")) defineConstant("SUBPOP_MAP", NULL); 28 | } 29 | 30 | // output immediately! Nothing should have changed. 31 | 1 early() { 32 | if (STAGE == "early") { 33 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 34 | sim.treeSeqOutput(TREES_FILE, simplify=F); 35 | } 36 | } 37 | 1 late() { 38 | if (STAGE == "late") { 39 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 40 | sim.treeSeqOutput(TREES_FILE, simplify=F); 41 | } 42 | } 43 | 44 | 20 early() { 45 | catn("Done."); 46 | sim.simulationFinished(); 47 | } 48 | -------------------------------------------------------------------------------- /tests/test_recipes/restart_nucleotides_WF_chromosomes.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(25); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | // as well as any bespoke TREES_FILE for output, you need to define: 6 | // TREES_IN = path to trees to initialise 7 | defineConstant("L", 1e2); 8 | initializeSLiMOptions(keepPedigrees=T, nucleotideBased=T); 9 | initializeSex(); 10 | initializeTreeSeq(timeUnit="generations"); 11 | initializeMutationTypeNuc("m1", 0.5, "f", 0.0); 12 | initializeMutationType("m2", 0.5, "n", 0.0, 0.1); 13 | initializeGenomicElementType("g1", m1, 1.0, mmJukesCantor(4e-2)); 14 | if (!exists("SUBPOP_MAP")) defineConstant("SUBPOP_MAP", NULL); 15 | 16 | types = c("A", "X", "Y", "H", "Z", "W", "HF", "FL", "HM", "ML", "-Y"); 17 | symbols = c("A", "X", "Y", "H", "Z", "W", "HF", "FL", "HM", "ML", "nY"); 18 | ids = 1 + seqAlong(types); 19 | length = 1e4; 20 | 21 | for (id in ids, symbol in symbols, type in types) 22 | { 23 | initializeChromosome(id, length, type, symbol); 24 | initializeAncestralNucleotides(paste0(rep("A", length))); // UNUSED 25 | initializeRecombinationRate(1e-5); 26 | initializeGenomicElement(g1, 0, length-1); 27 | } 28 | } 29 | 30 | 1 late() { 31 | // output immediately! Nothing should have changed. 32 | md = treeSeqMetadata(TREES_IN, userData=F).getValue("SLiM").getValue("user_metadata"); 33 | sim.readFromPopulationFile(TREES_IN, subpopMap=SUBPOP_MAP); 34 | sim.treeSeqOutput(TREES_FILE, simplify=F, metadata=md); 35 | } 36 | 37 | 2 early() { 38 | catn("Done."); 39 | sim.simulationFinished(); 40 | } 41 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | # Book settings 2 | # Learn more at https://jupyterbook.org/customize/config.html 3 | 4 | title: PySLiM manual 5 | author: Tskit Developers 6 | copyright: "2021" 7 | only_build_toc_files: true 8 | # logo: logo.png 9 | favicon: favicon.ico 10 | 11 | execute: 12 | execute_notebooks: cache 13 | timeout: 300 14 | 15 | repository: 16 | url: https://github.com/tskit-dev/pyslim 17 | branch: main 18 | path_to_book: docs 19 | 20 | html: 21 | use_issues_button: true 22 | use_repository_button: true 23 | use_edit_page_button: true 24 | 25 | sphinx: 26 | extra_extensions: 27 | - sphinx_copybutton 28 | - sphinx.ext.autodoc 29 | - sphinx.ext.autosummary 30 | - sphinx.ext.todo 31 | - sphinx.ext.viewcode 32 | - sphinx.ext.intersphinx 33 | - sphinx_issues 34 | - sphinxarg.ext 35 | - IPython.sphinxext.ipython_console_highlighting 36 | 37 | config: 38 | html_theme: sphinx_book_theme 39 | html_theme_options: 40 | pygments_dark_style: monokai 41 | navigation_with_keys: false 42 | logo: 43 | text: | 44 | pyslim
45 | version __PYSLIM_VERSION__ 46 | issues_github_path: tskit-dev/pyslim 47 | todo_include_todos: true 48 | intersphinx_mapping: 49 | python: ["https://docs.python.org/3/", null] 50 | tskit: ["https://tskit.dev/tskit/docs/stable", null] 51 | msprime: ["https://tskit.dev/msprime/docs/stable", null] 52 | tutorials: ["https://tskit.dev/tutorials/", null] 53 | stdpopsim: ["https://popsim-consortium.github.io/stdpopsim-docs/stable", null] 54 | numpy: ["https://numpy.org/doc/stable/", null] 55 | myst_enable_extensions: 56 | - colon_fence 57 | - deflist 58 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.4 - Detecting the dip in diversity (analyzing tree heights in Python) II.py: -------------------------------------------------------------------------------- 1 | # Keywords: Python, tree-sequence recording, tree sequence recording 2 | 3 | # This is a Python recipe; note that it runs the SLiM model internally, below 4 | 5 | import subprocess, tskit 6 | import matplotlib.pyplot as plt 7 | import numpy as np 8 | 9 | # Run the SLiM model and load the resulting .trees 10 | # subprocess.check_output(["slim", "-m", "-s", "0", "./recipe_17.4.slim"]) 11 | ts = tskit.load("./recipe_17.4.trees") 12 | ts = ts.simplify() 13 | 14 | # Measure the tree height at each base position 15 | height_for_pos = np.zeros(int(ts.sequence_length)) 16 | for tree in ts.trees(): 17 | mean_height = np.mean([tree.time(root) for root in tree.roots]) 18 | left, right = map(int, tree.interval) 19 | height_for_pos[left: right] = mean_height 20 | 21 | # Convert heights along chromosome into heights at distances from gene 22 | height_for_pos = height_for_pos - np.min(height_for_pos) 23 | L, L0, L1 = int(1e8), int(200e3), int(1e3) # total length, length between genes, gene length 24 | gene_starts = np.arange(L0, L - (L0 + L1) + 1, L0 + L1) 25 | gene_ends = gene_starts + L1 - 1 26 | max_d = L0 // 4 27 | height_for_left_dist = np.zeros(max_d) 28 | height_for_right_dist = np.zeros(max_d) 29 | for d in range(max_d): 30 | height_for_left_dist[d] = np.mean(height_for_pos[gene_starts - d - 1]) 31 | height_for_right_dist[d] = np.mean(height_for_pos[gene_ends + d + 1]) 32 | height_for_distance = np.hstack([height_for_left_dist[::-1], height_for_right_dist]) 33 | distances = np.hstack([np.arange(-max_d, 0), np.arange(1, max_d + 1)]) 34 | 35 | # Make a simple plot 36 | plt.plot(distances, height_for_distance) 37 | # plt.show() 38 | plt.savefig("recipe_17.4.png") 39 | -------------------------------------------------------------------------------- /tests/extra_recipes/Recipe 17.9 - Starting a sexual nonWF model with a coalescent history I.py: -------------------------------------------------------------------------------- 1 | # Keywords: Python, nonWF, non-Wright-Fisher, tree-sequence recording, tree sequence recording 2 | 3 | import msprime, pyslim, random 4 | import numpy as np 5 | 6 | ts = msprime.sim_ancestry(samples=5000, population_size=5000, sequence_length=1e8, recombination_rate=1e-8) 7 | 8 | tables = ts.dump_tables() 9 | pyslim.annotate_tables(tables, model_type="nonWF", tick=1) 10 | 11 | # add sexes and ages 12 | individual_metadata = [ind.metadata for ind in tables.individuals] 13 | for md in individual_metadata: 14 | md["sex"] = random.choice([pyslim.INDIVIDUAL_TYPE_FEMALE, pyslim.INDIVIDUAL_TYPE_MALE]) 15 | md["age"] = random.choice([0, 1, 2, 3, 4]) 16 | 17 | ims = tables.individuals.metadata_schema 18 | tables.individuals.packset_metadata( 19 | [ims.validate_and_encode_row(md) for md in individual_metadata]) 20 | 21 | # add selected mutation 22 | mut_ind_id = random.choice(range(tables.individuals.num_rows)) 23 | mut_node_id = random.choice(np.where(tables.nodes.individual == mut_ind_id)[0]) 24 | mut_node = tables.nodes[mut_node_id] 25 | mut_metadata = { 26 | "mutation_list": [ 27 | { 28 | "mutation_type": 2, 29 | "selection_coeff": 0.1, 30 | "subpopulation": mut_node.population, 31 | "slim_time": int(tables.metadata['SLiM']['tick'] - mut_node.time), 32 | "nucleotide": -1 33 | } 34 | ] 35 | } 36 | site_num = tables.sites.add_row(position=5000, ancestral_state='') 37 | tables.mutations.add_row( 38 | node=mut_node_id, 39 | site=site_num, 40 | derived_state='1', 41 | time=mut_node.time, 42 | metadata=mut_metadata) 43 | 44 | slim_ts = tables.tree_sequence() 45 | slim_ts.dump("recipe_17.9.trees") 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pyslim 2 | 3 | [![License](https://img.shields.io/github/license/tskit-dev/pyslim)](https://github.com/tskit-dev/pyslim/blob/main/LICENSE) [![PyPI version](https://img.shields.io/pypi/v/pyslim.svg)](https://pypi.org/project/pyslim/) [![Supported Python Versions](https://img.shields.io/pypi/pyversions/pyslim.svg)](https://pypi.org/project/pyslim/) [![Docs Build](https://github.com/tskit-dev/pyslim/actions/workflows/docs.yml/badge.svg)](https://github.com/tskit-dev/pyslim/actions/workflows/docs.yml) [![Tests](https://github.com/tskit-dev/pyslim/actions/workflows/tests.yml/badge.svg)](https://github.com/tskit-dev/pyslim/actions/workflows/tests.yml) [![codecov](https://codecov.io/gh/tskit-dev/pyslim/branch/main/graph/badge.svg)](https://codecov.io/gh/tskit-dev/pyslim) 4 | 5 | `pyslim` is a python module that provides a few extra tools for dealing with tree sequences 6 | produced by SLiM and for preparing other tree sequences for use with SLiM. 7 | Most tree sequence functionality is provided by [tskit](https://tskit.dev/tskit). 8 | Please see [our documentation](https://tskit.dev/pyslim/docs/stable/) ([latest](https://tskit.dev/pyslim/docs/latest/)) for more information. 9 | (That link is to documentation for the last release; 10 | instead, [the latest](https://tskit.dev/pyslim/docs/latest) documentation 11 | may have additional examples, but may also describe features you need to install from github to get.) 12 | 13 | ## Installation 14 | 15 | To install `pyslim`, do 16 | ``` 17 | pip install pyslim 18 | ``` 19 | or read the documentation for how to [install from source](https://tskit.dev/pyslim/docs/stable/development.html#sec-development). 20 | 21 | Alternatively, install from conda-forge: 22 | 23 | ``` 24 | conda install -c conda-forge pyslim 25 | ``` 26 | 27 | ## Quickstart 28 | 29 | See tutorials and examples at https://tskit.dev/pyslim/docs/stable/ 30 | -------------------------------------------------------------------------------- /tests/test_recipes/restart_multispecies_WF.slim: -------------------------------------------------------------------------------- 1 | // as well as any bespoke TREES_FILE for output, you need to define: 2 | // TREES_IN = (dictionary with values = paths to trees to initialise) 3 | 4 | species all initialize() 5 | { 6 | setSeed(23); 7 | initializeSLiMModelType("WF"); 8 | } 9 | 10 | species fox initialize() 11 | { 12 | if (!exists("TREES_FILE_fox")) 13 | defineGlobal("TREES_FILE_fox", "fox_out.trees"); 14 | initializeTreeSeq(); 15 | initializeMutationRate(1e-2); 16 | initializeMutationType("m1", 0.5, "f", -0.1); 17 | initializeGenomicElementType("g1", m1, 1.0); 18 | initializeGenomicElement(g1, 0, 99); 19 | initializeRecombinationRate(1e-2); 20 | if (!exists("SUBPOP_MAP")) 21 | defineConstant("SUBPOP_MAP", Dictionary()); 22 | } 23 | 24 | species mouse initialize() 25 | { 26 | if (!exists("TREES_FILE_mouse")) 27 | defineGlobal("TREES_FILE_mouse", "mouse_out.trees"); 28 | initializeTreeSeq(); 29 | initializeMutationRate(1e-2); 30 | initializeMutationType("m2", 0.5, "f", -0.1); 31 | initializeGenomicElementType("g2", m2, 1.0); 32 | initializeGenomicElement(g2, 0, 999); 33 | initializeRecombinationRate(1e-2); 34 | } 35 | 36 | // output immediately! Nothing should have changed. 37 | ticks all 1 early() { 38 | if (STAGE == "early") { 39 | for (sp in community.allSpecies) { 40 | sp.readFromPopulationFile(TREES_IN.getValue(sp.name), subpopMap=SUBPOP_MAP.getValue(sp.name)); 41 | sp.treeSeqOutput(executeLambda("TREES_FILE_" + sp.name + ";"), simplify=F); 42 | } 43 | } 44 | } 45 | ticks all 1 late() { 46 | if (STAGE == "late") { 47 | for (sp in community.allSpecies) { 48 | sp.readFromPopulationFile(TREES_IN.getValue(sp.name), subpopMap=SUBPOP_MAP.getValue(sp.name)); 49 | sp.treeSeqOutput(executeLambda("TREES_FILE_" + sp.name + ";"), simplify=F); 50 | } 51 | } 52 | } 53 | 54 | ticks all 20 early() { 55 | catn("Done."); 56 | community.simulationFinished(); 57 | } 58 | -------------------------------------------------------------------------------- /tests/test_recipes/restart_multispecies_nonWF.slim: -------------------------------------------------------------------------------- 1 | // as well as any bespoke TREES_FILE for output, you need to define: 2 | // TREES_IN = (dictionary with values = paths to trees to initialise) 3 | 4 | species all initialize() 5 | { 6 | setSeed(23); 7 | initializeSLiMModelType("nonWF"); 8 | } 9 | 10 | species fox initialize() 11 | { 12 | if (!exists("TREES_FILE_fox")) 13 | defineGlobal("TREES_FILE_fox", "fox_out.trees"); 14 | initializeTreeSeq(); 15 | initializeMutationRate(1e-2); 16 | initializeMutationType("m1", 0.5, "f", -0.1); 17 | initializeGenomicElementType("g1", m1, 1.0); 18 | initializeGenomicElement(g1, 0, 99); 19 | initializeRecombinationRate(1e-2); 20 | if (!exists("SUBPOP_MAP")) 21 | defineConstant("SUBPOP_MAP", Dictionary()); 22 | } 23 | 24 | species mouse initialize() 25 | { 26 | if (!exists("TREES_FILE_mouse")) 27 | defineGlobal("TREES_FILE_mouse", "mouse_out.trees"); 28 | initializeTreeSeq(); 29 | initializeMutationRate(1e-2); 30 | initializeMutationType("m2", 0.5, "f", -0.1); 31 | initializeGenomicElementType("g2", m2, 1.0); 32 | initializeGenomicElement(g2, 0, 999); 33 | initializeRecombinationRate(1e-2); 34 | } 35 | 36 | // output immediately! Nothing should have changed. 37 | ticks all 1 early() { 38 | if (STAGE == "early") { 39 | for (sp in community.allSpecies) { 40 | sp.readFromPopulationFile(TREES_IN.getValue(sp.name), subpopMap=SUBPOP_MAP.getValue(sp.name)); 41 | sp.treeSeqOutput(executeLambda("TREES_FILE_" + sp.name + ";"), simplify=F); 42 | } 43 | } 44 | } 45 | ticks all 1 late() { 46 | if (STAGE == "late") { 47 | for (sp in community.allSpecies) { 48 | sp.readFromPopulationFile(TREES_IN.getValue(sp.name), subpopMap=SUBPOP_MAP.getValue(sp.name)); 49 | sp.treeSeqOutput(executeLambda("TREES_FILE_" + sp.name + ";"), simplify=F); 50 | } 51 | } 52 | } 53 | 54 | ticks all 20 early() { 55 | catn("Done."); 56 | community.simulationFinished(); 57 | } 58 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_mutation_spectrum.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | defineConstant("L", 100); 5 | if (!exists("TREES_FILE")) 6 | defineGlobal("TREES_FILE", "out.trees"); 7 | if (!exists("MUTATIONS_FILE")) 8 | defineGlobal("MUTATIONS_FILE", "out_mutations.json"); 9 | initializeSLiMOptions(nucleotideBased=T); 10 | initializeTreeSeq(); 11 | initializeAncestralNucleotides(randomNucleotides(L)); 12 | initializeMutationTypeNuc("m1", 0.5, "f", 0.0); 13 | initializeGenomicElementType("g1", m1, 1.0, mmJukesCantor(1e-3)); 14 | initializeGenomicElement(g1, 0, L - 1); 15 | initializeRecombinationRate(1e-6); 16 | defineGlobal("M", Dictionary()); 17 | for (a in c("A", "C", "G", "T")) 18 | for (b in c("A", "C", "G", "T")) 19 | for (c in c("A", "C", "G", "T")) 20 | for (d in c("A", "C", "G", "T")) 21 | M.setValue(a+b+c+","+d, 0); 22 | } 23 | 24 | // record mutation spectrum 25 | mutation(NULL) 26 | { 27 | if (mut.position > 0 & mut.position < L - 1) { 28 | context = substr(REFSEQ, mut.position - 1, mut.position + 1); 29 | for (k in 0:2) { 30 | mut_k = which(haplosome.mutations.position == mut.position + k - 1); 31 | if (length(mut_k) > 0) { 32 | muts = haplosome.mutations[mut_k]; 33 | parent_mut = muts[whichMax(muts.originTick)]; 34 | context = ( 35 | substr(context, 0, k-1) 36 | + parent_mut.nucleotide 37 | + substr(context, k + 1, 2) 38 | ); 39 | } 40 | } 41 | M.setValue(context + "," + mut.nucleotide, M.getValue(context + "," + mut.nucleotide) + 1); 42 | } 43 | return T; 44 | } 45 | 46 | 1 early() 47 | { 48 | sim.addSubpop("p1", 100); 49 | sim.treeSeqRememberIndividuals(p1.individuals); 50 | defineConstant("REFSEQ", sim.chromosome.ancestralNucleotides()); 51 | } 52 | 53 | 1: late() 54 | { 55 | sim.treeSeqRememberIndividuals(p1.individuals); 56 | } 57 | 58 | 10 late() 59 | { 60 | sim.treeSeqOutput(TREES_FILE); 61 | writeFile(MUTATIONS_FILE, M.serialize(format="json")); 62 | catn("Done."); 63 | sim.simulationFinished(); 64 | } 65 | -------------------------------------------------------------------------------- /docs/vignette_space.slim: -------------------------------------------------------------------------------- 1 | initialize() { 2 | initializeSLiMModelType("nonWF"); 3 | initializeSLiMOptions(dimensionality="xy"); 4 | initializeTreeSeq(); 5 | initializeMutationRate(0.0); 6 | initializeMutationType("m1", 0.5, "f", 0.0); 7 | initializeGenomicElementType("g1", m1, 1.0); 8 | initializeGenomicElement(g1, 0, 1e8-1); 9 | initializeRecombinationRate(1e-8); 10 | 11 | defineConstant("LAMBDA", 2.0); // birth rate 12 | defineConstant("K", 1); // carrying capacity per unit area 13 | defineConstant("W", 35); // width and height of the area 14 | defineConstant("MU", 0.5); // death rate 15 | defineConstant("SIGMA", 1.0); // interaction distance 16 | 17 | // spatial interaction for local competition 18 | initializeInteractionType("i1", "xy", reciprocal=T, 19 | maxDistance = 3 * SIGMA); 20 | i1.setInteractionFunction("n", 1.0/(2*PI*SIGMA^2), SIGMA); 21 | } 22 | 23 | reproduction() { 24 | neighbor_density = i1.localPopulationDensity(individual); 25 | num_offspring = rpois(1, LAMBDA / (1 + neighbor_density / K)); 26 | mate = i1.drawByStrength(individual, 1); // single mating 27 | if (size(mate) > 0) { 28 | for (k in seqLen(num_offspring)) { 29 | offspring = p1.addCrossed(individual, mate); 30 | pos = individual.spatialPosition + rnorm(2, 0, SIGMA); 31 | offspring.setSpatialPosition(p1.pointReflected(pos)); 32 | } 33 | } 34 | } 35 | 36 | 1 early() { 37 | sim.addSubpop("p1", K * W * W); 38 | p1.setSpatialBounds(c(0.0, 0.0, W, W)); 39 | for (ind in p1.individuals) { 40 | ind.setSpatialPosition(p1.pointUniform()); 41 | } 42 | } 43 | 44 | early() { // survival probabilities 45 | p1.fitnessScaling = 1 - MU; 46 | } 47 | 48 | late() { 49 | i1.evaluate(sim.subpopulations); 50 | } 51 | 52 | 1000 late() { 53 | sim.treeSeqRememberIndividuals(p1.individuals); 54 | } 55 | 56 | 2000 late() { 57 | sim.treeSeqOutput("spatial_sim.trees"); 58 | catn("Done."); 59 | sim.simulationFinished(); 60 | } 61 | 62 | -------------------------------------------------------------------------------- /docs/development.md: -------------------------------------------------------------------------------- 1 | --- 2 | jupytext: 3 | text_representation: 4 | extension: .md 5 | format_name: myst 6 | format_version: 0.12 7 | jupytext_version: 1.9.1 8 | kernelspec: 9 | display_name: Python 3 10 | language: python 11 | name: python3 12 | --- 13 | 14 | (sec_development)= 15 | 16 | # Development 17 | 18 | 19 | To install a particular version of ``pyslim`` from source, e.g., to obtain a recent update: 20 | 21 | ```bash 22 | git clone https://github.com/tskit-dev/pyslim.git 23 | cd pyslim 24 | python -m pip install -e ".[dev]" 25 | ``` 26 | 27 | 28 | Then, to run the tests to make sure everything is working, do: 29 | 30 | ```bash 31 | python -m pytest tests 32 | ``` 33 | 34 | *Note:* if you use ``python3`` you may need to replace ``python`` with ``python3`` above. 35 | 36 | If you would like to add some features to ``pyslim``, please read the 37 | following. If you think there is anything missing, 38 | please open an [issue](http://github.com/tskit-dev/pyslim/issues) or 39 | [pull request](http://github.com/tskit-dev/pyslim/pulls) on GitHub! 40 | 41 | ## Quickstart 42 | 43 | - Make your own fork of the pyslim repo on [GitHub](http://github.com/tskit-dev/pyslim) 44 | - Clone your fork into a local directory: 45 | 46 | ```bash 47 | git clone git@github.com:YOUR_GITHUB/pyslim.git 48 | ``` 49 | 50 | - Install the development requirements using 51 | ``python3 -m pip install -e ".[dev]"``. 52 | - Run the tests to ensure everything has worked: ``python3 -m pytest tests``. These should 53 | all pass. 54 | - Make your changes in a local branch, and open a pull request on GitHub when you 55 | are ready. Please make sure that (a) the tests pass before you open the pull request; and 56 | (b) your code passes PEP8 checks before opening the pull request. 57 | 58 | For a more detailed walkthrough of development methods, 59 | see [the stdpopsim documentation](https://popsim-consortium.github.io/stdpopsim-docs/latest/development.html#github-workflow) 60 | and/or [the tskit documentation](https://tskit.dev/tskit/docs/latest/development.html#workflow). 61 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | } 14 | 15 | 1 early() { 16 | sim.addSubpop("p1", 10); 17 | } 18 | 19 | 10 late() { 20 | sim.treeSeqOutput(TREES_FILE); 21 | catn("Done."); 22 | sim.simulationFinished(); 23 | } 24 | 25 | // PEDIGREE OUTPUT 26 | 1 first() { 27 | writeFile(PEDIGREE_FILE, 28 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 29 | sep="\t")); 30 | } 31 | 32 | 1: first() { 33 | for (pop in sim.subpopulations) { 34 | for (ind in pop.individuals) { 35 | age = community.modelType == "nonWF" ? ind.age else -1; 36 | writeFile(PEDIGREE_FILE, 37 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 38 | sep='\t'), 39 | append=T); 40 | } 41 | } 42 | } 43 | 44 | 1: early() { 45 | for (pop in sim.subpopulations) { 46 | for (ind in pop.individuals) { 47 | age = community.modelType == "nonWF" ? ind.age else -1; 48 | writeFile(PEDIGREE_FILE, 49 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 50 | sep='\t'), 51 | append=T); 52 | } 53 | } 54 | } 55 | 56 | 1: late() { 57 | for (pop in sim.subpopulations) { 58 | for (ind in pop.individuals) { 59 | age = community.modelType == "nonWF" ? ind.age else -1; 60 | writeFile(PEDIGREE_FILE, 61 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 62 | sep='\t'), 63 | append=T); 64 | } 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_early_late.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | } 14 | 15 | 1 early() { 16 | sim.addSubpop("p1", 10); 17 | } 18 | 19 | 10 late() { 20 | sim.treeSeqOutput(TREES_FILE); 21 | catn("Done."); 22 | sim.simulationFinished(); 23 | } 24 | 25 | // PEDIGREE OUTPUT 26 | 1 first() { 27 | writeFile(PEDIGREE_FILE, 28 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 29 | sep="\t")); 30 | } 31 | 32 | 1: first() { 33 | for (pop in sim.subpopulations) { 34 | for (ind in pop.individuals) { 35 | age = community.modelType == "nonWF" ? ind.age else -1; 36 | writeFile(PEDIGREE_FILE, 37 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 38 | sep='\t'), 39 | append=T); 40 | } 41 | } 42 | } 43 | 44 | 1: early() { 45 | for (pop in sim.subpopulations) { 46 | for (ind in pop.individuals) { 47 | age = community.modelType == "nonWF" ? ind.age else -1; 48 | writeFile(PEDIGREE_FILE, 49 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 50 | sep='\t'), 51 | append=T); 52 | } 53 | } 54 | } 55 | 56 | 1: late() { 57 | for (pop in sim.subpopulations) { 58 | for (ind in pop.individuals) { 59 | age = community.modelType == "nonWF" ? ind.age else -1; 60 | writeFile(PEDIGREE_FILE, 61 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 62 | sep='\t'), 63 | append=T); 64 | } 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_first_late.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | } 14 | 15 | 1 first() { 16 | sim.addSubpop("p1", 10); 17 | } 18 | 19 | 10 late() { 20 | sim.treeSeqOutput(TREES_FILE); 21 | catn("Done."); 22 | sim.simulationFinished(); 23 | } 24 | 25 | // PEDIGREE OUTPUT 26 | 1 first() { 27 | writeFile(PEDIGREE_FILE, 28 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 29 | sep="\t")); 30 | } 31 | 32 | 1: first() { 33 | for (pop in sim.subpopulations) { 34 | for (ind in pop.individuals) { 35 | age = community.modelType == "nonWF" ? ind.age else -1; 36 | writeFile(PEDIGREE_FILE, 37 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 38 | sep='\t'), 39 | append=T); 40 | } 41 | } 42 | } 43 | 44 | 1: early() { 45 | for (pop in sim.subpopulations) { 46 | for (ind in pop.individuals) { 47 | age = community.modelType == "nonWF" ? ind.age else -1; 48 | writeFile(PEDIGREE_FILE, 49 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 50 | sep='\t'), 51 | append=T); 52 | } 53 | } 54 | } 55 | 56 | 1: late() { 57 | for (pop in sim.subpopulations) { 58 | for (ind in pop.individuals) { 59 | age = community.modelType == "nonWF" ? ind.age else -1; 60 | writeFile(PEDIGREE_FILE, 61 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 62 | sep='\t'), 63 | append=T); 64 | } 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_late_early.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | } 14 | 15 | 1 late() { 16 | sim.addSubpop("p1", 10); 17 | } 18 | 19 | 10 early() { 20 | sim.treeSeqOutput(TREES_FILE); 21 | catn("Done."); 22 | sim.simulationFinished(); 23 | } 24 | 25 | // PEDIGREE OUTPUT 26 | 1 first() { 27 | writeFile(PEDIGREE_FILE, 28 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 29 | sep="\t")); 30 | } 31 | 32 | 1: first() { 33 | for (pop in sim.subpopulations) { 34 | for (ind in pop.individuals) { 35 | age = community.modelType == "nonWF" ? ind.age else -1; 36 | writeFile(PEDIGREE_FILE, 37 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 38 | sep='\t'), 39 | append=T); 40 | } 41 | } 42 | } 43 | 44 | 1: early() { 45 | for (pop in sim.subpopulations) { 46 | for (ind in pop.individuals) { 47 | age = community.modelType == "nonWF" ? ind.age else -1; 48 | writeFile(PEDIGREE_FILE, 49 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 50 | sep='\t'), 51 | append=T); 52 | } 53 | } 54 | } 55 | 56 | 1: late() { 57 | for (pop in sim.subpopulations) { 58 | for (ind in pop.individuals) { 59 | age = community.modelType == "nonWF" ? ind.age else -1; 60 | writeFile(PEDIGREE_FILE, 61 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 62 | sep='\t'), 63 | append=T); 64 | } 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_late_first.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | } 14 | 15 | 1 late() { 16 | sim.addSubpop("p1", 10); 17 | } 18 | 19 | 10 first() { 20 | sim.treeSeqOutput(TREES_FILE); 21 | catn("Done."); 22 | sim.simulationFinished(); 23 | } 24 | 25 | // PEDIGREE OUTPUT 26 | 1 first() { 27 | writeFile(PEDIGREE_FILE, 28 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 29 | sep="\t")); 30 | } 31 | 32 | 1: first() { 33 | for (pop in sim.subpopulations) { 34 | for (ind in pop.individuals) { 35 | age = community.modelType == "nonWF" ? ind.age else -1; 36 | writeFile(PEDIGREE_FILE, 37 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 38 | sep='\t'), 39 | append=T); 40 | } 41 | } 42 | } 43 | 44 | 1: early() { 45 | for (pop in sim.subpopulations) { 46 | for (ind in pop.individuals) { 47 | age = community.modelType == "nonWF" ? ind.age else -1; 48 | writeFile(PEDIGREE_FILE, 49 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 50 | sep='\t'), 51 | append=T); 52 | } 53 | } 54 | } 55 | 56 | 1: late() { 57 | for (pop in sim.subpopulations) { 58 | for (ind in pop.individuals) { 59 | age = community.modelType == "nonWF" ? ind.age else -1; 60 | writeFile(PEDIGREE_FILE, 61 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 62 | sep='\t'), 63 | append=T); 64 | } 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_late_late.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | } 14 | 15 | 1 late() { 16 | sim.addSubpop("p1", 10); 17 | } 18 | 19 | 10 late() { 20 | sim.treeSeqOutput(TREES_FILE); 21 | catn("Done."); 22 | sim.simulationFinished(); 23 | } 24 | 25 | // PEDIGREE OUTPUT 26 | 1 first() { 27 | writeFile(PEDIGREE_FILE, 28 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 29 | sep="\t")); 30 | } 31 | 32 | 1: first() { 33 | for (pop in sim.subpopulations) { 34 | for (ind in pop.individuals) { 35 | age = community.modelType == "nonWF" ? ind.age else -1; 36 | writeFile(PEDIGREE_FILE, 37 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 38 | sep='\t'), 39 | append=T); 40 | } 41 | } 42 | } 43 | 44 | 1: early() { 45 | for (pop in sim.subpopulations) { 46 | for (ind in pop.individuals) { 47 | age = community.modelType == "nonWF" ? ind.age else -1; 48 | writeFile(PEDIGREE_FILE, 49 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 50 | sep='\t'), 51 | append=T); 52 | } 53 | } 54 | } 55 | 56 | 1: late() { 57 | for (pop in sim.subpopulations) { 58 | for (ind in pop.individuals) { 59 | age = community.modelType == "nonWF" ? ind.age else -1; 60 | writeFile(PEDIGREE_FILE, 61 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 62 | sep='\t'), 63 | append=T); 64 | } 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_early_early.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | } 14 | 15 | 1 early() { 16 | sim.addSubpop("p1", 10); 17 | } 18 | 19 | 10 early() { 20 | sim.treeSeqOutput(TREES_FILE); 21 | catn("Done."); 22 | sim.simulationFinished(); 23 | } 24 | 25 | // PEDIGREE OUTPUT 26 | 1 first() { 27 | writeFile(PEDIGREE_FILE, 28 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 29 | sep="\t")); 30 | } 31 | 32 | 1: first() { 33 | for (pop in sim.subpopulations) { 34 | for (ind in pop.individuals) { 35 | age = community.modelType == "nonWF" ? ind.age else -1; 36 | writeFile(PEDIGREE_FILE, 37 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 38 | sep='\t'), 39 | append=T); 40 | } 41 | } 42 | } 43 | 44 | 1: early() { 45 | for (pop in sim.subpopulations) { 46 | for (ind in pop.individuals) { 47 | age = community.modelType == "nonWF" ? ind.age else -1; 48 | writeFile(PEDIGREE_FILE, 49 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 50 | sep='\t'), 51 | append=T); 52 | } 53 | } 54 | } 55 | 56 | 1: late() { 57 | for (pop in sim.subpopulations) { 58 | for (ind in pop.individuals) { 59 | age = community.modelType == "nonWF" ? ind.age else -1; 60 | writeFile(PEDIGREE_FILE, 61 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 62 | sep='\t'), 63 | append=T); 64 | } 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_early_first.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | } 14 | 15 | 1 early() { 16 | sim.addSubpop("p1", 10); 17 | } 18 | 19 | 10 first() { 20 | sim.treeSeqOutput(TREES_FILE); 21 | catn("Done."); 22 | sim.simulationFinished(); 23 | } 24 | 25 | // PEDIGREE OUTPUT 26 | 1 first() { 27 | writeFile(PEDIGREE_FILE, 28 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 29 | sep="\t")); 30 | } 31 | 32 | 1: first() { 33 | for (pop in sim.subpopulations) { 34 | for (ind in pop.individuals) { 35 | age = community.modelType == "nonWF" ? ind.age else -1; 36 | writeFile(PEDIGREE_FILE, 37 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 38 | sep='\t'), 39 | append=T); 40 | } 41 | } 42 | } 43 | 44 | 1: early() { 45 | for (pop in sim.subpopulations) { 46 | for (ind in pop.individuals) { 47 | age = community.modelType == "nonWF" ? ind.age else -1; 48 | writeFile(PEDIGREE_FILE, 49 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 50 | sep='\t'), 51 | append=T); 52 | } 53 | } 54 | } 55 | 56 | 1: late() { 57 | for (pop in sim.subpopulations) { 58 | for (ind in pop.individuals) { 59 | age = community.modelType == "nonWF" ? ind.age else -1; 60 | writeFile(PEDIGREE_FILE, 61 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 62 | sep='\t'), 63 | append=T); 64 | } 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_first_early.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | } 14 | 15 | 1 first() { 16 | sim.addSubpop("p1", 10); 17 | } 18 | 19 | 10 early() { 20 | sim.treeSeqOutput(TREES_FILE); 21 | catn("Done."); 22 | sim.simulationFinished(); 23 | } 24 | 25 | // PEDIGREE OUTPUT 26 | 1 first() { 27 | writeFile(PEDIGREE_FILE, 28 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 29 | sep="\t")); 30 | } 31 | 32 | 1: first() { 33 | for (pop in sim.subpopulations) { 34 | for (ind in pop.individuals) { 35 | age = community.modelType == "nonWF" ? ind.age else -1; 36 | writeFile(PEDIGREE_FILE, 37 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 38 | sep='\t'), 39 | append=T); 40 | } 41 | } 42 | } 43 | 44 | 1: early() { 45 | for (pop in sim.subpopulations) { 46 | for (ind in pop.individuals) { 47 | age = community.modelType == "nonWF" ? ind.age else -1; 48 | writeFile(PEDIGREE_FILE, 49 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 50 | sep='\t'), 51 | append=T); 52 | } 53 | } 54 | } 55 | 56 | 1: late() { 57 | for (pop in sim.subpopulations) { 58 | for (ind in pop.individuals) { 59 | age = community.modelType == "nonWF" ? ind.age else -1; 60 | writeFile(PEDIGREE_FILE, 61 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 62 | sep='\t'), 63 | append=T); 64 | } 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_first_first.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | } 14 | 15 | 1 first() { 16 | sim.addSubpop("p1", 10); 17 | } 18 | 19 | 10 first() { 20 | sim.treeSeqOutput(TREES_FILE); 21 | catn("Done."); 22 | sim.simulationFinished(); 23 | } 24 | 25 | // PEDIGREE OUTPUT 26 | 1 first() { 27 | writeFile(PEDIGREE_FILE, 28 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 29 | sep="\t")); 30 | } 31 | 32 | 1: first() { 33 | for (pop in sim.subpopulations) { 34 | for (ind in pop.individuals) { 35 | age = community.modelType == "nonWF" ? ind.age else -1; 36 | writeFile(PEDIGREE_FILE, 37 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 38 | sep='\t'), 39 | append=T); 40 | } 41 | } 42 | } 43 | 44 | 1: early() { 45 | for (pop in sim.subpopulations) { 46 | for (ind in pop.individuals) { 47 | age = community.modelType == "nonWF" ? ind.age else -1; 48 | writeFile(PEDIGREE_FILE, 49 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 50 | sep='\t'), 51 | append=T); 52 | } 53 | } 54 | } 55 | 56 | 1: late() { 57 | for (pop in sim.subpopulations) { 58 | for (ind in pop.individuals) { 59 | age = community.modelType == "nonWF" ? ind.age else -1; 60 | writeFile(PEDIGREE_FILE, 61 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 62 | sep='\t'), 63 | append=T); 64 | } 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_roots.slim: -------------------------------------------------------------------------------- 1 | initialize() { 2 | setSeed(23); 3 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 4 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 5 | defineConstant("chromosome_length", 249250); 6 | initializeSLiMOptions(keepPedigrees=T); 7 | initializeTreeSeq(); 8 | initializeMutationRate(0); 9 | initializeMutationType("m1", 0.5, "f", 0); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, chromosome_length-1); 12 | initializeRecombinationRate(1e-8); 13 | } 14 | 15 | 1 early() { 16 | sim.addSubpop('p1', 1000); 17 | } 18 | 19 | 100 late() { 20 | sim.treeSeqOutput(TREES_FILE); 21 | catn("Done."); 22 | sim.simulationFinished(); 23 | } 24 | 25 | // PEDIGREE OUTPUT 26 | 1 first() { 27 | writeFile(PEDIGREE_FILE, 28 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 29 | sep="\t")); 30 | } 31 | 32 | 1: first() { 33 | for (pop in sim.subpopulations) { 34 | for (ind in pop.individuals) { 35 | age = community.modelType == "nonWF" ? ind.age else -1; 36 | writeFile(PEDIGREE_FILE, 37 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 38 | sep='\t'), 39 | append=T); 40 | } 41 | } 42 | } 43 | 44 | 1: early() { 45 | for (pop in sim.subpopulations) { 46 | for (ind in pop.individuals) { 47 | age = community.modelType == "nonWF" ? ind.age else -1; 48 | writeFile(PEDIGREE_FILE, 49 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 50 | sep='\t'), 51 | append=T); 52 | } 53 | } 54 | } 55 | 56 | 1: late() { 57 | for (pop in sim.subpopulations) { 58 | for (ind in pop.individuals) { 59 | age = community.modelType == "nonWF" ? ind.age else -1; 60 | writeFile(PEDIGREE_FILE, 61 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 62 | sep='\t'), 63 | append=T); 64 | } 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nucleotides_WF.slim: -------------------------------------------------------------------------------- 1 | // Based on Example 18.1 2 | 3 | initialize() { 4 | setSeed(23); 5 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 6 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 7 | defineConstant("L", 1e2); 8 | initializeSLiMOptions(keepPedigrees=T, nucleotideBased=T); 9 | initializeTreeSeq(timeUnit="generations"); 10 | initializeAncestralNucleotides(randomNucleotides(L)); 11 | initializeMutationTypeNuc("m1", 0.5, "f", 0.0); 12 | initializeGenomicElementType("g1", m1, 1.0, mmJukesCantor(4e-2)); 13 | initializeGenomicElement(g1, 0, L-1); 14 | initializeRecombinationRate(1e-2); 15 | } 16 | 17 | 1 early() { 18 | sim.addSubpop("p1", 10); 19 | } 20 | 21 | 10 late() { 22 | sim.treeSeqOutput(TREES_FILE); 23 | catn("Done."); 24 | sim.simulationFinished(); 25 | } 26 | 27 | // PEDIGREE OUTPUT 28 | 1 first() { 29 | writeFile(PEDIGREE_FILE, 30 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 31 | sep="\t")); 32 | } 33 | 34 | 1: first() { 35 | for (pop in sim.subpopulations) { 36 | for (ind in pop.individuals) { 37 | age = community.modelType == "nonWF" ? ind.age else -1; 38 | writeFile(PEDIGREE_FILE, 39 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 40 | sep='\t'), 41 | append=T); 42 | } 43 | } 44 | } 45 | 46 | 1: early() { 47 | for (pop in sim.subpopulations) { 48 | for (ind in pop.individuals) { 49 | age = community.modelType == "nonWF" ? ind.age else -1; 50 | writeFile(PEDIGREE_FILE, 51 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 52 | sep='\t'), 53 | append=T); 54 | } 55 | } 56 | } 57 | 58 | 1: late() { 59 | for (pop in sim.subpopulations) { 60 | for (ind in pop.individuals) { 61 | age = community.modelType == "nonWF" ? ind.age else -1; 62 | writeFile(PEDIGREE_FILE, 63 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 64 | sep='\t'), 65 | append=T); 66 | } 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_migration.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | } 14 | 15 | 1 early() { 16 | sim.addSubpop("p1", 10); 17 | sim.addSubpop("p3", 10); 18 | p1.setMigrationRates(p3, 0.2); 19 | p3.setMigrationRates(p1, 0.2); 20 | } 21 | 22 | 10 late() { 23 | sim.treeSeqOutput(TREES_FILE); 24 | catn("Done."); 25 | sim.simulationFinished(); 26 | } 27 | 28 | // PEDIGREE OUTPUT 29 | 1 first() { 30 | writeFile(PEDIGREE_FILE, 31 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 32 | sep="\t")); 33 | } 34 | 35 | 1: first() { 36 | for (pop in sim.subpopulations) { 37 | for (ind in pop.individuals) { 38 | age = community.modelType == "nonWF" ? ind.age else -1; 39 | writeFile(PEDIGREE_FILE, 40 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 41 | sep='\t'), 42 | append=T); 43 | } 44 | } 45 | } 46 | 47 | 1: early() { 48 | for (pop in sim.subpopulations) { 49 | for (ind in pop.individuals) { 50 | age = community.modelType == "nonWF" ? ind.age else -1; 51 | writeFile(PEDIGREE_FILE, 52 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 53 | sep='\t'), 54 | append=T); 55 | } 56 | } 57 | } 58 | 59 | 1: late() { 60 | for (pop in sim.subpopulations) { 61 | for (ind in pop.individuals) { 62 | age = community.modelType == "nonWF" ? ind.age else -1; 63 | writeFile(PEDIGREE_FILE, 64 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 65 | sep='\t'), 66 | append=T); 67 | } 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 early() { 22 | sim.addSubpop("p1", 10); 23 | } 24 | 25 | early() { 26 | p1.fitnessScaling = K / p1.individualCount; 27 | } 28 | 29 | 10 late() { 30 | sim.treeSeqOutput(TREES_FILE); 31 | catn("Done."); 32 | sim.simulationFinished(); 33 | } 34 | 35 | // PEDIGREE OUTPUT 36 | 1 first() { 37 | writeFile(PEDIGREE_FILE, 38 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 39 | sep="\t")); 40 | } 41 | 42 | 1: first() { 43 | for (pop in sim.subpopulations) { 44 | for (ind in pop.individuals) { 45 | age = community.modelType == "nonWF" ? ind.age else -1; 46 | writeFile(PEDIGREE_FILE, 47 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 48 | sep='\t'), 49 | append=T); 50 | } 51 | } 52 | } 53 | 54 | 1: early() { 55 | for (pop in sim.subpopulations) { 56 | for (ind in pop.individuals) { 57 | age = community.modelType == "nonWF" ? ind.age else -1; 58 | writeFile(PEDIGREE_FILE, 59 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 60 | sep='\t'), 61 | append=T); 62 | } 63 | } 64 | } 65 | 66 | 1: late() { 67 | for (pop in sim.subpopulations) { 68 | for (ind in pop.individuals) { 69 | age = community.modelType == "nonWF" ? ind.age else -1; 70 | writeFile(PEDIGREE_FILE, 71 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 72 | sep='\t'), 73 | append=T); 74 | } 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF_early_early.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 early() { 22 | sim.addSubpop("p1", 10); 23 | } 24 | 25 | early() { 26 | p1.fitnessScaling = K / p1.individualCount; 27 | } 28 | 29 | 10 early() { 30 | sim.treeSeqOutput(TREES_FILE); 31 | catn("Done."); 32 | sim.simulationFinished(); 33 | } 34 | 35 | // PEDIGREE OUTPUT 36 | 1 first() { 37 | writeFile(PEDIGREE_FILE, 38 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 39 | sep="\t")); 40 | } 41 | 42 | 1: first() { 43 | for (pop in sim.subpopulations) { 44 | for (ind in pop.individuals) { 45 | age = community.modelType == "nonWF" ? ind.age else -1; 46 | writeFile(PEDIGREE_FILE, 47 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 48 | sep='\t'), 49 | append=T); 50 | } 51 | } 52 | } 53 | 54 | 1: early() { 55 | for (pop in sim.subpopulations) { 56 | for (ind in pop.individuals) { 57 | age = community.modelType == "nonWF" ? ind.age else -1; 58 | writeFile(PEDIGREE_FILE, 59 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 60 | sep='\t'), 61 | append=T); 62 | } 63 | } 64 | } 65 | 66 | 1: late() { 67 | for (pop in sim.subpopulations) { 68 | for (ind in pop.individuals) { 69 | age = community.modelType == "nonWF" ? ind.age else -1; 70 | writeFile(PEDIGREE_FILE, 71 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 72 | sep='\t'), 73 | append=T); 74 | } 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF_early_first.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 early() { 22 | sim.addSubpop("p1", 10); 23 | } 24 | 25 | early() { 26 | p1.fitnessScaling = K / p1.individualCount; 27 | } 28 | 29 | 10 first() { 30 | sim.treeSeqOutput(TREES_FILE); 31 | catn("Done."); 32 | sim.simulationFinished(); 33 | } 34 | 35 | // PEDIGREE OUTPUT 36 | 1 first() { 37 | writeFile(PEDIGREE_FILE, 38 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 39 | sep="\t")); 40 | } 41 | 42 | 1: first() { 43 | for (pop in sim.subpopulations) { 44 | for (ind in pop.individuals) { 45 | age = community.modelType == "nonWF" ? ind.age else -1; 46 | writeFile(PEDIGREE_FILE, 47 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 48 | sep='\t'), 49 | append=T); 50 | } 51 | } 52 | } 53 | 54 | 1: early() { 55 | for (pop in sim.subpopulations) { 56 | for (ind in pop.individuals) { 57 | age = community.modelType == "nonWF" ? ind.age else -1; 58 | writeFile(PEDIGREE_FILE, 59 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 60 | sep='\t'), 61 | append=T); 62 | } 63 | } 64 | } 65 | 66 | 1: late() { 67 | for (pop in sim.subpopulations) { 68 | for (ind in pop.individuals) { 69 | age = community.modelType == "nonWF" ? ind.age else -1; 70 | writeFile(PEDIGREE_FILE, 71 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 72 | sep='\t'), 73 | append=T); 74 | } 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF_early_late.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 early() { 22 | sim.addSubpop("p1", 10); 23 | } 24 | 25 | early() { 26 | p1.fitnessScaling = K / p1.individualCount; 27 | } 28 | 29 | 10 late() { 30 | sim.treeSeqOutput(TREES_FILE); 31 | catn("Done."); 32 | sim.simulationFinished(); 33 | } 34 | 35 | // PEDIGREE OUTPUT 36 | 1 first() { 37 | writeFile(PEDIGREE_FILE, 38 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 39 | sep="\t")); 40 | } 41 | 42 | 1: first() { 43 | for (pop in sim.subpopulations) { 44 | for (ind in pop.individuals) { 45 | age = community.modelType == "nonWF" ? ind.age else -1; 46 | writeFile(PEDIGREE_FILE, 47 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 48 | sep='\t'), 49 | append=T); 50 | } 51 | } 52 | } 53 | 54 | 1: early() { 55 | for (pop in sim.subpopulations) { 56 | for (ind in pop.individuals) { 57 | age = community.modelType == "nonWF" ? ind.age else -1; 58 | writeFile(PEDIGREE_FILE, 59 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 60 | sep='\t'), 61 | append=T); 62 | } 63 | } 64 | } 65 | 66 | 1: late() { 67 | for (pop in sim.subpopulations) { 68 | for (ind in pop.individuals) { 69 | age = community.modelType == "nonWF" ? ind.age else -1; 70 | writeFile(PEDIGREE_FILE, 71 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 72 | sep='\t'), 73 | append=T); 74 | } 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF_first_early.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 first() { 22 | sim.addSubpop("p1", 10); 23 | } 24 | 25 | early() { 26 | p1.fitnessScaling = K / p1.individualCount; 27 | } 28 | 29 | 10 early() { 30 | sim.treeSeqOutput(TREES_FILE); 31 | catn("Done."); 32 | sim.simulationFinished(); 33 | } 34 | 35 | // PEDIGREE OUTPUT 36 | 1 first() { 37 | writeFile(PEDIGREE_FILE, 38 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 39 | sep="\t")); 40 | } 41 | 42 | 1: first() { 43 | for (pop in sim.subpopulations) { 44 | for (ind in pop.individuals) { 45 | age = community.modelType == "nonWF" ? ind.age else -1; 46 | writeFile(PEDIGREE_FILE, 47 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 48 | sep='\t'), 49 | append=T); 50 | } 51 | } 52 | } 53 | 54 | 1: early() { 55 | for (pop in sim.subpopulations) { 56 | for (ind in pop.individuals) { 57 | age = community.modelType == "nonWF" ? ind.age else -1; 58 | writeFile(PEDIGREE_FILE, 59 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 60 | sep='\t'), 61 | append=T); 62 | } 63 | } 64 | } 65 | 66 | 1: late() { 67 | for (pop in sim.subpopulations) { 68 | for (ind in pop.individuals) { 69 | age = community.modelType == "nonWF" ? ind.age else -1; 70 | writeFile(PEDIGREE_FILE, 71 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 72 | sep='\t'), 73 | append=T); 74 | } 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF_first_first.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 first() { 22 | sim.addSubpop("p1", 10); 23 | } 24 | 25 | early() { 26 | p1.fitnessScaling = K / p1.individualCount; 27 | } 28 | 29 | 10 first() { 30 | sim.treeSeqOutput(TREES_FILE); 31 | catn("Done."); 32 | sim.simulationFinished(); 33 | } 34 | 35 | // PEDIGREE OUTPUT 36 | 1 first() { 37 | writeFile(PEDIGREE_FILE, 38 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 39 | sep="\t")); 40 | } 41 | 42 | 1: first() { 43 | for (pop in sim.subpopulations) { 44 | for (ind in pop.individuals) { 45 | age = community.modelType == "nonWF" ? ind.age else -1; 46 | writeFile(PEDIGREE_FILE, 47 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 48 | sep='\t'), 49 | append=T); 50 | } 51 | } 52 | } 53 | 54 | 1: early() { 55 | for (pop in sim.subpopulations) { 56 | for (ind in pop.individuals) { 57 | age = community.modelType == "nonWF" ? ind.age else -1; 58 | writeFile(PEDIGREE_FILE, 59 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 60 | sep='\t'), 61 | append=T); 62 | } 63 | } 64 | } 65 | 66 | 1: late() { 67 | for (pop in sim.subpopulations) { 68 | for (ind in pop.individuals) { 69 | age = community.modelType == "nonWF" ? ind.age else -1; 70 | writeFile(PEDIGREE_FILE, 71 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 72 | sep='\t'), 73 | append=T); 74 | } 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF_first_late.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 first() { 22 | sim.addSubpop("p1", 10); 23 | } 24 | 25 | early() { 26 | p1.fitnessScaling = K / p1.individualCount; 27 | } 28 | 29 | 10 late() { 30 | sim.treeSeqOutput(TREES_FILE); 31 | catn("Done."); 32 | sim.simulationFinished(); 33 | } 34 | 35 | // PEDIGREE OUTPUT 36 | 1 first() { 37 | writeFile(PEDIGREE_FILE, 38 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 39 | sep="\t")); 40 | } 41 | 42 | 1: first() { 43 | for (pop in sim.subpopulations) { 44 | for (ind in pop.individuals) { 45 | age = community.modelType == "nonWF" ? ind.age else -1; 46 | writeFile(PEDIGREE_FILE, 47 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 48 | sep='\t'), 49 | append=T); 50 | } 51 | } 52 | } 53 | 54 | 1: early() { 55 | for (pop in sim.subpopulations) { 56 | for (ind in pop.individuals) { 57 | age = community.modelType == "nonWF" ? ind.age else -1; 58 | writeFile(PEDIGREE_FILE, 59 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 60 | sep='\t'), 61 | append=T); 62 | } 63 | } 64 | } 65 | 66 | 1: late() { 67 | for (pop in sim.subpopulations) { 68 | for (ind in pop.individuals) { 69 | age = community.modelType == "nonWF" ? ind.age else -1; 70 | writeFile(PEDIGREE_FILE, 71 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 72 | sep='\t'), 73 | append=T); 74 | } 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF_late_early.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 late() { 22 | sim.addSubpop("p1", 10); 23 | } 24 | 25 | 2: early() { 26 | p1.fitnessScaling = K / p1.individualCount; 27 | } 28 | 29 | 10 early() { 30 | sim.treeSeqOutput(TREES_FILE); 31 | catn("Done."); 32 | sim.simulationFinished(); 33 | } 34 | 35 | // PEDIGREE OUTPUT 36 | 1 first() { 37 | writeFile(PEDIGREE_FILE, 38 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 39 | sep="\t")); 40 | } 41 | 42 | 1: first() { 43 | for (pop in sim.subpopulations) { 44 | for (ind in pop.individuals) { 45 | age = community.modelType == "nonWF" ? ind.age else -1; 46 | writeFile(PEDIGREE_FILE, 47 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 48 | sep='\t'), 49 | append=T); 50 | } 51 | } 52 | } 53 | 54 | 1: early() { 55 | for (pop in sim.subpopulations) { 56 | for (ind in pop.individuals) { 57 | age = community.modelType == "nonWF" ? ind.age else -1; 58 | writeFile(PEDIGREE_FILE, 59 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 60 | sep='\t'), 61 | append=T); 62 | } 63 | } 64 | } 65 | 66 | 1: late() { 67 | for (pop in sim.subpopulations) { 68 | for (ind in pop.individuals) { 69 | age = community.modelType == "nonWF" ? ind.age else -1; 70 | writeFile(PEDIGREE_FILE, 71 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 72 | sep='\t'), 73 | append=T); 74 | } 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF_late_first.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 late() { 22 | sim.addSubpop("p1", 10); 23 | } 24 | 25 | 2: early() { 26 | p1.fitnessScaling = K / p1.individualCount; 27 | } 28 | 29 | 10 first() { 30 | sim.treeSeqOutput(TREES_FILE); 31 | catn("Done."); 32 | sim.simulationFinished(); 33 | } 34 | 35 | // PEDIGREE OUTPUT 36 | 1 first() { 37 | writeFile(PEDIGREE_FILE, 38 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 39 | sep="\t")); 40 | } 41 | 42 | 1: first() { 43 | for (pop in sim.subpopulations) { 44 | for (ind in pop.individuals) { 45 | age = community.modelType == "nonWF" ? ind.age else -1; 46 | writeFile(PEDIGREE_FILE, 47 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 48 | sep='\t'), 49 | append=T); 50 | } 51 | } 52 | } 53 | 54 | 1: early() { 55 | for (pop in sim.subpopulations) { 56 | for (ind in pop.individuals) { 57 | age = community.modelType == "nonWF" ? ind.age else -1; 58 | writeFile(PEDIGREE_FILE, 59 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 60 | sep='\t'), 61 | append=T); 62 | } 63 | } 64 | } 65 | 66 | 1: late() { 67 | for (pop in sim.subpopulations) { 68 | for (ind in pop.individuals) { 69 | age = community.modelType == "nonWF" ? ind.age else -1; 70 | writeFile(PEDIGREE_FILE, 71 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 72 | sep='\t'), 73 | append=T); 74 | } 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF_late_late.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 late() { 22 | sim.addSubpop("p1", 10); 23 | } 24 | 25 | 2: early() { 26 | p1.fitnessScaling = K / p1.individualCount; 27 | } 28 | 29 | 10 late() { 30 | sim.treeSeqOutput(TREES_FILE); 31 | catn("Done."); 32 | sim.simulationFinished(); 33 | } 34 | 35 | // PEDIGREE OUTPUT 36 | 1 first() { 37 | writeFile(PEDIGREE_FILE, 38 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 39 | sep="\t")); 40 | } 41 | 42 | 1: first() { 43 | for (pop in sim.subpopulations) { 44 | for (ind in pop.individuals) { 45 | age = community.modelType == "nonWF" ? ind.age else -1; 46 | writeFile(PEDIGREE_FILE, 47 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 48 | sep='\t'), 49 | append=T); 50 | } 51 | } 52 | } 53 | 54 | 1: early() { 55 | for (pop in sim.subpopulations) { 56 | for (ind in pop.individuals) { 57 | age = community.modelType == "nonWF" ? ind.age else -1; 58 | writeFile(PEDIGREE_FILE, 59 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 60 | sep='\t'), 61 | append=T); 62 | } 63 | } 64 | } 65 | 66 | 1: late() { 67 | for (pop in sim.subpopulations) { 68 | for (ind in pop.individuals) { 69 | age = community.modelType == "nonWF" ? ind.age else -1; 70 | writeFile(PEDIGREE_FILE, 71 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 72 | sep='\t'), 73 | append=T); 74 | } 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_record_everyone_WF_early.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T, dimensionality="xy"); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | defineConstant("K", 10); 14 | } 15 | 16 | 1 early() { 17 | sim.addSubpop("p1", 10); 18 | for (ind in p1.individuals) 19 | ind.setSpatialPosition(p1.pointUniform()); 20 | } 21 | 22 | early() { 23 | sim.treeSeqRememberIndividuals(p1.individuals); 24 | } 25 | 26 | 10 early() { 27 | sim.treeSeqOutput(TREES_FILE); 28 | catn("Done."); 29 | sim.simulationFinished(); 30 | } 31 | 32 | // PEDIGREE OUTPUT 33 | 1 first() { 34 | writeFile(PEDIGREE_FILE, 35 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 36 | sep="\t")); 37 | } 38 | 39 | 1: first() { 40 | for (pop in sim.subpopulations) { 41 | for (ind in pop.individuals) { 42 | age = community.modelType == "nonWF" ? ind.age else -1; 43 | writeFile(PEDIGREE_FILE, 44 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 45 | sep='\t'), 46 | append=T); 47 | } 48 | } 49 | } 50 | 51 | 1: early() { 52 | for (pop in sim.subpopulations) { 53 | for (ind in pop.individuals) { 54 | age = community.modelType == "nonWF" ? ind.age else -1; 55 | writeFile(PEDIGREE_FILE, 56 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 57 | sep='\t'), 58 | append=T); 59 | } 60 | } 61 | } 62 | 63 | 1: late() { 64 | for (pop in sim.subpopulations) { 65 | for (ind in pop.individuals) { 66 | age = community.modelType == "nonWF" ? ind.age else -1; 67 | writeFile(PEDIGREE_FILE, 68 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 69 | sep='\t'), 70 | append=T); 71 | } 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_record_everyone_WF_first.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T, dimensionality="xy"); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | defineConstant("K", 10); 14 | } 15 | 16 | 1 first() { 17 | sim.addSubpop("p1", 10); 18 | for (ind in p1.individuals) 19 | ind.setSpatialPosition(p1.pointUniform()); 20 | } 21 | 22 | 1: first() { 23 | sim.treeSeqRememberIndividuals(p1.individuals); 24 | } 25 | 26 | 10 first() { 27 | sim.treeSeqOutput(TREES_FILE); 28 | catn("Done."); 29 | sim.simulationFinished(); 30 | } 31 | 32 | // PEDIGREE OUTPUT 33 | 1 first() { 34 | writeFile(PEDIGREE_FILE, 35 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 36 | sep="\t")); 37 | } 38 | 39 | 1: first() { 40 | for (pop in sim.subpopulations) { 41 | for (ind in pop.individuals) { 42 | age = community.modelType == "nonWF" ? ind.age else -1; 43 | writeFile(PEDIGREE_FILE, 44 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 45 | sep='\t'), 46 | append=T); 47 | } 48 | } 49 | } 50 | 51 | 1: early() { 52 | for (pop in sim.subpopulations) { 53 | for (ind in pop.individuals) { 54 | age = community.modelType == "nonWF" ? ind.age else -1; 55 | writeFile(PEDIGREE_FILE, 56 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 57 | sep='\t'), 58 | append=T); 59 | } 60 | } 61 | } 62 | 63 | 1: late() { 64 | for (pop in sim.subpopulations) { 65 | for (ind in pop.individuals) { 66 | age = community.modelType == "nonWF" ? ind.age else -1; 67 | writeFile(PEDIGREE_FILE, 68 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 69 | sep='\t'), 70 | append=T); 71 | } 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_record_everyone_WF_late.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T, dimensionality="xy"); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | defineConstant("K", 10); 14 | } 15 | 16 | 1 early() { 17 | sim.addSubpop("p1", 10); 18 | for (ind in p1.individuals) 19 | ind.setSpatialPosition(p1.pointUniform()); 20 | sim.treeSeqRememberIndividuals(p1.individuals); 21 | } 22 | 23 | late() { 24 | sim.treeSeqRememberIndividuals(p1.individuals); 25 | } 26 | 27 | 10 late() { 28 | sim.treeSeqOutput(TREES_FILE); 29 | catn("Done."); 30 | sim.simulationFinished(); 31 | } 32 | 33 | // PEDIGREE OUTPUT 34 | 1 first() { 35 | writeFile(PEDIGREE_FILE, 36 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 37 | sep="\t")); 38 | } 39 | 40 | 1: first() { 41 | for (pop in sim.subpopulations) { 42 | for (ind in pop.individuals) { 43 | age = community.modelType == "nonWF" ? ind.age else -1; 44 | writeFile(PEDIGREE_FILE, 45 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 46 | sep='\t'), 47 | append=T); 48 | } 49 | } 50 | } 51 | 52 | 1: early() { 53 | for (pop in sim.subpopulations) { 54 | for (ind in pop.individuals) { 55 | age = community.modelType == "nonWF" ? ind.age else -1; 56 | writeFile(PEDIGREE_FILE, 57 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 58 | sep='\t'), 59 | append=T); 60 | } 61 | } 62 | } 63 | 64 | 1: late() { 65 | for (pop in sim.subpopulations) { 66 | for (ind in pop.individuals) { 67 | age = community.modelType == "nonWF" ? ind.age else -1; 68 | writeFile(PEDIGREE_FILE, 69 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 70 | sep='\t'), 71 | append=T); 72 | } 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF_H.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T); 8 | initializeTreeSeq(); 9 | initializeChromosome(1, 100, "H", "H"); 10 | initializeMutationRate(1e-2); 11 | initializeMutationType("m1", 0.5, "f", -0.1); 12 | initializeGenomicElementType("g1", m1, 1.0); 13 | initializeGenomicElement(g1, 0, 99); 14 | initializeRecombinationRate(1e-2); 15 | defineConstant("K", 10); 16 | } 17 | 18 | reproduction() { 19 | mate = subpop.sampleIndividuals(1); 20 | subpop.addCrossed(individual, mate); 21 | } 22 | 23 | 1 early() { 24 | sim.addSubpop("p1", 10); 25 | } 26 | 27 | early() { 28 | p1.fitnessScaling = K / p1.individualCount; 29 | } 30 | 31 | 10 late() { 32 | sim.treeSeqOutput(TREES_FILE); 33 | catn("Done."); 34 | sim.simulationFinished(); 35 | } 36 | 37 | // PEDIGREE OUTPUT 38 | 1 first() { 39 | writeFile(PEDIGREE_FILE, 40 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 41 | sep="\t")); 42 | } 43 | 44 | 1: first() { 45 | for (pop in sim.subpopulations) { 46 | for (ind in pop.individuals) { 47 | age = community.modelType == "nonWF" ? ind.age else -1; 48 | writeFile(PEDIGREE_FILE, 49 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 50 | sep='\t'), 51 | append=T); 52 | } 53 | } 54 | } 55 | 56 | 1: early() { 57 | for (pop in sim.subpopulations) { 58 | for (ind in pop.individuals) { 59 | age = community.modelType == "nonWF" ? ind.age else -1; 60 | writeFile(PEDIGREE_FILE, 61 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 62 | sep='\t'), 63 | append=T); 64 | } 65 | } 66 | } 67 | 68 | 1: late() { 69 | for (pop in sim.subpopulations) { 70 | for (ind in pop.individuals) { 71 | age = community.modelType == "nonWF" ? ind.age else -1; 72 | writeFile(PEDIGREE_FILE, 73 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 74 | sep='\t'), 75 | append=T); 76 | } 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nucleotides_plus_others.slim: -------------------------------------------------------------------------------- 1 | // Based on Example 18.1 2 | 3 | initialize() { 4 | setSeed(23); 5 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 6 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 7 | defineConstant("L", 1e2); 8 | initializeSLiMOptions(keepPedigrees=T, nucleotideBased=T); 9 | initializeTreeSeq(); 10 | initializeAncestralNucleotides(randomNucleotides(L)); 11 | initializeMutationTypeNuc("m1", 0.5, "f", 0.0); 12 | initializeMutationType("m2", 0.5, "n", 0.0, 0.1); 13 | initializeGenomicElementType("g1", m1, 1.0, mmJukesCantor(4e-2)); 14 | initializeGenomicElement(g1, 0, L-1); 15 | initializeRecombinationRate(1e-2); 16 | } 17 | 18 | 1 early() { 19 | sim.addSubpop("p1", 10); 20 | } 21 | 22 | 1: late() { 23 | // add *non-nucleotide* mutations also 24 | sample(p1.haplosomes, 10).addNewDrawnMutation(m2, rdunif(10, 0, L-1)); 25 | } 26 | 27 | 10 late() { 28 | sim.treeSeqOutput(TREES_FILE); 29 | catn("Done."); 30 | sim.simulationFinished(); 31 | } 32 | 33 | // PEDIGREE OUTPUT 34 | 1 first() { 35 | writeFile(PEDIGREE_FILE, 36 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 37 | sep="\t")); 38 | } 39 | 40 | 1: first() { 41 | for (pop in sim.subpopulations) { 42 | for (ind in pop.individuals) { 43 | age = community.modelType == "nonWF" ? ind.age else -1; 44 | writeFile(PEDIGREE_FILE, 45 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 46 | sep='\t'), 47 | append=T); 48 | } 49 | } 50 | } 51 | 52 | 1: early() { 53 | for (pop in sim.subpopulations) { 54 | for (ind in pop.individuals) { 55 | age = community.modelType == "nonWF" ? ind.age else -1; 56 | writeFile(PEDIGREE_FILE, 57 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 58 | sep='\t'), 59 | append=T); 60 | } 61 | } 62 | } 63 | 64 | 1: late() { 65 | for (pop in sim.subpopulations) { 66 | for (ind in pop.individuals) { 67 | age = community.modelType == "nonWF" ? ind.age else -1; 68 | writeFile(PEDIGREE_FILE, 69 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 70 | sep='\t'), 71 | append=T); 72 | } 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nucleotides_nonWF.slim: -------------------------------------------------------------------------------- 1 | initialize() { 2 | setSeed(23); 3 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 4 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 5 | defineConstant("L", 1e2); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T, nucleotideBased=T); 8 | initializeTreeSeq(); 9 | initializeAncestralNucleotides(randomNucleotides(L)); 10 | initializeMutationTypeNuc("m1", 0.5, "f", 0.0); 11 | initializeGenomicElementType("g1", m1, 1.0, mmJukesCantor(4e-2)); 12 | initializeGenomicElement(g1, 0, L-1); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 early() { 22 | sim.addSubpop("p1", 10); 23 | } 24 | 25 | early() { 26 | p1.fitnessScaling = K / p1.individualCount; 27 | } 28 | 29 | 10 late() { 30 | sim.treeSeqOutput(TREES_FILE); 31 | catn("Done."); 32 | sim.simulationFinished(); 33 | } 34 | 35 | // PEDIGREE OUTPUT 36 | 1 first() { 37 | writeFile(PEDIGREE_FILE, 38 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 39 | sep="\t")); 40 | } 41 | 42 | 1: first() { 43 | for (pop in sim.subpopulations) { 44 | for (ind in pop.individuals) { 45 | age = community.modelType == "nonWF" ? ind.age else -1; 46 | writeFile(PEDIGREE_FILE, 47 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 48 | sep='\t'), 49 | append=T); 50 | } 51 | } 52 | } 53 | 54 | 1: early() { 55 | for (pop in sim.subpopulations) { 56 | for (ind in pop.individuals) { 57 | age = community.modelType == "nonWF" ? ind.age else -1; 58 | writeFile(PEDIGREE_FILE, 59 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 60 | sep='\t'), 61 | append=T); 62 | } 63 | } 64 | } 65 | 66 | 1: late() { 67 | for (pop in sim.subpopulations) { 68 | for (ind in pop.individuals) { 69 | age = community.modelType == "nonWF" ? ind.age else -1; 70 | writeFile(PEDIGREE_FILE, 71 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 72 | sep='\t'), 73 | append=T); 74 | } 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF_X.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T); 8 | initializeTreeSeq(); 9 | initializeSex(); 10 | initializeChromosome(1, 100, "X", "X"); 11 | initializeMutationRate(1e-2); 12 | initializeMutationType("m1", 0.5, "f", -0.1); 13 | initializeGenomicElementType("g1", m1, 1.0); 14 | initializeGenomicElement(g1, 0, 99); 15 | initializeRecombinationRate(1e-2); 16 | defineConstant("K", 10); 17 | } 18 | 19 | reproduction(NULL, "F") { 20 | mate = subpop.sampleIndividuals(1, sex="M"); 21 | subpop.addCrossed(individual, mate); 22 | } 23 | 24 | 1 early() { 25 | sim.addSubpop("p1", 10); 26 | } 27 | 28 | early() { 29 | p1.fitnessScaling = K / p1.individualCount; 30 | } 31 | 32 | 10 late() { 33 | sim.treeSeqOutput(TREES_FILE); 34 | catn("Done."); 35 | sim.simulationFinished(); 36 | } 37 | 38 | // PEDIGREE OUTPUT 39 | 1 first() { 40 | writeFile(PEDIGREE_FILE, 41 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 42 | sep="\t")); 43 | } 44 | 45 | 1: first() { 46 | for (pop in sim.subpopulations) { 47 | for (ind in pop.individuals) { 48 | age = community.modelType == "nonWF" ? ind.age else -1; 49 | writeFile(PEDIGREE_FILE, 50 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 51 | sep='\t'), 52 | append=T); 53 | } 54 | } 55 | } 56 | 57 | 1: early() { 58 | for (pop in sim.subpopulations) { 59 | for (ind in pop.individuals) { 60 | age = community.modelType == "nonWF" ? ind.age else -1; 61 | writeFile(PEDIGREE_FILE, 62 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 63 | sep='\t'), 64 | append=T); 65 | } 66 | } 67 | } 68 | 69 | 1: late() { 70 | for (pop in sim.subpopulations) { 71 | for (ind in pop.individuals) { 72 | age = community.modelType == "nonWF" ? ind.age else -1; 73 | writeFile(PEDIGREE_FILE, 74 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 75 | sep='\t'), 76 | append=T); 77 | } 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF_Y.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T); 8 | initializeTreeSeq(); 9 | initializeSex(); 10 | initializeChromosome(1, 100, "Y", "Y"); 11 | initializeMutationRate(1e-2); 12 | initializeMutationType("m1", 0.5, "f", -0.1); 13 | initializeGenomicElementType("g1", m1, 1.0); 14 | initializeGenomicElement(g1, 0, 99); 15 | initializeRecombinationRate(1e-2); 16 | defineConstant("K", 10); 17 | } 18 | 19 | reproduction(NULL, "F") { 20 | mate = subpop.sampleIndividuals(1, sex="M"); 21 | subpop.addCrossed(individual, mate); 22 | } 23 | 24 | 1 early() { 25 | sim.addSubpop("p1", 10); 26 | } 27 | 28 | early() { 29 | p1.fitnessScaling = K / p1.individualCount; 30 | } 31 | 32 | 10 late() { 33 | sim.treeSeqOutput(TREES_FILE); 34 | catn("Done."); 35 | sim.simulationFinished(); 36 | } 37 | 38 | // PEDIGREE OUTPUT 39 | 1 first() { 40 | writeFile(PEDIGREE_FILE, 41 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 42 | sep="\t")); 43 | } 44 | 45 | 1: first() { 46 | for (pop in sim.subpopulations) { 47 | for (ind in pop.individuals) { 48 | age = community.modelType == "nonWF" ? ind.age else -1; 49 | writeFile(PEDIGREE_FILE, 50 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 51 | sep='\t'), 52 | append=T); 53 | } 54 | } 55 | } 56 | 57 | 1: early() { 58 | for (pop in sim.subpopulations) { 59 | for (ind in pop.individuals) { 60 | age = community.modelType == "nonWF" ? ind.age else -1; 61 | writeFile(PEDIGREE_FILE, 62 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 63 | sep='\t'), 64 | append=T); 65 | } 66 | } 67 | } 68 | 69 | 1: late() { 70 | for (pop in sim.subpopulations) { 71 | for (ind in pop.individuals) { 72 | age = community.modelType == "nonWF" ? ind.age else -1; 73 | writeFile(PEDIGREE_FILE, 74 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 75 | sep='\t'), 76 | append=T); 77 | } 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_retain_everyone_WF_late.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T, dimensionality="xy"); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationRate(1e-2); 9 | initializeMutationType("m1", 0.5, "f", -0.1); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | initializeGenomicElement(g1, 0, 99); 12 | initializeRecombinationRate(1e-2); 13 | defineConstant("K", 10); 14 | } 15 | 16 | 1 early() { 17 | sim.addSubpop("p1", 10); 18 | for (ind in p1.individuals) { 19 | ind.setSpatialPosition(p1.pointUniform()); 20 | } 21 | // it will help to record the first-gen ones that die as well 22 | sim.treeSeqRememberIndividuals(p1.individuals, permanent=F); 23 | } 24 | 25 | late() { 26 | sim.treeSeqRememberIndividuals(p1.individuals, permanent=F); 27 | } 28 | 29 | 10 late() { 30 | sim.treeSeqOutput(TREES_FILE); 31 | catn("Done."); 32 | sim.simulationFinished(); 33 | } 34 | 35 | // PEDIGREE OUTPUT 36 | 1 first() { 37 | writeFile(PEDIGREE_FILE, 38 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 39 | sep="\t")); 40 | } 41 | 42 | 1: first() { 43 | for (pop in sim.subpopulations) { 44 | for (ind in pop.individuals) { 45 | age = community.modelType == "nonWF" ? ind.age else -1; 46 | writeFile(PEDIGREE_FILE, 47 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 48 | sep='\t'), 49 | append=T); 50 | } 51 | } 52 | } 53 | 54 | 1: early() { 55 | for (pop in sim.subpopulations) { 56 | for (ind in pop.individuals) { 57 | age = community.modelType == "nonWF" ? ind.age else -1; 58 | writeFile(PEDIGREE_FILE, 59 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 60 | sep='\t'), 61 | append=T); 62 | } 63 | } 64 | } 65 | 66 | 1: late() { 67 | for (pop in sim.subpopulations) { 68 | for (ind in pop.individuals) { 69 | age = community.modelType == "nonWF" ? ind.age else -1; 70 | writeFile(PEDIGREE_FILE, 71 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 72 | sep='\t'), 73 | append=T); 74 | } 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_nonWF_selfing.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | if (runif(1) < 0.25) { 19 | mate = subpop.sampleIndividuals(1); 20 | } else { 21 | mate = individual; 22 | } 23 | for (_ in seqLen(rpois(1, 2))) { 24 | subpop.addCrossed(individual, mate); 25 | } 26 | } 27 | 28 | 1 early() { 29 | sim.addSubpop("p1", 10); 30 | } 31 | 32 | early() { 33 | p1.fitnessScaling = K / p1.individualCount; 34 | } 35 | 36 | 10 late() { 37 | sim.treeSeqOutput(TREES_FILE); 38 | catn("Done."); 39 | sim.simulationFinished(); 40 | } 41 | 42 | // PEDIGREE OUTPUT 43 | 1 first() { 44 | writeFile(PEDIGREE_FILE, 45 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 46 | sep="\t")); 47 | } 48 | 49 | 1: first() { 50 | for (pop in sim.subpopulations) { 51 | for (ind in pop.individuals) { 52 | age = community.modelType == "nonWF" ? ind.age else -1; 53 | writeFile(PEDIGREE_FILE, 54 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 55 | sep='\t'), 56 | append=T); 57 | } 58 | } 59 | } 60 | 61 | 1: early() { 62 | for (pop in sim.subpopulations) { 63 | for (ind in pop.individuals) { 64 | age = community.modelType == "nonWF" ? ind.age else -1; 65 | writeFile(PEDIGREE_FILE, 66 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 67 | sep='\t'), 68 | append=T); 69 | } 70 | } 71 | } 72 | 73 | 1: late() { 74 | for (pop in sim.subpopulations) { 75 | for (ind in pop.individuals) { 76 | age = community.modelType == "nonWF" ? ind.age else -1; 77 | writeFile(PEDIGREE_FILE, 78 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 79 | sep='\t'), 80 | append=T); 81 | } 82 | } 83 | } 84 | 85 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Docs 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: [main] 7 | merge_group: 8 | 9 | jobs: 10 | 11 | test: 12 | name: Build docs 13 | runs-on: ubuntu-24.04 14 | defaults: 15 | run: 16 | shell: bash 17 | steps: 18 | - name: Cancel Previous Runs 19 | uses: styfle/cancel-workflow-action@0.12.1 20 | with: 21 | access_token: ${{ github.token }} 22 | 23 | - name: Checkout 24 | uses: actions/checkout@v4.2.2 25 | with: 26 | submodules: true 27 | 28 | - name: Cache conda and dependencies 29 | id: cache 30 | uses: actions/cache@v4.2.2 31 | env: 32 | # Increase this to reset the cache if the key hasn't changed. 33 | CACHE_NUM: 3 34 | with: 35 | path: | 36 | /usr/share/miniconda/envs/anaconda-client-env 37 | ~/osx-conda 38 | ~/.profile 39 | key: conda-v${{ env.CACHE_NUM }}-${{ hashFiles('pyproject.toml') }} 40 | 41 | - name: Install Conda 42 | uses: conda-incubator/setup-miniconda@v3.1.1 43 | if: steps.cache.outputs.cache-hit != 'true' 44 | with: 45 | activate-environment: anaconda-client-env 46 | python-version: "3.10" 47 | channels: conda-forge 48 | channel-priority: strict 49 | auto-update-conda: true 50 | 51 | - name: Install slim 52 | if: steps.cache.outputs.cache-hit != 'true' 53 | shell: bash -l {0} #We need a login shell to get conda 54 | run: | 55 | conda install --yes slim 56 | 57 | - name: Install uv and pip deps 58 | if: steps.cache.outputs.cache-hit != 'true' 59 | shell: bash -l {0} 60 | run: | 61 | pip install uv 62 | uv pip install --system -r pyproject.toml --extra docs 63 | # Install current pyslim as editable to ensure we get the latest version 64 | uv pip install --system -e . 65 | 66 | # # Retaining commented block for next devel cycle 67 | # - name: Build SLiM 68 | # run: | 69 | # git clone https://github.com/messerlab/SLiM.git 70 | # cd SLiM 71 | # mkdir -p Release 72 | # cd Release 73 | # cmake -D CMAKE_BUILD_TYPE=Release .. 74 | # make -j 2 75 | 76 | - name: Build docs 77 | run: | 78 | source ~/.profile 79 | conda activate anaconda-client-env 80 | export PATH=$PWD/SLiM/Release:$PATH 81 | slim -v 82 | pip list 83 | cd docs && make 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools", "setuptools-scm"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "pyslim" 7 | dynamic = ["version"] 8 | description = "Manipulate tree sequences produced by SLiM." 9 | readme = "README.md" 10 | license = {text = "MIT"} 11 | authors = [ 12 | {name = "Peter Ralph", email = "petrel.harp@gmail.com"}, 13 | ] 14 | classifiers = [ 15 | "Development Status :: 4 - Beta", 16 | "Intended Audience :: Developers", 17 | "Intended Audience :: Science/Research", 18 | "License :: OSI Approved :: MIT License", 19 | "Operating System :: MacOS :: MacOS X", 20 | "Operating System :: POSIX", 21 | "Operating System :: Microsoft :: Windows", 22 | "Programming Language :: Python", 23 | "Programming Language :: Python :: 3", 24 | "Programming Language :: Python :: 3.10", 25 | "Programming Language :: Python :: 3.11", 26 | "Programming Language :: Python :: 3.12", 27 | "Programming Language :: Python :: 3.13", 28 | "Topic :: Scientific/Engineering", 29 | "Topic :: Scientific/Engineering :: Bio-Informatics", 30 | ] 31 | keywords = ["tree sequences", "tskit"] 32 | requires-python = ">=3.10" 33 | dependencies = [ 34 | "msprime>=1.0.1", 35 | "tskit", 36 | "numpy", 37 | ] 38 | 39 | [project.urls] 40 | homepage = "https://github.com/tskit-dev/pyslim" 41 | repository = "https://github.com/tskit-dev/pyslim" 42 | "Bug Reports" = "https://github.com/tskit-dev/pyslim/issues" 43 | 44 | [tool.setuptools] 45 | packages = ["pyslim"] 46 | include-package-data = true 47 | 48 | [tool.setuptools.dynamic] 49 | version = {attr = "pyslim._version.pyslim_version"} 50 | 51 | [project.optional-dependencies] 52 | test = [ 53 | "flake8==7.1.2", 54 | "pytest==8.3.5", 55 | "pytest-cov==6.1.1", 56 | "pytest-xdist==3.6.1", 57 | "filelock==3.19.1", 58 | "tskit==0.6.4", 59 | "msprime>=1.2.0", 60 | "matplotlib==3.9.4", 61 | "pandas==2.3.2", 62 | ] 63 | 64 | docs = [ 65 | "jupyter-book==1.0.4.post1", 66 | "matplotlib==3.10.3", 67 | "msprime==1.3.4", 68 | "pandas==2.2.3", 69 | "PyGithub==2.6.1", 70 | "setuptools-scm==8.2.1", 71 | "sphinx-argparse==0.5.2", 72 | "sphinx-issues==5.0.0", 73 | "tskit==0.6.3", 74 | ] 75 | 76 | dev = [ 77 | "flake8>=7.0", 78 | "pytest>=8.0", 79 | "pytest-cov>=6.0", 80 | "pytest-xdist>=3.0", 81 | "numpy", 82 | "filelock", 83 | "tskit>=0.6.3", 84 | "msprime>=1.2.0", 85 | "matplotlib>=3.0", 86 | "pandas>=2.0", 87 | "jupyter-book>=1.0", 88 | "setuptools-scm>=8.0", 89 | "sphinx-argparse>=0.5", 90 | "sphinx-issues>=5.0", 91 | ] -------------------------------------------------------------------------------- /tests/test_recipes/recipe_record_everyone_nonWF_late.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T, dimensionality="xy"); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 early() { 22 | sim.addSubpop("p1", 10); 23 | for (ind in p1.individuals) 24 | ind.setSpatialPosition(p1.pointUniform()); 25 | } 26 | 27 | early() { 28 | p1.fitnessScaling = K / p1.individualCount; 29 | } 30 | 31 | late() { 32 | sim.treeSeqRememberIndividuals(p1.individuals); 33 | } 34 | 35 | 10 late() { 36 | sim.treeSeqOutput(TREES_FILE); 37 | catn("Done."); 38 | sim.simulationFinished(); 39 | } 40 | 41 | // PEDIGREE OUTPUT 42 | 1 first() { 43 | writeFile(PEDIGREE_FILE, 44 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 45 | sep="\t")); 46 | } 47 | 48 | 1: first() { 49 | for (pop in sim.subpopulations) { 50 | for (ind in pop.individuals) { 51 | age = community.modelType == "nonWF" ? ind.age else -1; 52 | writeFile(PEDIGREE_FILE, 53 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 54 | sep='\t'), 55 | append=T); 56 | } 57 | } 58 | } 59 | 60 | 1: early() { 61 | for (pop in sim.subpopulations) { 62 | for (ind in pop.individuals) { 63 | age = community.modelType == "nonWF" ? ind.age else -1; 64 | writeFile(PEDIGREE_FILE, 65 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 66 | sep='\t'), 67 | append=T); 68 | } 69 | } 70 | } 71 | 72 | 1: late() { 73 | for (pop in sim.subpopulations) { 74 | for (ind in pop.individuals) { 75 | age = community.modelType == "nonWF" ? ind.age else -1; 76 | writeFile(PEDIGREE_FILE, 77 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 78 | sep='\t'), 79 | append=T); 80 | } 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_record_everyone_nonWF_early.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T, dimensionality="xy"); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 early() { 22 | sim.addSubpop("p1", 10); 23 | for (ind in p1.individuals) 24 | ind.setSpatialPosition(p1.pointUniform()); 25 | } 26 | 27 | early() { 28 | p1.fitnessScaling = K / p1.individualCount; 29 | } 30 | 31 | early() { 32 | sim.treeSeqRememberIndividuals(p1.individuals); 33 | } 34 | 35 | 10 early() { 36 | sim.treeSeqOutput(TREES_FILE); 37 | catn("Done."); 38 | sim.simulationFinished(); 39 | } 40 | 41 | // PEDIGREE OUTPUT 42 | 1 first() { 43 | writeFile(PEDIGREE_FILE, 44 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 45 | sep="\t")); 46 | } 47 | 48 | 1: first() { 49 | for (pop in sim.subpopulations) { 50 | for (ind in pop.individuals) { 51 | age = community.modelType == "nonWF" ? ind.age else -1; 52 | writeFile(PEDIGREE_FILE, 53 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 54 | sep='\t'), 55 | append=T); 56 | } 57 | } 58 | } 59 | 60 | 1: early() { 61 | for (pop in sim.subpopulations) { 62 | for (ind in pop.individuals) { 63 | age = community.modelType == "nonWF" ? ind.age else -1; 64 | writeFile(PEDIGREE_FILE, 65 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 66 | sep='\t'), 67 | append=T); 68 | } 69 | } 70 | } 71 | 72 | 1: late() { 73 | for (pop in sim.subpopulations) { 74 | for (ind in pop.individuals) { 75 | age = community.modelType == "nonWF" ? ind.age else -1; 76 | writeFile(PEDIGREE_FILE, 77 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 78 | sep='\t'), 79 | append=T); 80 | } 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_record_everyone_nonWF_first.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T, dimensionality="xy"); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 early() { 22 | sim.addSubpop("p1", 10); 23 | for (ind in p1.individuals) 24 | ind.setSpatialPosition(p1.pointUniform()); 25 | } 26 | 27 | early() { 28 | p1.fitnessScaling = K / p1.individualCount; 29 | } 30 | 31 | 2: first() { 32 | sim.treeSeqRememberIndividuals(p1.individuals); 33 | } 34 | 35 | 10 first() { 36 | sim.treeSeqOutput(TREES_FILE); 37 | catn("Done."); 38 | sim.simulationFinished(); 39 | } 40 | 41 | // PEDIGREE OUTPUT 42 | 1 first() { 43 | writeFile(PEDIGREE_FILE, 44 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 45 | sep="\t")); 46 | } 47 | 48 | 1: first() { 49 | for (pop in sim.subpopulations) { 50 | for (ind in pop.individuals) { 51 | age = community.modelType == "nonWF" ? ind.age else -1; 52 | writeFile(PEDIGREE_FILE, 53 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 54 | sep='\t'), 55 | append=T); 56 | } 57 | } 58 | } 59 | 60 | 1: early() { 61 | for (pop in sim.subpopulations) { 62 | for (ind in pop.individuals) { 63 | age = community.modelType == "nonWF" ? ind.age else -1; 64 | writeFile(PEDIGREE_FILE, 65 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 66 | sep='\t'), 67 | append=T); 68 | } 69 | } 70 | } 71 | 72 | 1: late() { 73 | for (pop in sim.subpopulations) { 74 | for (ind in pop.individuals) { 75 | age = community.modelType == "nonWF" ? ind.age else -1; 76 | writeFile(PEDIGREE_FILE, 77 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 78 | sep='\t'), 79 | append=T); 80 | } 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_retain_everyone_nonWF_late.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T, dimensionality="xy"); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 early() { 22 | sim.addSubpop("p1", 10); 23 | for (ind in p1.individuals) 24 | ind.setSpatialPosition(p1.pointUniform()); 25 | } 26 | 27 | early() { 28 | p1.fitnessScaling = K / p1.individualCount; 29 | } 30 | 31 | late() { 32 | sim.treeSeqRememberIndividuals(p1.individuals, permanent=F); 33 | } 34 | 35 | 10 late() { 36 | sim.treeSeqOutput(TREES_FILE); 37 | catn("Done."); 38 | sim.simulationFinished(); 39 | } 40 | 41 | // PEDIGREE OUTPUT 42 | 1 first() { 43 | writeFile(PEDIGREE_FILE, 44 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 45 | sep="\t")); 46 | } 47 | 48 | 1: first() { 49 | for (pop in sim.subpopulations) { 50 | for (ind in pop.individuals) { 51 | age = community.modelType == "nonWF" ? ind.age else -1; 52 | writeFile(PEDIGREE_FILE, 53 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 54 | sep='\t'), 55 | append=T); 56 | } 57 | } 58 | } 59 | 60 | 1: early() { 61 | for (pop in sim.subpopulations) { 62 | for (ind in pop.individuals) { 63 | age = community.modelType == "nonWF" ? ind.age else -1; 64 | writeFile(PEDIGREE_FILE, 65 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 66 | sep='\t'), 67 | append=T); 68 | } 69 | } 70 | } 71 | 72 | 1: late() { 73 | for (pop in sim.subpopulations) { 74 | for (ind in pop.individuals) { 75 | age = community.modelType == "nonWF" ? ind.age else -1; 76 | writeFile(PEDIGREE_FILE, 77 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 78 | sep='\t'), 79 | append=T); 80 | } 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /pyslim/provenance.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import platform 4 | import warnings 5 | import json 6 | import msprime 7 | import tskit 8 | 9 | from . import _version 10 | 11 | __version__ = _version.pyslim_version 12 | 13 | 14 | def slim_provenance_version(provenance): 15 | """ 16 | Parses a provenance record, returning whether the record is a SLiM 17 | provenance entry, and version is the file format version, or "unknown" if 18 | it is not a SLiM entry. 19 | 20 | :param Provenance provenance: The provenance entry, as for instance obtained 21 | from ts.provenance(0). 22 | :return: A (bool, string) tuple (is_slim, version). 23 | """ 24 | record = json.loads(provenance.record) 25 | software_name = "unknown" 26 | file_version = "unknown" 27 | # >= SLiM 3.1 // file version >= 0.2 28 | try: 29 | software_name = record["software"]["name"] 30 | except: 31 | pass 32 | 33 | if software_name == "SLiM": 34 | try: 35 | file_version = record["slim"]["file_version"] 36 | except: 37 | pass 38 | else: 39 | # SLiM 3.0 // file version 0.1 40 | try: 41 | software_name = record["program"] 42 | except: 43 | pass 44 | try: 45 | file_version = record["file_version"] 46 | except: 47 | pass 48 | is_slim = (software_name == "SLiM") 49 | return is_slim, file_version 50 | 51 | 52 | def get_environment(): 53 | """ 54 | Returns a dictionary describing the environment in which we are 55 | currently running. 56 | """ 57 | env = { 58 | "libraries": { 59 | }, 60 | "parameters" : { 61 | "command" : [] 62 | }, 63 | "os": { 64 | "system": platform.system(), 65 | "node": platform.node(), 66 | "release": platform.release(), 67 | "version": platform.version(), 68 | "machine": platform.machine(), 69 | }, 70 | "python": { 71 | "implementation": platform.python_implementation(), 72 | "version": platform.python_version_tuple(), 73 | } 74 | } 75 | return env 76 | 77 | 78 | def make_pyslim_provenance_dict(): 79 | """ 80 | Returns a dictionary encoding the information about this version of pyslim. 81 | """ 82 | document = { 83 | "schema_version": "1.0.0", 84 | "software": { 85 | "name" : "pyslim", 86 | "version": __version__, 87 | }, 88 | "parameters": { 89 | "command": {} 90 | }, 91 | "environment": get_environment() 92 | } 93 | return document 94 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_remember_and_retain.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMModelType("nonWF"); 7 | initializeSLiMOptions(keepPedigrees=T, dimensionality="xy"); 8 | initializeTreeSeq(); 9 | initializeMutationRate(1e-2); 10 | initializeMutationType("m1", 0.5, "f", -0.1); 11 | initializeGenomicElementType("g1", m1, 1.0); 12 | initializeGenomicElement(g1, 0, 99); 13 | initializeRecombinationRate(1e-2); 14 | defineConstant("K", 10); 15 | } 16 | 17 | reproduction() { 18 | subpop.addCrossed(individual, subpop.sampleIndividuals(1)); 19 | } 20 | 21 | 1 early() { 22 | sim.addSubpop("p1", 10); 23 | for (ind in p1.individuals) 24 | ind.setSpatialPosition(p1.pointUniform()); 25 | } 26 | 27 | early() { 28 | p1.fitnessScaling = K / p1.individualCount; 29 | } 30 | 31 | late() { 32 | // alternate remembering and retaining 33 | sim.treeSeqRememberIndividuals(p1.individuals, permanent=(sim.cycle % 2 == 0)); 34 | } 35 | 36 | 10 late() { 37 | sim.treeSeqOutput(TREES_FILE); 38 | catn("Done."); 39 | sim.simulationFinished(); 40 | } 41 | 42 | // PEDIGREE OUTPUT 43 | 1 first() { 44 | writeFile(PEDIGREE_FILE, 45 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 46 | sep="\t")); 47 | } 48 | 49 | 1: first() { 50 | for (pop in sim.subpopulations) { 51 | for (ind in pop.individuals) { 52 | age = community.modelType == "nonWF" ? ind.age else -1; 53 | writeFile(PEDIGREE_FILE, 54 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 55 | sep='\t'), 56 | append=T); 57 | } 58 | } 59 | } 60 | 61 | 1: early() { 62 | for (pop in sim.subpopulations) { 63 | for (ind in pop.individuals) { 64 | age = community.modelType == "nonWF" ? ind.age else -1; 65 | writeFile(PEDIGREE_FILE, 66 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 67 | sep='\t'), 68 | append=T); 69 | } 70 | } 71 | } 72 | 73 | 1: late() { 74 | for (pop in sim.subpopulations) { 75 | for (ind in pop.individuals) { 76 | age = community.modelType == "nonWF" ? ind.age else -1; 77 | writeFile(PEDIGREE_FILE, 78 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 79 | sep='\t'), 80 | append=T); 81 | } 82 | } 83 | } 84 | 85 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_H-_chromosome.slim: -------------------------------------------------------------------------------- 1 | initialize() { 2 | setSeed(23); 3 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 4 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 5 | initializeSLiMModelType("nonWF"); 6 | initializeSLiMOptions(keepPedigrees=T, dimensionality="xy"); 7 | initializeTreeSeq(); 8 | defineConstant("K", 20); // carrying capacity 9 | initializeMutationType("m1", 0.5, "f", 0.0); 10 | initializeGenomicElementType("g1", m1, 1.0); 11 | m1.convertToSubstitution = T; 12 | 13 | types = c("H-", "A", "H-", "H"); 14 | symbols = c("H1", "A", "H2", "H"); 15 | ids = 1 + seqAlong(types); 16 | length = 1e4; 17 | 18 | for (id in ids, symbol in symbols, type in types) 19 | { 20 | initializeChromosome(id, length, type, symbol); 21 | initializeMutationRate(1e-5); 22 | initializeRecombinationRate(1e-5); 23 | initializeGenomicElement(g1, 0, length-1); 24 | } 25 | } 26 | reproduction(NULL) { 27 | subpop.addCloned(individual, count=rpois(1, lambda=1.5)); 28 | } 29 | 1 early() { 30 | sim.addSubpop("p1", K); 31 | } 32 | early() { 33 | p1.fitnessScaling = K / p1.individualCount; 34 | } 35 | 36 | 30 late() { 37 | sim.treeSeqOutput(TREES_FILE); 38 | catn("Done."); 39 | sim.simulationFinished(); 40 | } 41 | 42 | // PEDIGREE OUTPUT 43 | 1 first() { 44 | writeFile(PEDIGREE_FILE, 45 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 46 | sep="\t")); 47 | } 48 | 49 | 1: first() { 50 | for (pop in sim.subpopulations) { 51 | for (ind in pop.individuals) { 52 | age = community.modelType == "nonWF" ? ind.age else -1; 53 | writeFile(PEDIGREE_FILE, 54 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 55 | sep='\t'), 56 | append=T); 57 | } 58 | } 59 | } 60 | 61 | 1: early() { 62 | for (pop in sim.subpopulations) { 63 | for (ind in pop.individuals) { 64 | age = community.modelType == "nonWF" ? ind.age else -1; 65 | writeFile(PEDIGREE_FILE, 66 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 67 | sep='\t'), 68 | append=T); 69 | } 70 | } 71 | } 72 | 73 | 1: late() { 74 | for (pop in sim.subpopulations) { 75 | for (ind in pop.individuals) { 76 | age = community.modelType == "nonWF" ? ind.age else -1; 77 | writeFile(PEDIGREE_FILE, 78 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 79 | sep='\t'), 80 | append=T); 81 | } 82 | } 83 | } 84 | 85 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_H.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T, nucleotideBased=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeMutationTypeNuc("m1", 0.5, "f", 0.0); 9 | initializeMutationType("m2", 0.5, "n", 0.0, 0.1); 10 | initializeGenomicElementType("g1", m1, 1.0, mmJukesCantor(8e-2)); 11 | defineConstant("L", 100); 12 | initializeChromosome(1, L, type="H", symbol="H"); 13 | initializeGenomicElement(g1, 0, L-1); 14 | initializeAncestralNucleotides(randomNucleotides(L)); 15 | initializeRecombinationRate(1e-2); 16 | } 17 | 18 | 1 early() { 19 | sim.addSubpop("p1", 10); 20 | } 21 | 1: late() { 22 | // add *non-nucleotide* mutations also 23 | for (chrom in sim.chromosomes) { 24 | haps = p1.individuals.haplosomesForChromosomes(chrom, includeNulls=F); 25 | if (length(haps) > 0) { 26 | sample(haps, 1 + asInteger(length(haps)/2)).addNewDrawnMutation(m2, rdunif(10, 0, L-1)); 27 | } 28 | } 29 | } 30 | 31 | 10 late() { 32 | sim.treeSeqOutput(TREES_FILE); 33 | catn("Done."); 34 | sim.simulationFinished(); 35 | } 36 | 37 | // PEDIGREE OUTPUT 38 | 1 first() { 39 | writeFile(PEDIGREE_FILE, 40 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 41 | sep="\t")); 42 | } 43 | 44 | 1: first() { 45 | for (pop in sim.subpopulations) { 46 | for (ind in pop.individuals) { 47 | age = community.modelType == "nonWF" ? ind.age else -1; 48 | writeFile(PEDIGREE_FILE, 49 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 50 | sep='\t'), 51 | append=T); 52 | } 53 | } 54 | } 55 | 56 | 1: early() { 57 | for (pop in sim.subpopulations) { 58 | for (ind in pop.individuals) { 59 | age = community.modelType == "nonWF" ? ind.age else -1; 60 | writeFile(PEDIGREE_FILE, 61 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 62 | sep='\t'), 63 | append=T); 64 | } 65 | } 66 | } 67 | 68 | 1: late() { 69 | for (pop in sim.subpopulations) { 70 | for (ind in pop.individuals) { 71 | age = community.modelType == "nonWF" ? ind.age else -1; 72 | writeFile(PEDIGREE_FILE, 73 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 74 | sep='\t'), 75 | append=T); 76 | } 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_HF.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T, nucleotideBased=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeSex(); 9 | initializeMutationTypeNuc("m1", 0.5, "f", 0.0); 10 | initializeMutationType("m2", 0.5, "n", 0.0, 0.1); 11 | initializeGenomicElementType("g1", m1, 1.0, mmJukesCantor(8e-2)); 12 | defineConstant("L", 100); 13 | initializeChromosome(1, L, type="HF", symbol="HF"); 14 | initializeGenomicElement(g1, 0, L-1); 15 | initializeAncestralNucleotides(randomNucleotides(L)); 16 | initializeRecombinationRate(1e-2); 17 | } 18 | 19 | 1 early() { 20 | sim.addSubpop("p1", 10); 21 | } 22 | 1: late() { 23 | // add *non-nucleotide* mutations also 24 | for (chrom in sim.chromosomes) { 25 | haps = p1.individuals.haplosomesForChromosomes(chrom, includeNulls=F); 26 | if (length(haps) > 0) { 27 | sample(haps, 1 + asInteger(length(haps)/2)).addNewDrawnMutation(m2, rdunif(10, 0, L-1)); 28 | } 29 | } 30 | } 31 | 32 | 10 late() { 33 | sim.treeSeqOutput(TREES_FILE); 34 | catn("Done."); 35 | sim.simulationFinished(); 36 | } 37 | 38 | // PEDIGREE OUTPUT 39 | 1 first() { 40 | writeFile(PEDIGREE_FILE, 41 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 42 | sep="\t")); 43 | } 44 | 45 | 1: first() { 46 | for (pop in sim.subpopulations) { 47 | for (ind in pop.individuals) { 48 | age = community.modelType == "nonWF" ? ind.age else -1; 49 | writeFile(PEDIGREE_FILE, 50 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 51 | sep='\t'), 52 | append=T); 53 | } 54 | } 55 | } 56 | 57 | 1: early() { 58 | for (pop in sim.subpopulations) { 59 | for (ind in pop.individuals) { 60 | age = community.modelType == "nonWF" ? ind.age else -1; 61 | writeFile(PEDIGREE_FILE, 62 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 63 | sep='\t'), 64 | append=T); 65 | } 66 | } 67 | } 68 | 69 | 1: late() { 70 | for (pop in sim.subpopulations) { 71 | for (ind in pop.individuals) { 72 | age = community.modelType == "nonWF" ? ind.age else -1; 73 | writeFile(PEDIGREE_FILE, 74 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 75 | sep='\t'), 76 | append=T); 77 | } 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_HM.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T, nucleotideBased=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeSex(); 9 | initializeMutationTypeNuc("m1", 0.5, "f", 0.0); 10 | initializeMutationType("m2", 0.5, "n", 0.0, 0.1); 11 | initializeGenomicElementType("g1", m1, 1.0, mmJukesCantor(8e-2)); 12 | defineConstant("L", 100); 13 | initializeChromosome(1, L, type="HM", symbol="HM"); 14 | initializeGenomicElement(g1, 0, L-1); 15 | initializeAncestralNucleotides(randomNucleotides(L)); 16 | initializeRecombinationRate(1e-2); 17 | } 18 | 19 | 1 early() { 20 | sim.addSubpop("p1", 10); 21 | } 22 | 1: late() { 23 | // add *non-nucleotide* mutations also 24 | for (chrom in sim.chromosomes) { 25 | haps = p1.individuals.haplosomesForChromosomes(chrom, includeNulls=F); 26 | if (length(haps) > 0) { 27 | sample(haps, 1 + asInteger(length(haps)/2)).addNewDrawnMutation(m2, rdunif(10, 0, L-1)); 28 | } 29 | } 30 | } 31 | 32 | 10 late() { 33 | sim.treeSeqOutput(TREES_FILE); 34 | catn("Done."); 35 | sim.simulationFinished(); 36 | } 37 | 38 | // PEDIGREE OUTPUT 39 | 1 first() { 40 | writeFile(PEDIGREE_FILE, 41 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 42 | sep="\t")); 43 | } 44 | 45 | 1: first() { 46 | for (pop in sim.subpopulations) { 47 | for (ind in pop.individuals) { 48 | age = community.modelType == "nonWF" ? ind.age else -1; 49 | writeFile(PEDIGREE_FILE, 50 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 51 | sep='\t'), 52 | append=T); 53 | } 54 | } 55 | } 56 | 57 | 1: early() { 58 | for (pop in sim.subpopulations) { 59 | for (ind in pop.individuals) { 60 | age = community.modelType == "nonWF" ? ind.age else -1; 61 | writeFile(PEDIGREE_FILE, 62 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 63 | sep='\t'), 64 | append=T); 65 | } 66 | } 67 | } 68 | 69 | 1: late() { 70 | for (pop in sim.subpopulations) { 71 | for (ind in pop.individuals) { 72 | age = community.modelType == "nonWF" ? ind.age else -1; 73 | writeFile(PEDIGREE_FILE, 74 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 75 | sep='\t'), 76 | append=T); 77 | } 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_W.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T, nucleotideBased=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeSex(); 9 | initializeMutationTypeNuc("m1", 0.5, "f", 0.0); 10 | initializeMutationType("m2", 0.5, "n", 0.0, 0.1); 11 | initializeGenomicElementType("g1", m1, 1.0, mmJukesCantor(8e-2)); 12 | defineConstant("L", 100); 13 | initializeChromosome(1, L, type="W", symbol="W"); 14 | initializeGenomicElement(g1, 0, L-1); 15 | initializeAncestralNucleotides(randomNucleotides(L)); 16 | initializeRecombinationRate(1e-2); 17 | } 18 | 19 | 1 early() { 20 | sim.addSubpop("p1", 10); 21 | } 22 | 1: late() { 23 | // add *non-nucleotide* mutations also 24 | for (chrom in sim.chromosomes) { 25 | haps = p1.individuals.haplosomesForChromosomes(chrom, includeNulls=F); 26 | if (length(haps) > 0) { 27 | sample(haps, 1 + asInteger(length(haps)/2)).addNewDrawnMutation(m2, rdunif(10, 0, L-1)); 28 | } 29 | } 30 | } 31 | 32 | 10 late() { 33 | sim.treeSeqOutput(TREES_FILE); 34 | catn("Done."); 35 | sim.simulationFinished(); 36 | } 37 | 38 | // PEDIGREE OUTPUT 39 | 1 first() { 40 | writeFile(PEDIGREE_FILE, 41 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 42 | sep="\t")); 43 | } 44 | 45 | 1: first() { 46 | for (pop in sim.subpopulations) { 47 | for (ind in pop.individuals) { 48 | age = community.modelType == "nonWF" ? ind.age else -1; 49 | writeFile(PEDIGREE_FILE, 50 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 51 | sep='\t'), 52 | append=T); 53 | } 54 | } 55 | } 56 | 57 | 1: early() { 58 | for (pop in sim.subpopulations) { 59 | for (ind in pop.individuals) { 60 | age = community.modelType == "nonWF" ? ind.age else -1; 61 | writeFile(PEDIGREE_FILE, 62 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 63 | sep='\t'), 64 | append=T); 65 | } 66 | } 67 | } 68 | 69 | 1: late() { 70 | for (pop in sim.subpopulations) { 71 | for (ind in pop.individuals) { 72 | age = community.modelType == "nonWF" ? ind.age else -1; 73 | writeFile(PEDIGREE_FILE, 74 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 75 | sep='\t'), 76 | append=T); 77 | } 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_X.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T, nucleotideBased=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeSex(); 9 | initializeMutationTypeNuc("m1", 0.5, "f", 0.0); 10 | initializeMutationType("m2", 0.5, "n", 0.0, 0.1); 11 | initializeGenomicElementType("g1", m1, 1.0, mmJukesCantor(8e-2)); 12 | defineConstant("L", 100); 13 | initializeChromosome(1, L, type="X", symbol="X"); 14 | initializeGenomicElement(g1, 0, L-1); 15 | initializeAncestralNucleotides(randomNucleotides(L)); 16 | initializeRecombinationRate(1e-2); 17 | } 18 | 19 | 1 early() { 20 | sim.addSubpop("p1", 10); 21 | } 22 | 1: late() { 23 | // add *non-nucleotide* mutations also 24 | for (chrom in sim.chromosomes) { 25 | haps = p1.individuals.haplosomesForChromosomes(chrom, includeNulls=F); 26 | if (length(haps) > 0) { 27 | sample(haps, 1 + asInteger(length(haps)/2)).addNewDrawnMutation(m2, rdunif(10, 0, L-1)); 28 | } 29 | } 30 | } 31 | 32 | 10 late() { 33 | sim.treeSeqOutput(TREES_FILE); 34 | catn("Done."); 35 | sim.simulationFinished(); 36 | } 37 | 38 | // PEDIGREE OUTPUT 39 | 1 first() { 40 | writeFile(PEDIGREE_FILE, 41 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 42 | sep="\t")); 43 | } 44 | 45 | 1: first() { 46 | for (pop in sim.subpopulations) { 47 | for (ind in pop.individuals) { 48 | age = community.modelType == "nonWF" ? ind.age else -1; 49 | writeFile(PEDIGREE_FILE, 50 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 51 | sep='\t'), 52 | append=T); 53 | } 54 | } 55 | } 56 | 57 | 1: early() { 58 | for (pop in sim.subpopulations) { 59 | for (ind in pop.individuals) { 60 | age = community.modelType == "nonWF" ? ind.age else -1; 61 | writeFile(PEDIGREE_FILE, 62 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 63 | sep='\t'), 64 | append=T); 65 | } 66 | } 67 | } 68 | 69 | 1: late() { 70 | for (pop in sim.subpopulations) { 71 | for (ind in pop.individuals) { 72 | age = community.modelType == "nonWF" ? ind.age else -1; 73 | writeFile(PEDIGREE_FILE, 74 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 75 | sep='\t'), 76 | append=T); 77 | } 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_Z.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T, nucleotideBased=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeSex(); 9 | initializeMutationTypeNuc("m1", 0.5, "f", 0.0); 10 | initializeMutationType("m2", 0.5, "n", 0.0, 0.1); 11 | initializeGenomicElementType("g1", m1, 1.0, mmJukesCantor(8e-2)); 12 | defineConstant("L", 100); 13 | initializeChromosome(1, L, type="Z", symbol="Z"); 14 | initializeGenomicElement(g1, 0, L-1); 15 | initializeAncestralNucleotides(randomNucleotides(L)); 16 | initializeRecombinationRate(1e-2); 17 | } 18 | 19 | 1 early() { 20 | sim.addSubpop("p1", 10); 21 | } 22 | 1: late() { 23 | // add *non-nucleotide* mutations also 24 | for (chrom in sim.chromosomes) { 25 | haps = p1.individuals.haplosomesForChromosomes(chrom, includeNulls=F); 26 | if (length(haps) > 0) { 27 | sample(haps, 1 + asInteger(length(haps)/2)).addNewDrawnMutation(m2, rdunif(10, 0, L-1)); 28 | } 29 | } 30 | } 31 | 32 | 10 late() { 33 | sim.treeSeqOutput(TREES_FILE); 34 | catn("Done."); 35 | sim.simulationFinished(); 36 | } 37 | 38 | // PEDIGREE OUTPUT 39 | 1 first() { 40 | writeFile(PEDIGREE_FILE, 41 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 42 | sep="\t")); 43 | } 44 | 45 | 1: first() { 46 | for (pop in sim.subpopulations) { 47 | for (ind in pop.individuals) { 48 | age = community.modelType == "nonWF" ? ind.age else -1; 49 | writeFile(PEDIGREE_FILE, 50 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 51 | sep='\t'), 52 | append=T); 53 | } 54 | } 55 | } 56 | 57 | 1: early() { 58 | for (pop in sim.subpopulations) { 59 | for (ind in pop.individuals) { 60 | age = community.modelType == "nonWF" ? ind.age else -1; 61 | writeFile(PEDIGREE_FILE, 62 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 63 | sep='\t'), 64 | append=T); 65 | } 66 | } 67 | } 68 | 69 | 1: late() { 70 | for (pop in sim.subpopulations) { 71 | for (ind in pop.individuals) { 72 | age = community.modelType == "nonWF" ? ind.age else -1; 73 | writeFile(PEDIGREE_FILE, 74 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 75 | sep='\t'), 76 | append=T); 77 | } 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /tests/test_recipes/recipe_WF_Y.slim: -------------------------------------------------------------------------------- 1 | initialize() 2 | { 3 | setSeed(23); 4 | if (!exists("TREES_FILE")) defineGlobal("TREES_FILE", "out.trees"); 5 | if (!exists("PEDIGREE_FILE")) defineGlobal("PEDIGREE_FILE", "out.pedigree"); 6 | initializeSLiMOptions(keepPedigrees=T, nucleotideBased=T); 7 | initializeTreeSeq(timeUnit="generations"); 8 | initializeSex(); 9 | initializeMutationTypeNuc("m1", 0.5, "f", 0.0); 10 | initializeMutationType("m2", 0.5, "n", 0.0, 0.1); 11 | initializeGenomicElementType("g1", m1, 1.0, mmJukesCantor(8e-2)); 12 | defineConstant("L", 100); 13 | initializeChromosome(1, L, type="Y", symbol="Y"); 14 | initializeGenomicElement(g1, 0, L-1); 15 | initializeAncestralNucleotides(randomNucleotides(L)); 16 | initializeRecombinationRate(1e-2); 17 | } 18 | 19 | 1 early() { 20 | sim.addSubpop("p1", 10); 21 | } 22 | 1: late() { 23 | // add *non-nucleotide* mutations also 24 | for (chrom in sim.chromosomes) { 25 | haps = p1.individuals.haplosomesForChromosomes(chrom, includeNulls=F); 26 | if (length(haps) > 0) { 27 | sample(haps, 1 + asInteger(length(haps)/2)).addNewDrawnMutation(m2, rdunif(10, 0, L-1)); 28 | } 29 | } 30 | } 31 | 32 | 10 late() { 33 | sim.treeSeqOutput(TREES_FILE); 34 | catn("Done."); 35 | sim.simulationFinished(); 36 | } 37 | 38 | // PEDIGREE OUTPUT 39 | 1 first() { 40 | writeFile(PEDIGREE_FILE, 41 | paste(c("generation", "stage", "individual", "age", "parent1", "parent2"), 42 | sep="\t")); 43 | } 44 | 45 | 1: first() { 46 | for (pop in sim.subpopulations) { 47 | for (ind in pop.individuals) { 48 | age = community.modelType == "nonWF" ? ind.age else -1; 49 | writeFile(PEDIGREE_FILE, 50 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 51 | sep='\t'), 52 | append=T); 53 | } 54 | } 55 | } 56 | 57 | 1: early() { 58 | for (pop in sim.subpopulations) { 59 | for (ind in pop.individuals) { 60 | age = community.modelType == "nonWF" ? ind.age else -1; 61 | writeFile(PEDIGREE_FILE, 62 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 63 | sep='\t'), 64 | append=T); 65 | } 66 | } 67 | } 68 | 69 | 1: late() { 70 | for (pop in sim.subpopulations) { 71 | for (ind in pop.individuals) { 72 | age = community.modelType == "nonWF" ? ind.age else -1; 73 | writeFile(PEDIGREE_FILE, 74 | paste(c(sim.cycle, community.cycleStage, ind.pedigreeID, age, ind.pedigreeParentIDs), 75 | sep='\t'), 76 | append=T); 77 | } 78 | } 79 | } 80 | 81 | 82 | --------------------------------------------------------------------------------