diff --git a/docs/articles/vignette-00-installation.html b/docs/articles/vignette-00-installation.html index b8ff8e9d6..6f4e7b5c1 100644 --- a/docs/articles/vignette-00-installation.html +++ b/docs/articles/vignette-00-installation.html @@ -256,6 +256,80 @@

SLiM

Note that slendr requires SLiM 4.0 and will not work with an earlier version. Again, running library(slendr) will inform you of any potential issues with your SLiM installation.

+
+

Adding SLiM to the $PATH +

+

In order for slendr to be able to find your SLiM +installation, R must be able to find the slim binary (or +slim.exe in case of Windows) in the so called $PATH +variable. The easiest way to verify that this is true is to call +Sys.which("slim") (or Sys.which("slim.exe") on +Windows) in your R session. For instance, on my own Mac, I get this:

+
> Sys.which("slim")
+                 slim 
+"/usr/local/bin/slim" 
+

On Windows, I get this (I followed the section 2.3.1 of the SLiM +manual describing the most “official” way to install SLiM and I +recommend you follow this as well):

+
> Sys.which("slim.exe")
+                            slim.exe 
+"C:\\msys64\\mingw64\\bin\\slim.exe" 
+

If, on the other hand, you might get something like this — an empty +string:

+
> Sys.which("slim")
+slim 
+  "" 
+

This means that your $PATH R is not configured +properly and R (and slendr) won’t be able to find SLiM in the +$PATH.

+

How to add SLiM to the $PATH then? Probably the most +convenient way to do this is by editing the .Renviron file. +The precise location of this file depends on your operation system but +you can automatically get it open in a text editor by using this command +(you might have to do install.packages("usethis") +first):

+
usethis::edit_r_environ()
+

Then, you can either add the following (note that there’s no +$ in this line!):

+
PATH="<path to directory with SLiM binaries>"
+

Alternatively, should you already have some $PATH +contents specified for your R session, you can get it by calling +Sys.getenv("PATH") in your R console, grab the entire +string you get in this way, and append the path where you installed SLiM +using an appropriate delimiter (: on Linux/macOS, +; on Windows) to this string. In this case, the edit might +look something like this:

+
PATH="<original Sys.getenv("PATH") content><delimiter><path to directory with SLiM binaries>"
+

For instance, on my Mac, the .Renviron file contains +this line (note the last item /usr/local/bin matches the +path to slim I showed above):

+
PATH="/opt/homebrew/bin:/opt/homebrew/sbin:/Users/mp/.my_local/bin:/Users/mp/.my_local/AdmixTools/bin:/Library/TeX/texbin:/opt/homebrew/opt/gnu-sed/libexec/gnubin:/opt/homebrew/opt/coreutils/libexec/gnubin:/usr/local/bin"
+

On my testing Windows machine, I have this in the +.Renviron file (again, look for the path +C:/msys64/mingw64/bin;$PATH" which matches the +slim.exe binary shown above):

+
PATH="C:\\msys64\\usr\\bin;C:\\rtools43\\x86_64-w64-mingw32.static.posix\\bin;C:\\rtools43\\usr\\bin;C:\\Program Files (x86)\\R\\R-4.3.2\\bin\\x64;C:/msys64/mingw64/bin"
+

The most important check that your R can find SLiM is using +the Sys.which() command described above. Before this gives +you a positive result, you won’t be able to use slendr’s +spatial SLiM simulations. If you’re struggling with this, +search for advice related to .Renviron and +$PATH online.

+
+
Fallback options +
+

If you don’t want to deal with editing the .Renviron +file, you should be able to set the path to SLiM using the command +Sys.setenv(PATH = "<path to directory with SLiM binaries>"). +You will have to do this at the beginning of each of your slendr R +scripts though.

+

Alternatively, the slim() function has an argument +slim_path= where you can specify the full path to the +slim or slim.exe binaries directly (not the +directory as it’s the case with the $PATH! the full path to +the slim/slim.exe binary itself).

+
+

Python diff --git a/docs/articles/vignette-01-tutorial.html b/docs/articles/vignette-01-tutorial.html index 337767da3..561cf1721 100644 --- a/docs/articles/vignette-01-tutorial.html +++ b/docs/articles/vignette-01-tutorial.html @@ -775,7 +775,7 @@

Running the simulation#> ╔═══════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════╣ -#> ║Trees │ 130║ +#> ║Trees │ 133║ #> ╟───────────────┼───────╢ #> ║Sequence Length│ 100000║ #> ╟───────────────┼───────╢ @@ -788,15 +788,15 @@

Running the simulation#> ╔═══════════╤═════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪═════╪═════════╪════════════╣ -#> ║Edges │18739│585.6 KiB│ No║ +#> ║Edges │18682│583.8 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ -#> ║Individuals│12841│ 1.2 MiB│ Yes║ +#> ║Individuals│12838│ 1.2 MiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ -#> ║Nodes │18380│682.7 KiB│ Yes║ +#> ║Nodes │18332│681.0 KiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Populations│ 6│ 2.6 KiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ diff --git a/docs/articles/vignette-02-grid-model.html b/docs/articles/vignette-02-grid-model.html index 376f5bf07..8d7517ca6 100644 --- a/docs/articles/vignette-02-grid-model.html +++ b/docs/articles/vignette-02-grid-model.html @@ -284,15 +284,15 @@

Simple two-dimensional grid model#> ╔═══════════╤════╤═════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪═════════╪════════════╣ -#> ║Edges │9042│282.6 KiB│ No║ +#> ║Edges │9065│283.3 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ -#> ║Individuals│6310│617.8 KiB│ Yes║ +#> ║Individuals│6316│618.4 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ -#> ║Nodes │9068│337.2 KiB│ Yes║ +#> ║Nodes │9090│338.0 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Populations│ 25│ 5.7 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ @@ -382,7 +382,7 @@

More customized spatial modelmap <- world(xrange = xrange, yrange = yrange, crs = "EPSG:31970")

#> Reading layer `ne_110m_land' from data source 
-#>   `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/Rtmpug1qnH/naturalearth/ne_110m_land.shp' 
+#>   `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpI0CWYj/naturalearth/ne_110m_land.shp' 
 #>   using driver `ESRI Shapefile'
 #> Simple feature collection with 127 features and 3 fields
 #> Geometry type: POLYGON
diff --git a/docs/articles/vignette-05-tree-sequences.html b/docs/articles/vignette-05-tree-sequences.html
index a57b01438..7879b8064 100644
--- a/docs/articles/vignette-05-tree-sequences.html
+++ b/docs/articles/vignette-05-tree-sequences.html
@@ -340,11 +340,11 @@ 

Scheduling of sampling events#> -------------------------------------------------- #> msprime command: #> -#> /Users/mp/Library/r-miniconda-arm64/envs/Python-3.12_msprime-1.3.0_tskit-0.5.6_pyslim-1.0.4_tspop-0.0.2/bin/python /private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpYADxQ3/file122e5348d0ae_introgression/script.py --seed 314159 --model /private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpYADxQ3/file122e5348d0ae_introgression --output /var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpYADxQ3/file122e57375f75f.trees --sequence-length 100000000 --recombination-rate 1e-08 --sampling-schedule /var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpYADxQ3/file122e550be251a --verbose +#> /Users/mp/Library/r-miniconda-arm64/envs/Python-3.12_msprime-1.3.0_tskit-0.5.6_pyslim-1.0.4_tspop-0.0.2/bin/python /private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpQbon7e/filee17860409253_introgression/script.py --seed 314159 --model /private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpQbon7e/filee17860409253_introgression --output /var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpQbon7e/filee1784cccb6b3.trees --sequence-length 100000000 --recombination-rate 1e-08 --sampling-schedule /var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpQbon7e/filee17859cbb4d3 --verbose #> -------------------------------------------------- #> #> Tree sequence was saved to: -#> /var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpYADxQ3/file122e57375f75f.trees +#> /var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpQbon7e/filee1784cccb6b3.trees #> Loading the tree-sequence file...

 ts
@@ -431,7 +431,7 @@

Loading and processin ) output_file -
#> [1] "/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpYADxQ3/file122e534b363bf"
+
#> [1] "/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpQbon7e/filee17821d8acf8"

In case have the tree-sequence output saved in a custom location on disk, we can load the tree sequence using the slendr function ts_load(). If we’re dealing with a tree sequence produced diff --git a/docs/articles/vignette-08-nonslendr-tskit.html b/docs/articles/vignette-08-nonslendr-tskit.html index 5735d5b1e..c2da2a340 100644 --- a/docs/articles/vignette-08-nonslendr-tskit.html +++ b/docs/articles/vignette-08-nonslendr-tskit.html @@ -189,7 +189,7 @@

Non-spatial SLiM tree sequences

After we run this script in SLiM, we can use slendr to load the output tree sequence (saved to @@ -315,7 +315,7 @@

Non-spatial SLiM tree sequences ggtree(tree, branch.length = "none") %<+% labels + geom_label(aes(label = tskit_id)) -

+

 library(ape)
 plot(tree, show.tip.label = FALSE)
@@ -394,7 +394,7 @@ 

Spatial SLiM (non-slendr) tree s } 10000 late() { - sim.treeSeqOutput("/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpZrPslt/file12655786f22f"); + sim.treeSeqOutput("/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//Rtmpx99kMg/filee61c27e4c5b7"); }

We can then load and simplify the output tree sequence in just as we did above in this vignette (or anywhere in the slendr @@ -436,7 +436,7 @@

Spatial SLiM (non-slendr) tree s location of each recorded node:

 ggplot() + geom_sf(data = data, aes(color = time), alpha = 0.5)
-

+

We can also collect spatio-temporal ancestry information of a particular node (i.e. the times and locations of all of its ancestors all the way to the root, with each “link” in the plot signifying @@ -452,7 +452,7 @@

Spatial SLiM (non-slendr) tree s geom_sf(data = ancestral_links, size = 0.5, aes(alpha = parent_time)) + geom_sf(data = sf::st_set_geometry(ancestral_links, "parent_location"), aes(color = parent_time)) + geom_sf(data = data[data$node_id == 0, ], size = 3, color = "red")

-

+

Conclusion diff --git a/docs/articles/vignette-08-nonslendr-tskit_files/figure-html/nonslendr_ancestries-1.png b/docs/articles/vignette-08-nonslendr-tskit_files/figure-html/nonslendr_ancestries-1.png index 22a3ddadb..37724ec4a 100644 Binary files a/docs/articles/vignette-08-nonslendr-tskit_files/figure-html/nonslendr_ancestries-1.png and b/docs/articles/vignette-08-nonslendr-tskit_files/figure-html/nonslendr_ancestries-1.png differ diff --git a/docs/articles/vignette-08-nonslendr-tskit_files/figure-html/nonslendr_locations-1.png b/docs/articles/vignette-08-nonslendr-tskit_files/figure-html/nonslendr_locations-1.png index c7d3d7ab1..c14d5aab9 100644 Binary files a/docs/articles/vignette-08-nonslendr-tskit_files/figure-html/nonslendr_locations-1.png and b/docs/articles/vignette-08-nonslendr-tskit_files/figure-html/nonslendr_locations-1.png differ diff --git a/docs/articles/vignette-08-nonslendr-tskit_files/figure-html/nonslendr_tree-1.png b/docs/articles/vignette-08-nonslendr-tskit_files/figure-html/nonslendr_tree-1.png index 0522a1a69..c4e56e146 100644 Binary files a/docs/articles/vignette-08-nonslendr-tskit_files/figure-html/nonslendr_tree-1.png and b/docs/articles/vignette-08-nonslendr-tskit_files/figure-html/nonslendr_tree-1.png differ diff --git a/docs/articles/vignette-09-paper.html b/docs/articles/vignette-09-paper.html index 52158bf55..e64ab3643 100644 --- a/docs/articles/vignette-09-paper.html +++ b/docs/articles/vignette-09-paper.html @@ -359,7 +359,7 @@

Script from panel A
 map <- world(xrange = c(-13, 70), yrange = c(18, 65), crs = 3035)
 #> Reading layer `ne_110m_land' from data source 
-#>   `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/Rtmp6dsC0I/naturalearth/ne_110m_land.shp' 
+#>   `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpdblWjc/naturalearth/ne_110m_land.shp' 
 #>   using driver `ESRI Shapefile'
 #> Simple feature collection with 127 features and 3 fields
 #> Geometry type: POLYGON
@@ -395,7 +395,7 @@ 

Script from panel A
 map <- world(xrange = c(-13, 70), yrange = c(18, 65), crs = 3035)
 #> Reading layer `ne_110m_land' from data source 
-#>   `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/Rtmp6dsC0I/naturalearth/ne_110m_land.shp' 
+#>   `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpdblWjc/naturalearth/ne_110m_land.shp' 
 #>   using driver `ESRI Shapefile'
 #> Simple feature collection with 127 features and 3 fields
 #> Geometry type: POLYGON
@@ -638,22 +638,22 @@ 

Run time of each code exam ex1 -5.919463 +9.1276798 mins ex2 -11.885701 +13.1026733 mins ex3 -2.055744 +2.2592016 mins ex4 -0.560190 +0.6743221 secs diff --git a/docs/articles/vignette-10-tracts.html b/docs/articles/vignette-10-tracts.html index d22a2f239..bee61b142 100644 --- a/docs/articles/vignette-10-tracts.html +++ b/docs/articles/vignette-10-tracts.html @@ -295,7 +295,7 @@

“Chromosome painting” of anc ggtitle("True ancestry tracts along each chromosome") + theme(axis.text.y = element_blank(), panel.grid = element_blank()) + facet_grid(pop ~ ., scales = "free_y")

-

+

By lining up NEA & DEN ancestry tracts in both EUR and PAP populations, we can see how the common origin of Neanderthal ancestry in both non-African populations manifests in a significant overlap of NEA diff --git a/docs/articles/vignette-10-tracts_files/figure-html/chrom_painting-1.png b/docs/articles/vignette-10-tracts_files/figure-html/chrom_painting-1.png index 62cfdd724..e13acadbd 100644 Binary files a/docs/articles/vignette-10-tracts_files/figure-html/chrom_painting-1.png and b/docs/articles/vignette-10-tracts_files/figure-html/chrom_painting-1.png differ diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml index 38e581aef..e269d68ec 100644 --- a/docs/pkgdown.yml +++ b/docs/pkgdown.yml @@ -1,4 +1,4 @@ -pandoc: 3.1.1 +pandoc: 3.1.11.1 pkgdown: 2.0.7 pkgdown_sha: ~ articles: @@ -13,7 +13,7 @@ articles: vignette-08-nonslendr-tskit: vignette-08-nonslendr-tskit.html vignette-09-paper: vignette-09-paper.html vignette-10-tracts: vignette-10-tracts.html -last_built: 2024-02-06T15:16Z +last_built: 2024-02-07T09:51Z urls: reference: https://www.slendr.net/reference article: https://www.slendr.net/articles diff --git a/docs/reference/join.html b/docs/reference/join.html index bd1705ac1..609058a4c 100644 --- a/docs/reference/join.html +++ b/docs/reference/join.html @@ -133,7 +133,7 @@

Examples real_map <- world(xrange = c(-15, 40), yrange = c(30, 60), crs = "EPSG:3035") #> Reading layer `ne_110m_land' from data source -#> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmphADFZn/naturalearth/ne_110m_land.shp' +#> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpFhhY5X/naturalearth/ne_110m_land.shp' #> using driver `ESRI Shapefile' #> Simple feature collection with 127 features and 3 fields #> Geometry type: POLYGON diff --git a/docs/reference/region.html b/docs/reference/region.html index 504dece32..78017f629 100644 --- a/docs/reference/region.html +++ b/docs/reference/region.html @@ -156,7 +156,7 @@

Examples real_map <- world(xrange = c(-15, 40), yrange = c(30, 60), crs = "EPSG:3035") #> Reading layer `ne_110m_land' from data source -#> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmphADFZn/naturalearth/ne_110m_land.shp' +#> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpFhhY5X/naturalearth/ne_110m_land.shp' #> using driver `ESRI Shapefile' #> Simple feature collection with 127 features and 3 fields #> Geometry type: POLYGON diff --git a/docs/reference/world.html b/docs/reference/world.html index 9c27d03a2..4b1f52886 100644 --- a/docs/reference/world.html +++ b/docs/reference/world.html @@ -167,7 +167,7 @@

Examples real_map <- world(xrange = c(-15, 40), yrange = c(30, 60), crs = "EPSG:3035") #> Reading layer `ne_110m_land' from data source -#> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmphADFZn/naturalearth/ne_110m_land.shp' +#> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpFhhY5X/naturalearth/ne_110m_land.shp' #> using driver `ESRI Shapefile' #> Simple feature collection with 127 features and 3 fields #> Geometry type: POLYGON diff --git a/docs/search.json b/docs/search.json index 3cc1c0337..daa194275 100644 --- a/docs/search.json +++ b/docs/search.json @@ -1 +1 @@ -[{"path":"https://www.slendr.net/LICENSE.html","id":null,"dir":"","previous_headings":"","what":"MIT License","title":"MIT License","text":"Copyright (c) 2022 Martin Petr Permission hereby granted, free charge, person obtaining copy software associated documentation files (“Software”), deal Software without restriction, including without limitation rights use, copy, modify, merge, publish, distribute, sublicense, /sell copies Software, permit persons Software furnished , subject following conditions: copyright notice permission notice shall included copies substantial portions Software. SOFTWARE PROVIDED “”, WITHOUT WARRANTY KIND, EXPRESS IMPLIED, INCLUDING LIMITED WARRANTIES MERCHANTABILITY, FITNESS PARTICULAR PURPOSE NONINFRINGEMENT. EVENT SHALL AUTHORS COPYRIGHT HOLDERS LIABLE CLAIM, DAMAGES LIABILITY, WHETHER ACTION CONTRACT, TORT OTHERWISE, ARISING , CONNECTION SOFTWARE USE DEALINGS SOFTWARE.","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"quick-installation","dir":"Articles","previous_headings":"","what":"Quick installation","title":"Installation instructions","text":"slendr available CRAN R package repository. , can install simply executing install.packages(\"slendr\") R console. want (need) get development version, can install directly GitHub executing devtools::install_github(\"bodkan/slendr\") via R package devtools (can gen devtools running install.packages(\"devtools\")). fact, decide try slendr, please make sure update regularly keep eye changelog regular basis! can find information latest bugfixes potential breaking changes. install slendr, calling library(slendr) check software dependencies available. , R package provide brief helpful guide resolve potential issues. rest vignette talks necessary software dependencies bit detail. Please note slendr extensively tested macOS Linux moment. However, experimental support runnig SLiM msprime simulations Windows analyzing tree-sequence outputs using tskit interface platform well. Feedback issues using slendr Windows highly appreciated.","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"software-dependencies","dir":"Articles","previous_headings":"","what":"Software dependencies","title":"Installation instructions","text":"slendr relies three main software dependencies: geospatial data analysis R package sf (encoding spatial slendr models analysing spatial tree-sequence data), forward population genetic simulator SLiM (forward simulations), Python modules tskit, msprime, pyslim (coalescent simulations tree-sequence analysis), also pandas used internally simulation back ends. three widely used respective fields , , easily obtainable major operating systems (see information troubleshoot potential problems). Note depending use case, three sets dependencies necessarily needed. ’re going running forward spatial simulations, don’t need SLiM geospatial R packages sf, stars, rnaturalearth. applies also animation spatial models using gganimate R package. slendr install dependencies. need functionality, install respective R packages manually. vignette, briefly explain get slendr’s software dependencies installed. said, note normal circumstances (exception SLiM), manual installation individual dependencies required.","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"sf-stars-rnaturalearth","dir":"Articles","previous_headings":"Software dependencies","what":"sf, stars, rnaturalearth","title":"Installation instructions","text":"R package sf heart geospatial data analysis R. available CRAN can installed major platforms executing install.packages(\"sf\") R session. applies stars rnaturalearth. first load slendr via library(slendr), ’re missing three geospatial R packages, notified instructed can easily obtain CRAN using single call install.packages(). said, sf depends number geospatial libraries depending exact setup Linux macOS machine, libraries missing. Luckily, easy install via Homebrew (macOS) via appropriate package manager Linux distribution (Ubuntu, Fedora, etc.). Detailed instructions operating system can found . ’re problems installation three packages, look help .","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"macos","dir":"Articles","previous_headings":"Software dependencies > sf, stars, rnaturalearth","what":"macOS","title":"Installation instructions","text":"One user recently installed slendr fresh macOS system reported needed install libgit2 order able install package devtools devtools::install_github(\"bodkan/slendr\") step described top page. Additionally, install couple C/C++ libraries well (dependencies sf package). end, able successfully install slendr running: Note assumes Homebrew package manager already setup Mac. ’re beginning computational scientist using Mac, strongly encourage install Homebrew. Sooner later need specific Linux/unix program anyway, Homebrew way get (Mac unix machine, without Homebrew poor one default).","code":"brew install libgit2 udunits gdal proj"},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"linux","dir":"Articles","previous_headings":"Software dependencies > sf, stars, rnaturalearth","what":"Linux","title":"Installation instructions","text":"Testing slendr installation fresh, pristine Debian installation dependencies previously installed, run following: ’s unlikely need (might need packages non-Debian distributions), got slendr dependencies running completely clean system. Might good start case trouble Linux machine. Windows special treatment necessary get slendr running. install slendr via install.packages(\"slendr\"), get binary version package dependencies without need compiling sources.","code":"sudo apt-get install libudunits2-dev libssl-dev libgdal-dev libgsl-dev libgit2-dev libfontconfig1-dev libharfbuzz-dev libfribidi-dev"},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"slim","dir":"Articles","previous_headings":"Software dependencies","what":"SLiM","title":"Installation instructions","text":"forward population genetic software SLiM available major software platforms. complete installation instructions can found . Mac, recommend installing SLiM via pkg installer available direct download website. Linux, can either install SLiM via appropriate package manager Linux distribution (see SLiM manual information), can easily compile . install SLiM Windows, please follow instructions section 2.3.1 SLiM manual. Note although SLiM also available conda, comes without SLiMgui! Note slendr requires SLiM 4.0 work earlier version. , running library(slendr) inform potential issues SLiM installation.","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"python","dir":"Articles","previous_headings":"Software dependencies","what":"Python","title":"Installation instructions","text":"order able run coalescent simulations process tree-sequence files, slendr needs Python modules tskit, msprime, pyslim (also needs pandas library). Setting isolated Python environment specific version Python packages (important avoid clashes among different Python programs needed system) can bit hassle users. especially true R users might use Python daily work. order make sure R package appropriate version Python available, correct versions Python module dependencies, slendr provides dedicated function setup_env() automatically downloads completely separate Python distribution installs required versions tskit, msprime, pyslim modules dedicated virtual environment. Moreover, Python installation virtual environment entirely isolated Python configurations already present user’s system, avoiding potential conflicts versions Python Python modules required slendr. Next time call library(slendr), need activate environment automatically calling init_env(). ’re comfortable Python don’t need worry beyond calling setup_env() init_env(), interaction Python necessary working slendr R.","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"failing-conda","dir":"Articles","previous_headings":"Software dependencies > Python","what":"Failing conda?","title":"Installation instructions","text":"order support Windows, slendr uses conda download Python interpreter explained . Given fact, run setup_env(), slendr tries leverage conda present install Python dependencies (msprime, tskit, pyslim, pandas) via conda . Unfortunately, conda can break frustratingly many random reasons completely trips setup_env(). run issue, fallback option install Python dependencies msprime, tskit, pyslim, pandas via pip , unlike conda, works practically every time. setup_env() fails conda-related reason, first clear broken environment calling clear_env(), restart R session, call setup_env(pip = TRUE) instead default setup_env(). Note might require install GSL numerical library, ’s trivial issue macOS (brew install gsl) Linux (Ubuntu, instance, sudo apt-get install libgsl-dev).","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"information-for-python-experts","dir":"Articles","previous_headings":"Software dependencies > Python","what":"Information for Python experts","title":"Installation instructions","text":"case wondering slendr accomplish : slendr’s Python interface implemented using R package reticulate. embeds Python interpreter inside R session, enabling high-performance interoperability languages without need user intervention.","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"docker","dir":"Articles","previous_headings":"","what":"Docker","title":"Installation instructions","text":"currently official Docker image slendr one soon. current plan use geospatial image published Rocker project (already contains pre-compiled R, RStudio, necessary R package dependencies sf ) extend slendr SLiM. Stay tuned!","code":""},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"motivation","dir":"Articles","previous_headings":"","what":"Motivation","title":"Introduction and basic tutorial","text":"motivation starting project create programmable simulation framework add explicit spatial dimension population genetics models. Specifically, original idea able take models one — representing simplified view history anatomically modern humans (AMH) West Eurasia last ~50 thousand years (comprehensive overview can found review Lazaridis)—design tool makes possible simulate models explicit geographical context capture processes similar following figure (taken study Haak et al. 2015): reason probably clear. lot studying history humans species focused reconstructing population movements, expansions gene flow events, happen geographic context. fact, geographic component often interested (.e., “ancestors population come ?”, “route fast migrate?”, etc.). However, goes beyond just simulating demographic history. instance, selection pressure driving adaptation can often spatially heterogeneous: members population occupying one part continent exposed different environmental pressure individuals elsewhere, allele frequency distributions shaped adaptation process reflect spatial heterogeneity accordingly. framework enables simulation explicitly spatial genomic data situations allow us build realistic models test specific hypotheses, goals simply possible using non-spatial simulation methods. R package slendr introduced vignette presents framework. Internally, package two independent tightly interconnected units: R interface provides set functional primitives (“mini-language” sorts) encoding various features spatio-temporal models: population migrations, expansions gene flow, happening real geographic landscape defined freely available cartographic data. Populations represented simple R objects easily visualized spatial boundaries, making possible build complex models interactively set small simple building blocks. SLiM simulation back end represented built-generic SLiM script designed read spatio-temporal model configuration parameters objects established step 1. , tailor simulation run user-defined model. Alternatively, slendr also supports executing standard population genetics models random-mating setting. means models need explicit geographic map can simulated either built-SLiM back end script, efficient msprime back end also provided package. important design objective make integration parts 1. 2. appear completely seamless. Even extremely complex models, model building execution (.e., simulation) can performed without leaving convenience R interface RStudio. simulation complexities happen automatically hood knowledge SLiM required. fact, motto slendr package “Write complex spatiotemporal population genetics models simple R script.”","code":""},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"geospatial-data","dir":"Articles","previous_headings":"","what":"Geospatial data","title":"Introduction and basic tutorial","text":"Geospatial analysis deep complex topic, dozens libraries programs designed deal fact Earth three-dimensional object forced plot geographical objects (, case, simulate data) two-dimensional plane. Luckily, technical issues Coordinate Reference Systems, transformations manipulation geometric objects (shifting population boundaries, expansions, etc.) pretty much solved now. Unfortunately, dealing issues practice quite challenging requires non-trivial degree domain expertise. Programming even simple task geospatial data analysis also often requires lot code. R package designed provide collection primitives (“mini-language” sorts) programming population dynamics (splits, movement, gene flow, expansion spatial boundaries) across space time without explicitly deal challenges inherent geospatial analyses.","code":""},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"installation-and-setup","dir":"Articles","previous_headings":"","what":"Installation and setup","title":"Introduction and basic tutorial","text":"slendr R package available CRAN can installed simply running install.packages(\"slendr\"). need run latest development version (instance, need latest bugfixes), can get via R package devtools executing devtools::install_github(\"bodkan/slendr\") R terminal. can find detailed installation instructions vignette. get slendr installed, just need load : dependencies (SLiM necessary Python modules) missing, get informative message proceed.","code":"library(slendr) # activate the internal Python environment needed for simulation and # tree-sequence processing init_env() #> The interface to all required Python modules has been activated."},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"defining-the-overall-world-map","dir":"Articles","previous_headings":"","what":"Defining the overall world map","title":"Introduction and basic tutorial","text":"anything else, need define section map world provide context downstream spatio-temporal manipulation population ranges. principle, source geospatial data can manipulated using simple features (sf) infrastructure used. now slendr package implicitly uses Natural Earth project data (vectorized form!), internally loads using rnaturalearth interface. first slendr function look map(). function load map entire world vectorized format zoom specified section world. Note call , specify coordinates zoom geographical Coordinate Reference System (CRS), longitude/latitude, also specified want perform downstream manipulation spatial population maps projected CRS (Lambert Azimuthal Equal-Area projection) appropriate representing wider European continent used tutorial. course, different CRS projections used based part world want simulate. Describing intricacies coordinate reference systems beyond scope tutorial, ’re interested learning encourage read freely available textbook dedicated topic. approach slendr: let user specify everything easy--understand longitude/latitude geographical CRS (can read map, making easy define spatial boundaries trajectories movement), internal data structures final exported spatial maps internally handled projected CRS, important make sure distances proportions distorted. Internally, map object currently normal sf class object without additional components. unlike slendr objects described , also sf objects carry additional internal components. Note summary object says “projected CRS: ETRS89-extended / LAEA Europe”. means world map indeed transformed projected CRS specified .","code":"map <- world( xrange = c(-13, 70), # min-max longitude yrange = c(18, 65), # min-max latitude crs = \"EPSG:3035\" # coordinate reference system (CRS) for West Eurasia ) map #> slendr 'map' object #> ------------------- #> map: internal coordinate reference system EPSG 3035 #> spatial limits (in degrees longitude and latitude): #> - vertical -13 ... 70 #> - horizontal 18 ... 65"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"plotting-geographic-features-and-population-ranges","dir":"Articles","previous_headings":"","what":"Plotting geographic features and population ranges","title":"Introduction and basic tutorial","text":"slendr package implements plotting function called plot_map(). order make easier convenient iteratively build complex models. function can intelligently decide (based given input arguments) right way present data user, helps define models quickly without relying lower-level mechanisms sf package. see examples plot_map() action .","code":""},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"defining-smaller-geographic-regions","dir":"Articles","previous_headings":"","what":"Defining smaller geographic regions","title":"Introduction and basic tutorial","text":"addition overall spatial map context, can also define smaller geographic boundaries. mostly useful whenever want restrict population’s movement (spatial population expansion) smaller region map intuitive geographic meaning (.e., Anatolia, West Eurasia, etc.). Note objects created population boundaries (yet anyway)! simply labels generic geographic boundaries can used later. attached population point. , object returned region() function actually sf object, carries additional annotation name region (“Anatolia”): However, object also carries additional class annotations purpose internal slendr machinery: Furthermore, note region() calls specified map object defined beginning. object added hidden attribute slendr object represents context geospatial transformations, expansions, plots. can use generic plot_map() function plot geographic regions context defined section world map: Note map object longer explicitly specified. needed, class objects provided plot_map() function must carry “map” attribute. fact, object must carry map context — slendr complains whenever case. can check component really , although hidden, using built-attr function verify map object created beginning:","code":"africa <- region( \"Africa\", map, polygon = list(c(-18, 20), c(38, 20), c(30, 33), c(20, 33), c(10, 38), c(-6, 35)) ) europe <- region( \"Europe\", map, polygon = list( c(-8, 35), c(-5, 36), c(10, 38), c(20, 35), c(25, 35), c(33, 45), c(20, 58), c(-5, 60), c(-15, 50) ) ) anatolia <- region( \"Anatolia\", map, polygon = list(c(28, 35), c(40, 35), c(42, 40), c(30, 43), c(27, 40), c(25, 38)) ) anatolia #> slendr 'region' object #> ---------------------- #> name: Anatolia #> #> map: internal coordinate reference system EPSG 3035 class(anatolia) #> [1] \"slendr\" \"slendr_region\" \"sf\" \"data.frame\" plot_map(africa, europe, anatolia, title = \"Geographic regions\") all(attr(europe, \"map\") == map) #> [1] TRUE all(attr(anatolia, \"map\") == map) #> [1] TRUE"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"defining-spatial-population-boundaries","dir":"Articles","previous_headings":"","what":"Defining spatial population boundaries","title":"Introduction and basic tutorial","text":"One aims slendr package formalize specification spatial population boundaries changes time. core function population(), takes population name, time want enforce population’s boundary, effective population size population time, map object described . also specify existing population specified population split (explicitly say ’s ancestral population). specifying actual spatial boundaries, several options.","code":""},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"polygon-population-ranges","dir":"Articles","previous_headings":"Defining spatial population boundaries","what":"Polygon population ranges","title":"Introduction and basic tutorial","text":"can define detailed population boundaries using polygon geometry object region object created region() function , using polygon = argument population(). , reminder, note coordinates described context geographic CRS. First, let’s create African ancestors modern humans. restrict spatial boundary African population africa region defined :","code":"afr <- population(\"AFR\", time = 52000, N = 3000, map = map, polygon = africa) plot_map(afr)"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"circular-population-ranges","dir":"Articles","previous_headings":"Defining spatial population boundaries","what":"Circular population ranges","title":"Introduction and basic tutorial","text":"want simulate abstract simple population boundary, can specify circular range center radius arguments instead polygon. distance units slendr package specified coordinate system given “world creation”. instance, EPSG 3035 (’re using ) specifies distances meters. define location population non-Africans right split African ancestors: call plot_map() function returned object, option either plot population range “raw” form “intersected” form, case raw boundary intersected “background” landscape (removing large bodies water, etc.). intersected form ultimately exported serialized format (see ) loaded spatial map SLiM. plot_map() function renders intersected population ranges default.","code":"ooa <- population( \"OOA\", parent = afr, time = 51000, N = 500, remove = 25000, center = c(33, 30), radius = 400e3 ) plot_map(ooa, intersect = TRUE, title = \"'Intersected' population range\")"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"population-movement-across-a-landscape","dir":"Articles","previous_headings":"","what":"Population movement across a landscape","title":"Introduction and basic tutorial","text":"describe directional population movement, can use function move(). accepts coordinates destination points along way (trajectory) duration migration, automatically generates number intermediate spatial maps along trajectory movement produce reasonable degree spatial continuity (number can also specified manually). can inspect object returned move() function see now contains just first YAM population range 7000 years ago, also ranges intermediate locations: Checking result visually , see: Let’s create population Eastern Hunter Gatherers (EHG), split first non-Africans 28000 years ago: ’re , let’s also create population Western Hunter Gatherers (WHG). people living region eventually became present day Europeans receiving gene flow groups time (see ), call “EUR” simplify modeling code little bit:","code":"ooa <- ooa %>% move( trajectory = list(c(40, 30), c(50, 30), c(60, 40)), start = 50000, end = 40000 ) ooa #> slendr 'population' object #> -------------------------- #> name: OOA #> habitat: terrestrial #> #> number of spatial maps: 28 #> map: internal coordinate reference system EPSG 3035 #> scheduled removal at time 25000 #> #> population history overview: #> - time 51000: split from AFR (N = 500) #> - time 50000-40000: movement across a landscape plot_map(ooa, title = \"Intermediate migration maps\") ehg <- population( \"EHG\", parent = ooa, time = 28000, N = 1000, remove = 6000, polygon = list( c(26, 55), c(38, 53), c(48, 53), c(60, 53), c(60, 60), c(48, 63), c(38, 63), c(26, 60)) ) eur <- population( # European population name = \"EUR\", parent = ehg, time = 25000, N = 2000, polygon = europe )"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"spatial-population-expansion","dir":"Articles","previous_headings":"","what":"Spatial population expansion","title":"Introduction and basic tutorial","text":"can simulate expanding range population using function expand_range(), accepts parameters specifying many kilometers boundary expand (argument), long expansion take (duration argument) many intermediate spatial map snapshots exported representing expansion (snapshots argument). instance, let’s represent expansion Anatolian farmers, also split OOA population 28000 years ago time split EHG population. Note use optional parameter, polygon, restricts expansion Europe, instead around Anatolia: Note , principle, specify entire spatio-temporal history population single pipeline using pipe operator %>%. , can inspect object returned expand_range() function see contains spatial maps (“snapshots”) expansion process across time: can () check results visually: visually see really going behind scenes, can also plot raw, non-intersected form expansion : can see population Anatolian farmers point invades spatial boundary EUR population. , doesn’t imply gene flow. section gene flow , see slendr implements gene flow overlapping (non-overlapping) populations. Let’s add couple populations migrations move implementing gene flow . Yamnaya steppe herders:","code":"ana <- population( # Anatolian farmers name = \"ANA\", time = 28000, N = 3000, parent = ooa, remove = 4000, center = c(34, 38), radius = 500e3, polygon = anatolia ) %>% expand_range( # expand the range by 2.500 km by = 2500e3, start = 10000, end = 7000, polygon = join(europe, anatolia) ) ana #> slendr 'population' object #> -------------------------- #> name: ANA #> habitat: terrestrial #> #> number of spatial maps: 16 #> map: internal coordinate reference system EPSG 3035 #> scheduled removal at time 4000 #> #> population history overview: #> - time 28000: split from OOA (N = 3000) #> - time 10000-7000: range expansion plot_map(ana, title = \"Anatolian expansion into Europe\") plot_map(ana, title = \"Anatolian expansion into Europe (not intersected)\", intersect = FALSE) yam <- population( # Yamnaya steppe population name = \"YAM\", time = 7000, N = 500, parent = ehg, remove = 2500, polygon = list(c(26, 50), c(38, 49), c(48, 50), c(48, 56), c(38, 59), c(26, 56)) ) %>% move( trajectory = c(15, 50), start = 5000, end = 3000, snapshots = 8 ) plot_map(yam)"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"plotting-multiple-slendr-objects","dir":"Articles","previous_headings":"","what":"Plotting multiple slendr objects","title":"Introduction and basic tutorial","text":"addition plotting individual population ranges, generic function plot_map() can handle combination population ranges, can also partition individual facets. useful visual inspection specified model, looking potential issues export individual spatio-temporal maps. Obviously, lot multi-dimensional information: see better way explore slendr model interactively.","code":"plot_map(afr, ooa, ehg, eur, ana, yam)"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"defining-gene-flow-events","dir":"Articles","previous_headings":"","what":"Defining gene flow events","title":"Introduction and basic tutorial","text":"way slendr implements gene flow events calling gene_flow() function. function straightforward interface, shown . One thing note default, populations gene flow events must overlapping spatial ranges order simulate gene flow. probably rather obvious, populations can’t mix space-time don’t overlap given point space-time. example, look spatial boundaries plotted , ’ll see European African populations don’t overlap population ranges. try instruct slendr simulate geneflow , get error: error message instructs us visually verify case, can done slendr’s plot_map() function optional parameter pop_facets = F (set TRUE default). Many models include multiple gene flow events, can collect simple R list: gene_flow() function simply returns data frame collecting geneflow parameters compile_model() step :","code":"gf <- gene_flow(from = eur, to = afr, rate = 0.1, start = 20000, end = 15000) Error: No overlap between population ranges of EUR and AFR at time 20000. Please check the spatial maps of both populations by running `plot_map(eur, afr)` and adjust them accordingly. Alternatively, in case this makes sense for your model, you can add `overlap = F` which will instruct slendr to simulate gene flow without spatial overlap between populations. gf <- list( gene_flow(from = ana, to = yam, rate = 0.5, start = 6500, end = 6400, overlap = FALSE), gene_flow(from = ana, to = eur, rate = 0.5, start = 8000, end = 6000), gene_flow(from = yam, to = eur, rate = 0.75, start = 4000, end = 3000) ) gf #> [[1]] #> from_name to_name tstart tend rate overlap #> 1 ANA YAM 6500 6400 0.5 FALSE #> #> [[2]] #> from_name to_name tstart tend rate overlap #> 1 ANA EUR 8000 6000 0.5 TRUE #> #> [[3]] #> from_name to_name tstart tend rate overlap #> 1 YAM EUR 4000 3000 0.75 TRUE"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"compile-the-whole-model-and-load-it-in-slim","dir":"Articles","previous_headings":"","what":"Compile the whole model and load it in SLiM","title":"Introduction and basic tutorial","text":"crucial function slendr compile_model(). takes population ranges defined across space time, together list gene flow events (optional, since models won’t include gene flow), proceeds converting vectorized spatial ranges raster bitmaps. Furthermore, compiles information split times, \\(N_e\\) values, gene flow directions, times, rates series tables. saved automatically dedicated directory format understood back end SLiM script provided slendr (). files model directory look like? Ideally, user never worry ; fact, whole purpose slendr let work much higher level abstraction without worrying low-level details. said, might find useful see things look like behind curtain… First , can inspect contents directory see , indeed, contain defined spatial maps (now PNG files, SLiM requires). also contains series tab-delimited configuration tables. tables contain summaries model parameters defined graphically , namely: table population splits: table geneflow events: finally, table populations whose spatial maps updated throughout simulation, well times updates (table rather large, ’re showing ). object returned compile_model() function (called model ) binds information together. fact, easier debugging sanity checking, carries locations tables (well important information) inside , elements list: model$splits, model$geneflows, etc. case ’d want separate model specification running different scripts, slendr includes function read_model() just purpose:","code":"model_dir <- paste0(tempfile(), \"_tutorial-model\") model <- compile_model( populations = list(afr, ooa, ehg, eur, ana, yam), # populations defined above gene_flow = gf, # gene-flow events defined above generation_time = 30, resolution = 10e3, # resolution in meters per pixel competition = 130e3, mating = 100e3, # spatial interaction in SLiM dispersal = 70e3, # how far will offspring end up from their parents path = model_dir ) list.files(model_dir, pattern = \"*.jpg\") #> character(0) read.table(file.path(model_dir, \"populations.tsv\"), header = TRUE) #> pop parent N tsplit_gen tsplit_orig tremove_gen tremove_orig #> 1 AFR __pop_is_ancestor 3000 1 52000 -1 -1 #> 2 OOA AFR 500 34 51000 901 25000 #> 3 EHG OOA 1000 801 28000 1534 6000 #> 4 ANA OOA 3000 801 28000 1601 4000 #> 5 EUR EHG 2000 901 25000 -1 -1 #> 6 YAM EHG 500 1501 7000 1651 2500 #> pop_id parent_id #> 1 0 -1 #> 2 1 0 #> 3 2 1 #> 4 3 1 #> 5 4 2 #> 6 5 2 read.table(file.path(model_dir, \"geneflow.tsv\"), header = TRUE) #> from to rate overlap tstart_gen tstart_orig tend_gen tend_orig from_id to_id #> 1 ANA YAM 0.50 0 1518 6500 1521 6400 3 5 #> 2 ANA EUR 0.50 1 1468 8000 1534 6000 3 4 #> 3 YAM EUR 0.75 1 1601 4000 1634 3000 5 4 loaded_model <- read_model(model_dir)"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"visualize-the-entire-history-of-splits-and-gene-flow","dir":"Articles","previous_headings":"","what":"Visualize the entire history of splits and gene flow","title":"Introduction and basic tutorial","text":"code snippets , defined simple history European populations last 50000 years. history includes population splits gene flow events, well demographic changes. slendr tries make formal specification spatio-temporal population dynamics concise possible, hard really visualize everything happen SLiM side simulation starts just code alone. purpose, package includes function named plot_model() takes information relationships populations (.e., population gene flow objects defined ) plots form -called admixture graph (see discussion admixture graph concept). One important thing note unlike traditional admixture graphs node/population present , full slendr graph single population can participate many gene flow events course history. visualized assigning color population, different nodes color represent snapshots time demographic event affecting population happens.","code":"plot_model(model, proportions = TRUE)"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"interactive-exploration-of-spatio-temporal-models","dir":"Articles","previous_headings":"","what":"Interactive exploration of spatio-temporal models","title":"Introduction and basic tutorial","text":"slightly fancier way visualize models implemented function explore_model(). function accepts compiled model parameter spawns R shiny-based browser app makes possible click time snapshots interactively visualize spatial maps time point.","code":"explore_model(model)"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"running-the-simulation","dir":"Articles","previous_headings":"","what":"Running the simulation","title":"Introduction and basic tutorial","text":"way feed entire serialized model SLiM slim() function, understands format model directory created compile_model() function generates SLiM script (using back end skeleton script part package can found calling system.file(\"scripts/script.slim\", package = \"slendr\"), case ’d like peek internals). output slendr simulation tree-sequence file (produced SLiM simulation behind scenes). tree sequence automatically loaded R returned user: lots slendr allows , terms simulation , also terms analyzing tree-sequence data. list provides list additional resources might want look .","code":"ts <- slim(model, sequence_length = 100000, recombination_rate = 1e-8) ts #> ╔═══════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════╣ #> ║Trees │ 130║ #> ╟───────────────┼───────╢ #> ║Sequence Length│ 100000║ #> ╟───────────────┼───────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼───────╢ #> ║Sample Nodes │ 10000║ #> ╟───────────────┼───────╢ #> ║Total Size │2.7 MiB║ #> ╚═══════════════╧═══════╝ #> ╔═══════════╤═════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪═════╪═════════╪════════════╣ #> ║Edges │18739│585.6 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Individuals│12841│ 1.2 MiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Nodes │18380│682.7 KiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Populations│ 6│ 2.6 KiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Provenances│ 1│ 34.7 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧═════╧═════════╧════════════╝"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"more-information","dir":"Articles","previous_headings":"","what":"More information","title":"Introduction and basic tutorial","text":"vignette described basic features slendr package already quite long. much slendr demonstrated . instance: can tweak parameters influencing dispersal dynamics (“clumpy” populations , far offspring can migrate parents, etc.) change dynamics evolve time. See vignette information. can use slendr program non-spatial models, means standard, Wright-Fisher demographic model can simulated lines R code , instance, plugged Approximate Bayesian Computation pipeline analyses leveraging readily available R packages. can find vignette much detailed example vignette SLiM msprime back ends. can build complex spatial models still abstract (assuming real geographic location), including traditional simulations demes lattice structure. complete example shown vignette. SLiM saves data .trees tree-sequence file format, thanks R package reticulate interfacing Python code incredible power tskit pyslim process simulated data massive scale right fingertips, within convenient environment R. See much detailed example vignette vignette extensive tutorial feature.","code":""},{"path":"https://www.slendr.net/articles/vignette-02-grid-model.html","id":"simple-two-dimensional-grid-model","dir":"Articles","previous_headings":"","what":"Simple two-dimensional grid model","title":"Demes on a regular spatial grid","text":"First, let’s load slendr R package create two-dimensional abstract world map: Next, define helper function ) create single slendr population object, b) place population appropriate coordinate lattice world map based numeric identifier population (runs 1 \\(n \\times n\\) , n total number demes along one side regular grid): defined population construction function, let’s build model. Let’s say want create regular grid n × n populations, N individuals population: Let’s plot whole spatial population configuration, make sure set things correctly: far, way model specified, population stuck circular “island”. can change programming gene flow events using slendr function gene_flow(). , let’s first program simple helper function generate gene flow events according neighborhood relationships two-dimensional grid, allowing population exchange migrants neighbors (making sure coordinates population stay within grid using simple modulo arithmetic population index ). Let’s test function. gene flow events population lower left corner grid (, first population series)? everything works, population allowed exchange migrants neighbor right (population number 2) neighbor . Looks right! Let’s generate entire set continuous gene flow events: total number individual gene flow events : Finally, can compile whole model: familiar SLiM manual recognize model described section 5.3.3. Finally, can run simulation using slim() function.","code":"library(slendr) init_env() #> The interface to all required Python modules has been activated. map <- world( xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\" ) create_pop <- function(i, n_side, map, N, radius) { # get dimensions of the world map dim <- c(diff(attr(map, \"xrange\")), diff(attr(map, \"yrange\"))) # position of the i-th population on the two-dimensional lattice grid coords <- c((i - 1) %% n_side, (i - 1) %/% n_side) center <- coords / n_side * dim + dim / (2 * n_side) pop <- tryCatch({ population( name = sprintf(\"pop%d\", i), N = N, time = 1, map = map, center = center + c(attr(map, \"xrange\")[1], attr(map, \"yrange\")[1]), radius = radius ) }, error = function(e) NULL) pop } n <- 5 populations <- seq(1, n * n) %>% lapply(create_pop, n_side = n, map = map, N = 100, radius = 40) do.call(plot_map, populations) + ggplot2::theme(legend.position = \"none\") set_geneflow <- function(i, n_side, rate, start, end, populations) { pop <- populations[[i]] # get the position of the i-th population on the n*n grid coords <- c((i - 1) %% n_side, (i - 1) %/% n_side) # get coordinates of the i-th population's neighbors on the grid neighbor_pos <- list( c(coords[1] - 1, coords[2]), c(coords[1] + 1, coords[2]), c(coords[1], coords[2] + 1), c(coords[1], coords[2] - 1) ) # generate geneflow events for population coordinates inside the grid geneflows <- lapply(neighbor_pos, function(pos) { if (any(pos < 0 | pos >= n_side)) return(NULL) neighbor <- populations[[pos[2] * n_side + pos[1] + 1]] if (is.null(neighbor)) return(NULL) rbind( gene_flow(from = pop, to = neighbor, rate = rate, start = start, end = end, overlap = FALSE), gene_flow(from = neighbor, to = pop, rate = rate, start = start, end = end, overlap = FALSE) ) }) %>% do.call(rbind, .) geneflows } set_geneflow(1, n, rate = 0.1, start = 2, end = 1000, populations) #> from_name to_name tstart tend rate overlap #> 1 pop1 pop2 2 1000 0.1 FALSE #> 2 pop2 pop1 2 1000 0.1 FALSE #> 3 pop1 pop6 2 1000 0.1 FALSE #> 4 pop6 pop1 2 1000 0.1 FALSE geneflows <- seq(1, n * n) %>% lapply(set_geneflow, n, rate = 0.05, start = 2, end = 1000, populations) %>% do.call(rbind, .) %>% unique # filter out duplicate events due to symmetries nrow(geneflows) #> [1] 80 model <- compile_model( populations = populations, gene_flow = geneflows, generation_time = 1, resolution = 10, competition = 10, mating = 10, dispersal = 10, simulation_length = 1000 ) ts <- slim(model, sequence_length = 10000, recombination_rate = 0) # simulate a single 10kb locus ts #> ╔═══════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════╣ #> ║Trees │ 1║ #> ╟───────────────┼───────╢ #> ║Sequence Length│ 10000║ #> ╟───────────────┼───────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼───────╢ #> ║Sample Nodes │ 5000║ #> ╟───────────────┼───────╢ #> ║Total Size │1.3 MiB║ #> ╚═══════════════╧═══════╝ #> ╔═══════════╤════╤═════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪═════════╪════════════╣ #> ║Edges │9042│282.6 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Individuals│6310│617.8 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Nodes │9068│337.2 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Populations│ 25│ 5.7 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Provenances│ 1│ 34.6 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧════╧═════════╧════════════╝"},{"path":"https://www.slendr.net/articles/vignette-02-grid-model.html","id":"population-grid-on-a-real-geographic-landscape","dir":"Articles","previous_headings":"","what":"Population grid on a real geographic landscape","title":"Demes on a regular spatial grid","text":"can take things one step . wanted similar thing (.e. simulate regularly spaced demes) real geographic context? Let’s zoom interesting part world create grid demes using helper function create_pop defined (population boundary 300 km diameter): course, lay regular grid across map world, population boundaries fall outside African continent. solve issue, go list populations filter least 50% area land, using another helper function: Let’s plot layout population grid real geographic background: Next, probably set scenario gene flow subpopulations; perhaps interested studying selected allele spreads continent based factors interest. , simulate data spatial model, first compile_model() run SLiM via slim() function. Given process described example , won’t repeating .","code":"map <- world( xrange = c(-25, 55), yrange = c(-32, 35), crs = 4326 ) n <- 20 populations <- seq(1, n * n) %>% lapply(create_pop, n_side = n, map = map, N = 100, radius = 1.5) continent <- region( map = map, polygon = list( c(-10, 35), c(-20, 20), c(-15, 8), c(-10, 5), c(0, 2), c(20, -40), c(35, -32), c(50, -25), c(55, -10), c(50, 0), c(53, 13), c(45, 10), c(37, 20), c(32, 30), c(16, 38), c(0, 38) ) ) check_area <- function(pop, map, continent) { if (is.null(pop)) return(NULL) # total population area pop_area <- area(pop)$area # population area overlapping a map map_area <- area(overlap(pop, map)) # population area overlapping African continent continent_area <- area(overlap(pop, continent)) # at least 50% of population's boundary be on land, and it must fall # on to the African continent itself if (continent_area == 0 || (map_area / pop_area) < 0.5) return(NULL) else return(pop) } filtered <- lapply(populations, check_area, map, continent) %>% Filter(Negate(is.null), .) do.call(plot_map, filtered) + ggplot2::theme(legend.position = \"none\")"},{"path":"https://www.slendr.net/articles/vignette-02-grid-model.html","id":"more-customized-spatial-model","dir":"Articles","previous_headings":"","what":"More customized spatial model","title":"Demes on a regular spatial grid","text":"want introduce spatiality model need manual control position subpopulation, can course customize spatial layout much detail. Consider followin map South America: Let’s lay demes scattered, irregular fashion. illustration purposes, define population’s geographic range circle radius 200 km. Importantly, note introduced one ancestral population population associated location world map! want simulate data coalescent backend, formally encode population genealogies eventually coalesce. words, models specified run msprime() back end contain isolated demes formally descend single ancestor run models msprime, get error infinite coalescent times. formally introduce ancestral population : Furthermore, let’s say fairly good idea complex interaction/gene-flow network deme, can encode like (instead forcing regular arrangement demes gene-flow interactions previous examples): Now can compile model `twist, however: try simulate data non-spatial way using msprime, skip serialization model data disk, skipping spatial interaction dispersal parameters. words, care simulating demographic model traditional, Wright-Fisher, random-mating demes gene flow , dispersal within individual deme. ? Mostly just demonstrate possible! However, certainly situations “half-spatial” model useful – instance, situation within-deme individual dynamics interest, location subpopulation . can make sure demographic model specified correctly quickly visualizing : can also plot spatial organization demes map glory, including gene flow events (one arrow per unidirectional gene flow). Note get warning message stating (non-spatial) ancestral population won’t visualized map: Finally, can simulate tree sequence model! Notice simulating data using msprime(), effectively dropping continuous space dimension model. situation, map serves visual aid, making easier set complex “spatial” position demes map.","code":"xrange <- c(-90, -20) yrange <- c(-58, 15) map <- world(xrange = xrange, yrange = yrange, crs = \"EPSG:31970\") #> Reading layer `ne_110m_land' from data source #> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/Rtmpug1qnH/naturalearth/ne_110m_land.shp' #> using driver `ESRI Shapefile' #> Simple feature collection with 127 features and 3 fields #> Geometry type: POLYGON #> Dimension: XY #> Bounding box: xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513 #> Geodetic CRS: WGS 84 plot_map(map) # non-spatial ancestral population p_anc <- population(\"p_anc\", N = 1000, time = 1) # spatial populations p1 <- population(\"p1\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-75, 0), radius = 200e3) p2 <- population(\"p2\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-60, 5), radius = 200e3) p3 <- population(\"p3\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-65, -5), radius = 200e3) p4 <- population(\"p4\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-60, -20), radius = 200e3) p5 <- population(\"p5\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-65, -35), radius = 200e3) p6 <- population(\"p6\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-69, -42), radius = 200e3) p7 <- population(\"p7\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-51, -10), radius = 200e3) p8 <- population(\"p8\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-45, -15), radius = 200e3) p9 <- population(\"p9\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-71, -12), radius = 200e3) p10 <- population(\"p10\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-55, -25), radius = 200e3) gf <- list( gene_flow(p1, p2, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p2, p1, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p1, p3, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p3, p1, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p2, p3, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p3, p2, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p2, p7, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p7, p2, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p3, p7, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p7, p3, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p7, p8, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p8, p7, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p4, p7, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p7, p4, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p4, p5, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p5, p4, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p5, p6, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p6, p5, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p3, p4, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p4, p3, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p1, p9, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p9, p1, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p3, p9, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p9, p3, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p4, p9, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p9, p4, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p10, p4, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p4, p10, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p10, p8, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p8, p10, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p10, p5, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p5, p10, 0.1, 1000, 2000, overlap = FALSE) ) model <- compile_model( populations = list(p_anc, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), gene_flow = gf, generation_time = 1, simulation_length = 5000, serialize = FALSE ) #> Warning: Model containing a mix of spatial and non-spatial populations will be compiled. #> Although this is definitely supported, make sure this is really what you want. #> Warning: Spatial models must be serialized to disk for SLiM to simulate data from. #> Compiled like this, your model can only be simulated with msprime. plot_model(model) plot_map(model, gene_flow = TRUE) #> Warning: All gene-flow event will be visualized at once. If you wish to visualize #> gene flows at a particular point in time, use the `time` argument. #> Warning: Non-spatial populations in your model won't be visualized ts <- msprime(model, sequence_length = 10e6, recombination_rate = 1e-8, random_seed = 42) ts #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 34057║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 10000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 22000║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 9.4 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │182742│ 5.6 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 11000│300.8 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │ 74344│ 2.0 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 11│605 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 1│ 10.5 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧══════╧═════════╧════════════╝"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"setting-up-python-environment","dir":"Articles","previous_headings":"","what":"Setting up Python environment","title":"Tree-sequence processing and statistics","text":"First, order able interface tskit pyslim using reticulate package (run simulations using msprime, ), need working Python environment required Python modules pyslim, tskit msprime already installed. setting Python environments can quite hassle, slendr provides single function setup_env() make things easier. call without arguments, slendr automatically download, install, setup completely separate Python environment (based “miniconda” distribution) just slendr activate background. important stress setup_env() interfere way Python installations might already computer. Python installation environment entirely isolated used just purpose slendr workflows. Python environment set , can activate calling: can use another built-function check_env() make sure slendr installed configured correct environment us: Now ’re good go ready simulate analyse tree sequence outputs R!","code":"setup_env() init_env() #> The interface to all required Python modules has been activated. check_env() #> Summary of the currently active Python environment: #> #> Python binary: /Users/mp/Library/r-miniconda-arm64/envs/Python-3.12_msprime-1.3.0_tskit-0.5.6_pyslim-1.0.4_tspop-0.0.2/bin/python #> Python version: 3.12.1 | packaged by conda-forge | (main, Dec 23 2023, 08:01:35) [Clang 16.0.6 ] #> #> slendr requirements: #> - tskit: version 0.5.6 ✓ #> - msprime: version 1.3.0 ✓ #> - pyslim: version 1.0.4 ✓ #> - tspop: present ✓"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"model-of-neanderthal-introgression-into-eurasians","dir":"Articles","previous_headings":"Setting up Python environment","what":"Model of Neanderthal introgression into Eurasians","title":"Tree-sequence processing and statistics","text":"First, let’s set simple non-spatial model Neanderthal introgression using slendr. essentially procedure shown another vignette introducing non-spatial slendr models. different spatial model, except left map argument calling population(). ’s toy model visualized “demographic graph” sorts (.e., tree-like structure specifying population splits additional edges representing gene flow events). particularly illuminating simple example, ’s always worth keeping mind graph embedded within every slendr model can always invoked make sure model ’re setting correct:","code":"library(ggplot2) library(dplyr) #> #> Attaching package: 'dplyr' #> The following objects are masked from 'package:stats': #> #> filter, lag #> The following objects are masked from 'package:base': #> #> intersect, setdiff, setequal, union set.seed(314159) # create the ancestor of everyone and a chimpanzee outgroup # (we set both N = 1 to reduce the computational time for this model) chimp <- population(\"CH\", time = 6.5e6, N = 1000) # two populations of anatomically modern humans: Africans and Europeans afr <- population(\"AFR\", parent = chimp, time = 6e6, N = 10000) eur <- population(\"EUR\", parent = afr, time = 70e3, N = 5000) # Neanderthal population splitting at 600 ky ago from modern humans # (becomes extinct by 40 ky ago) nea <- population(\"NEA\", parent = afr, time = 600e3, N = 1000, remove = 40e3) # 3% Neanderthal introgression into Europeans between 55-50 ky ago gf <- gene_flow(from = nea, to = eur, rate = 0.03, start = 55000, end = 45000) model <- compile_model( populations = list(chimp, nea, afr, eur), gene_flow = gf, generation_time = 30, path = paste0(tempfile(), \"_introgression\") ) cowplot::plot_grid( plot_model(model, sizes = FALSE), plot_model(model, sizes = FALSE, log = TRUE), nrow = 1 )"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"scheduling-of-sampling-events","dir":"Articles","previous_headings":"","what":"Scheduling of sampling events","title":"Tree-sequence processing and statistics","text":"Now defined model, sample data ? Ideally, like schedule sampling events given time, sampling defined number individuals given population. slendr provides function schedule_sampling() serves define sampling schedule automatically enforces populations already (.e. appearance simulation) still (removed simulation) present sampled . example, want sample two Neanderthal individuals (older one Altai Neanderthal published Pruefer et al. 2014, younger one Vindija Neanderthal published Pruefer et al., 2017). two genomes need estimate Neanderthal ancestry proportion using -called \\(f_4\\)-ratio statistic (, also see Petr et al., PNAS 2019): can see, schedule_sampling() function simply accepts vector times remembering schedule, list pairs (, ) encoding populations many individuals remembered time points given times vector. Next, want sample present-day individuals: outgroup representing chimpanzee, couple Africans Europeans: can see , schedule_sampling() function returns plain old data frame simple structure three columns: time, population name, number individuals. means can define sampling events using whatever input data might already available (radiocarbon-dated ancient DNA samples Excel sheet publication). instance, lot interest estimate trajectory Neanderthal ancestry Europe time using ancient DNA data anatomically modern human individuals (also called early modern humans, EMH) across last couple tens thousands years. can simulate something close available EMH ancient DNA data set last 50 thousand years running : samples single ancient European individuals randomly chosen times 40 10 ky ago. One nice feature schedule_sampling() function schedules sampling events population, population present simulation given time. makes possible simply take wide time range sampling, specify populations sizes samples, let function generate sampling events populations present time. reason stricter control sampling required, behavior can switched setting strict = TRUE like : Now already model object ready, can simulate data , sampling individuals according sampling schedule. Although use slim() function shown previous vignettes, case run simulation msprime() coalescent back end. , model non-spatial using coalescent simulator much efficient forward simulation. Switching msprime SLiM back ends slendr demonstrated much detail dedicated vignette. simulation back end utilized msprime() function (well slim() function) produces tree-sequence output immediately loaded ready downstream analysis. Note bind individual sampling schedule data frames using rbind function provided base R (show , sampling schedule really just data frame can manipulate ).","code":"nea_samples <- schedule_sampling(model, times = c(70000, 40000), list(nea, 1)) nea_samples #> # A tibble: 2 × 7 #> time pop n y_orig x_orig y x #> #> 1 40000 NEA 1 NA NA NA NA #> 2 70000 NEA 1 NA NA NA NA present_samples <- schedule_sampling(model, times = 0, list(chimp, 1), list(afr, 5), list(eur, 10)) present_samples #> # A tibble: 3 × 7 #> time pop n y_orig x_orig y x #> #> 1 0 CH 1 NA NA NA NA #> 2 0 AFR 5 NA NA NA NA #> 3 0 EUR 10 NA NA NA NA emh_samples <- schedule_sampling(model, times = runif(n = 40, min = 10000, max = 40000), list(eur, 1)) emh_samples #> # A tibble: 40 × 7 #> time pop n y_orig x_orig y x #> #> 1 10320 EUR 1 NA NA NA NA #> 2 11188 EUR 1 NA NA NA NA #> 3 11396 EUR 1 NA NA NA NA #> 4 11529 EUR 1 NA NA NA NA #> 5 11927 EUR 1 NA NA NA NA #> 6 12675 EUR 1 NA NA NA NA #> 7 13689 EUR 1 NA NA NA NA #> 8 13744 EUR 1 NA NA NA NA #> 9 14775 EUR 1 NA NA NA NA #> 10 16362 EUR 1 NA NA NA NA #> # ℹ 30 more rows # this attempts to sample a Neanderthal individual at a point when Neanderthals # are already extinct, resulting in an error schedule_sampling(model, times = 10000, list(nea, 1), strict = TRUE) Error: Cannot schedule sampling for 'NEA' at time 10000 because the population will not be present in the simulation at that point. Consider running this function with `strict = FALSE` which will automatically retain only valid sampling events. ts <- msprime( model, sequence_length = 100e6, recombination_rate = 1e-8, samples = rbind(nea_samples, present_samples, emh_samples), random_seed = 314159, verbose = TRUE ) #> -------------------------------------------------- #> msprime command: #> #> /Users/mp/Library/r-miniconda-arm64/envs/Python-3.12_msprime-1.3.0_tskit-0.5.6_pyslim-1.0.4_tspop-0.0.2/bin/python /private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpYADxQ3/file122e5348d0ae_introgression/script.py --seed 314159 --model /private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpYADxQ3/file122e5348d0ae_introgression --output /var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpYADxQ3/file122e57375f75f.trees --sequence-length 100000000 --recombination-rate 1e-08 --sampling-schedule /var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpYADxQ3/file122e550be251a --verbose #> -------------------------------------------------- #> #> Tree sequence was saved to: #> /var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpYADxQ3/file122e57375f75f.trees #> Loading the tree-sequence file... ts #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 240041║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 116║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 40.0 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │916588│ 28.0 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 58│ 1.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │189654│ 5.1 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 1│ 7.0 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧══════╧═════════╧════════════╝"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"r-interface-for-tskit-and-pyslim","dir":"Articles","previous_headings":"","what":"R interface for tskit and pyslim","title":"Tree-sequence processing and statistics","text":"Tree-sequences one revolutionary developments population genetics last couple decades number reasons. One possibility store extremely large data sets succinctly encoding entire evolutionary history sample individuals series correlated tree genealogies along genome. Going much detail topic clearly beyond scope tutorial, especially everything explain much better elsewhere. Instead, demonstrate rest vignette can access manipulate tree-sequence outputs generated slendr models perform various statistics using Python modules tskit pyslim directly slendr, without leave R! key magical R package reticulate creates seamless binding Python modules R. means even don’t know Python, slendr allows quite lot tree-sequences R. course, proficient Python user, needs said tree-sequence file generated slendr & SLiM, can easily perform every conceivable analysis directly using tskit. intention show can continue working tree-sequence files R even run entire slendr simulation.","code":""},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"loading-and-processing-tree-sequence-output-files","dir":"Articles","previous_headings":"","what":"Loading and processing tree-sequence output files","title":"Tree-sequence processing and statistics","text":"default, msprime() slim() run produce tree-sequence object (saved temporary file) immediately load . Thus, use-cases, explicit loading simulated tree sequence needed. said, sake completeness, let’s run simulation specify custom path tree-sequence file . case tree-sequence output saved custom location disk, can load tree sequence using slendr function ts_load(). ’re dealing tree sequence produced SLiM back end (case ), can also instruct function simplify tree-sequence individuals explicitly sampled (recall sampling schedule set schedule_sampling() function ). Note provide model object generated compile_model() order model annotation information simulated tree-sequence data (, loading): surprisingly, get output got printed tree sequence returned msprime() function. shows normal circumstances, loading output manually via ts_load() needed. try simplify msprime-generated tree sequence, get warning. tree sequence already simplified form, definition coming coalescent simulator. default, simplification trims tree sequence remembered individuals (.e. explicitly scheduled sampling), true every msprime tree sequence. Alternatively, can also narrow simplification defined set individuals using simplify_to = argument. Internally, simplification implemented dedicated function ts_simplify() can always call explicitly, like : Similarly, slendr provides function ts_recapitate() performs [recapitation]https://tskit.dev/pyslim/docs/latest/tutorial.html#recapitation). , needed msprime tree sequence, fully coalesced (recapitated) definition. current tree sequence object, simply get warning informing us ’re attempting something effect: can make sure tree sequence fully coalesced calling another slendr function ts_coalesced(). useful dealing slim()-produced tree sequences: might noticed simulate mutations SLiM run. computational efficiency. Luckily, tree-sequence contains complete history sample individuals makes easy sprinkle mutations genealogies simulation . can add mutations given rate running: processed simulated tree sequence, can calculate basic statistics simulated data. However, , first like note everything rest vignette (.e. whenever call function prefix ts_*() slendr), interfacing tskit Python module hood. goal capture analyses one might want perform tree-sequences R wrap neat interface indistinguishable R function—, , reason reticulate created first place (making various Python data science modules appear regular R packages).","code":"output_file <- tempfile() ts <- msprime( model, sequence_length = 100e6, recombination_rate = 1e-8, samples = rbind(nea_samples, present_samples, emh_samples), output = output_file, random_seed = 314159 ) output_file #> [1] \"/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpYADxQ3/file122e534b363bf\" ts <- ts_load(output_file, model) ts #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 240041║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 116║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 40.0 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │916588│ 28.0 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 58│ 1.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │189654│ 5.1 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 1│ 7.0 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧══════╧═════════╧════════════╝ ts_simplify(ts) #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 238681║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 116║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 36.7 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │864772│ 26.4 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 58│ 1.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │139203│ 3.7 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 2│ 7.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧══════╧═════════╧════════════╝ ts_small <- ts_simplify(ts, simplify_to = c(\"CH_1\", \"NEA_1\", \"NEA_2\", \"AFR_1\", \"AFR_2\", \"EUR_20\", \"EUR_50\")) ts_small #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 132496║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 14║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 19.0 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │441206│ 13.5 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 7│220 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │ 79249│ 2.1 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 2│ 7.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧══════╧═════════╧════════════╝ ts <- ts_recapitate(ts, recombination_rate = 1e-8, Ne = 10000) ts_coalesced(ts) #> [1] TRUE ts <- ts_mutate(ts, mutation_rate = 1e-8, random_seed = 314159) ts #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 240041║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 116║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 76.8 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │916588│ 28.0 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 58│ 1.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │623249│ 22.0 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │189654│ 5.1 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 2│ 7.8 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │621331│ 14.8 MiB│ No║ #> ╚═══════════╧══════╧═════════╧════════════╝"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"visualisation-of-trees-and-tree-sequences","dir":"Articles","previous_headings":"","what":"Visualisation of trees and tree-sequences","title":"Tree-sequence processing and statistics","text":"Now introduce function ts_phylo() can used extract one tree tree-sequence (either -th tree sequence, tree overlapping -th position simulated genome, depending value mode argument) convert phylo class, standard format phylogenetic trees R world. phylo format, see packages ape, phangorn, phytools. type tree object R console, can verify got ordinary phylo object: means whole R phylogenetic ecosystem disposal analyze trees. instance can use powerful package ggtree plot tree just extracted:","code":"# extract the 42nd tree in the tree sequence tree <- ts_phylo(ts_small, 42 - 1) #> Starting checking the validity of tree... #> Found number of tips: n = 14 #> Found number of nodes: m = 13 #> Done. tree #> #> Phylogenetic tree with 14 tips and 13 internal nodes. #> #> Tip labels: #> 13 (EUR_50), 12 (EUR_50), 11 (CH_1), 10 (CH_1), 9 (AFR_2), 8 (AFR_2), ... #> Node labels: #> 77386, 70, 2699, 5175, 5199, 6642, ... #> #> Rooted; includes branch lengths. library(ggtree) #> ggtree v3.10.0 For help: https://yulab-smu.top/treedata-book/ #> #> If you use the ggtree package suite in published research, please cite #> the appropriate paper(s): #> #> Guangchuang Yu, David Smith, Huachen Zhu, Yi Guan, Tommy Tsan-Yuk Lam. #> ggtree: an R package for visualization and annotation of phylogenetic #> trees with their covariates and other associated data. Methods in #> Ecology and Evolution. 2017, 8(1):28-36. doi:10.1111/2041-210X.12628 #> #> Guangchuang Yu. Data Integration, Manipulation and Visualization of #> Phylogenetic Trees (1st edition). Chapman and Hall/CRC. 2022, #> doi:10.1201/9781003279242 #> #> G Yu. Data Integration, Manipulation and Visualization of Phylogenetic #> Trees (1st ed.). Chapman and Hall/CRC. 2022. ISBN: 9781032233574 ggtree(tree) + geom_point2(aes(subset = !isTip)) + # points for internal nodes geom_tiplab() + # sample labels for tips hexpand(0.1) # make more space for the tip labels library(ape) plot(tree) nodelabels()"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"accessing-tskit-functionality-directly","dir":"Articles","previous_headings":"","what":"Accessing tskit functionality directly","title":"Tree-sequence processing and statistics","text":"mentioned previous section, goal vignette show use slendr perform main tree-sequence operations using convenient R interface tskit. However, always keep mind restricted subset tskit functionality slendr translated R (.e. functions prefix ts_). Thanks incredible R package reticulate, can access Python methods object variables directly, using $ operator. example, instead calling function ts_coalesced() tree-sequence , check trees coalesced running following snippet instead (note inefficient ’re operation first one hundred trees): believe makes sense use R interface whenever possible (even makes many operations little bit convenient). However, functionality slendr missing, can always resort accessing Python objects directly just demonstrated. can verify methods attributes Python tree-sequence object still accessible R: fact, recognize elements output examples involving ts_ functions vignette! short, blackbox—slendr provides slightly convenient layer tskit R users.","code":"# iterate over all trees in the tree-sequence and check if each # has only one root (i.e. is fully coalesced) - note that Python # lists are 0-based, which is something we need to take care of all(sapply(seq_len(ts$num_trees)[1:100], function(i) ts$at_index(i - 1)$num_roots == 1)) names(ts) #> [1] \"alignments\" \"allele_frequency_spectrum\" #> [3] \"as_fasta\" \"as_nexus\" #> [5] \"as_vcf\" \"aslist\" #> [7] \"at\" \"at_index\" #> [9] \"breakpoints\" \"check_index\" #> [11] \"coalescence_time_distribution\" \"coiterate\" #> [13] \"count_topologies\" \"decapitate\" #> [15] \"delete_intervals\" \"delete_sites\" #> [17] \"diffs\" \"discrete_genome\" #> [19] \"discrete_time\" \"divergence\" #> [21] \"divergence_matrix\" \"diversity\" #> [23] \"draw_svg\" \"draw_text\" #> [25] \"dump\" \"dump_tables\" #> [27] \"dump_text\" \"edge\" #> [29] \"edge_diffs\" \"edges\" #> [31] \"edges_child\" \"edges_left\" #> [33] \"edges_parent\" \"edges_right\" #> [35] \"edgesets\" \"equals\" #> [37] \"f2\" \"f3\" #> [39] \"f4\" \"file_uuid\" #> [41] \"first\" \"Fst\" #> [43] \"genealogical_nearest_neighbours\" \"general_stat\" #> [45] \"genetic_relatedness\" \"genetic_relatedness_weighted\" #> [47] \"genotype_matrix\" \"get_ll_tree_sequence\" #> [49] \"get_num_mutations\" \"get_num_nodes\" #> [51] \"get_num_records\" \"get_num_sites\" #> [53] \"get_num_trees\" \"get_pairwise_diversity\" #> [55] \"get_population\" \"get_sample_size\" #> [57] \"get_samples\" \"get_sequence_length\" #> [59] \"get_time\" \"haplotypes\" #> [61] \"has_reference_sequence\" \"ibd_segments\" #> [63] \"impute_unknown_mutations_time\" \"indexes_edge_insertion_order\" #> [65] \"indexes_edge_removal_order\" \"individual\" #> [67] \"individual_locations\" \"individual_populations\" #> [69] \"individual_times\" \"individuals\" #> [71] \"individuals_flags\" \"individuals_location\" #> [73] \"individuals_population\" \"individuals_time\" #> [75] \"kc_distance\" \"keep_intervals\" #> [77] \"last\" \"ll_tree_sequence\" #> [79] \"load\" \"load_tables\" #> [81] \"ltrim\" \"max_root_time\" #> [83] \"max_time\" \"mean_descendants\" #> [85] \"metadata\" \"metadata_schema\" #> [87] \"migration\" \"migrations\" #> [89] \"migrations_dest\" \"migrations_left\" #> [91] \"migrations_node\" \"migrations_right\" #> [93] \"migrations_source\" \"migrations_time\" #> [95] \"min_time\" \"mutation\" #> [97] \"mutations\" \"mutations_node\" #> [99] \"mutations_parent\" \"mutations_site\" #> [101] \"mutations_time\" \"nbytes\" #> [103] \"newick_trees\" \"node\" #> [105] \"nodes\" \"nodes_flags\" #> [107] \"nodes_individual\" \"nodes_population\" #> [109] \"nodes_time\" \"num_edges\" #> [111] \"num_individuals\" \"num_migrations\" #> [113] \"num_mutations\" \"num_nodes\" #> [115] \"num_populations\" \"num_provenances\" #> [117] \"num_samples\" \"num_sites\" #> [119] \"num_trees\" \"pairwise_diversity\" #> [121] \"parse_windows\" \"population\" #> [123] \"populations\" \"provenance\" #> [125] \"provenances\" \"records\" #> [127] \"reference_sequence\" \"rtrim\" #> [129] \"sample_count_stat\" \"sample_size\" #> [131] \"samples\" \"segregating_sites\" #> [133] \"sequence_length\" \"simplify\" #> [135] \"site\" \"sites\" #> [137] \"sites_position\" \"split_edges\" #> [139] \"subset\" \"table_metadata_schemas\" #> [141] \"tables\" \"tables_dict\" #> [143] \"Tajimas_D\" \"time_units\" #> [145] \"to_macs\" \"to_nexus\" #> [147] \"trait_correlation\" \"trait_covariance\" #> [149] \"trait_linear_model\" \"trait_regression\" #> [151] \"trees\" \"trim\" #> [153] \"union\" \"variants\" #> [155] \"write_fasta\" \"write_nexus\" #> [157] \"write_vcf\" \"Y1\" #> [159] \"Y2\" \"Y3\""},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"calculating-f-statistics","dir":"Articles","previous_headings":"","what":"Calculating f-statistics","title":"Tree-sequence processing and statistics","text":"addition revolutionary breakthrough terms computation efficiency, many statistics often interested population genetics natural consequence direct access tree sequence genealogies, simply genealogies capture true demographic history sample. , can’t go much detail encourage take look paper Ralph et al. duality statistics expressed terms branch lengths traditional summaries based samples genetic variation. instance, functions ts_f2(), ts_f3(), ts_f4() ts_f4ratio() calculate well-known set Patterson’s \\(f\\)-statistics: functions accept mode = argument, specifying whether statistics calculated using mutation site patterns (mode = \"site\", default), branch lengths (mode = \"branch\"), node (mode = \"node\"), well windows argument, similarly “multiway” statistics implemented tskit. See relevant sections official tskit documentation topic. Note previous chunk referred individuals names (numeric IDs nodes tskit Python). allow readability make easier see individuals based specified sampling schedule (names assigned individuals based order sampling). can get overview individuals scheduled sampling (.e. permanently remembered) names helper function ts_samples(): said, like run statistics nodes rather individuals, can simply using integer IDs instead character names function’s interface.","code":"# f2 is a measure of the branch length connecting A and B ts_f2(ts, A = \"EUR_1\", B = \"AFR_1\") #> # A tibble: 1 × 3 #> A B f2 #> #> 1 EUR_1 AFR_1 0.0000448 # f4 is a measure of the drift shared between A and B after their split from C ts_f3(ts, A = \"EUR_1\", B = \"AFR_1\", C = \"CH_1\") #> # A tibble: 1 × 4 #> A B C f3 #> #> 1 EUR_1 AFR_1 CH_1 0.0000130 # this value should be very close to zero (no introgression in Africans) ts_f4(ts, \"AFR_1\", \"AFR_2\", \"NEA_1\", \"CH_1\", mode = \"branch\") #> # A tibble: 1 × 5 #> W X Y Z f4 #> #> 1 AFR_1 AFR_2 NEA_1 CH_1 -118. # this value should be significantly negative (many more ABBA sites # compared to BABA site due to the introgression into Europeans) ts_f4(ts, \"AFR_1\", \"EUR_1\", \"NEA_1\", \"CH_1\", mode = \"branch\") #> # A tibble: 1 × 5 #> W X Y Z f4 #> #> 1 AFR_1 EUR_1 NEA_1 CH_1 -741. ts_samples(ts) #> # A tibble: 58 × 3 #> name time pop #> #> 1 NEA_1 70000 NEA #> 2 NEA_2 40000 NEA #> 3 EUR_1 39171 EUR #> 4 EUR_2 39134 EUR #> 5 EUR_3 37739 EUR #> 6 EUR_4 36531 EUR #> 7 EUR_5 36362 EUR #> 8 EUR_6 35945 EUR #> 9 EUR_7 33900 EUR #> 10 EUR_8 33854 EUR #> # ℹ 48 more rows"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"estimating-neanderthal-ancestry-proportions","dir":"Articles","previous_headings":"","what":"Estimating Neanderthal ancestry proportions","title":"Tree-sequence processing and statistics","text":"Let’s try put new tools practice estimate proportion Neanderthal ancestry Africans Europeans simulated data. can using Patterson’s \\(f_4\\)-ratio statistic implemented ts_f4ratio() function slendr (can find information particular version statistic Petr et al., PNAS 2019): now summarise inferred Neanderthal distribution populations, see Neanderthal ancestry Africans (expected model–Africans receive Neanderthal introgression pulse) small proportion Neanderthal ancestry Europeans (consistent 3% introgression pulse simulated ): exactly specified model configuration , suggesting simulations work . can see quite bit noise ’s simulated small amount sequence. can also plot trajectory Neanderthal ancestry Europe time-window simulated ancient present-day DNA samples: , result consistent empirical estimates Neanderthal ancestry using ancient DNA data (see Petr et al., PNAS 2019).","code":"# first get a table of simulated African and European individuals in the tree-sequence inds <- ts_samples(ts) %>% dplyr::filter(pop %in% c(\"AFR\", \"EUR\")) # estimate the amounts of Neanderthal ancestry in these individuals and add # these values to the table inds$ancestry <- ts_f4ratio(ts, X = inds$name, \"NEA_1\", \"NEA_2\", \"AFR_1\", \"CH_1\")$alpha ggplot(inds, aes(pop, ancestry, fill = pop)) + geom_boxplot() + geom_jitter() + labs(y = \"Neanderthal ancestry proportion\", x = \"\") + theme(legend.position = \"none\") + coord_cartesian(ylim = c(0, 0.1)) dplyr::filter(inds, pop == \"EUR\") %>% ggplot(aes(time, ancestry)) + geom_point() + geom_smooth(method = \"lm\", linetype = 2, color = \"red\", linewidth = 0.5) + xlim(40000, 0) + coord_cartesian(ylim = c(0, 0.1)) + labs(x = \"time [years ago]\", y = \"Neanderthal ancestry proportion\") #> `geom_smooth()` using formula = 'y ~ x'"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"admixtools-analyses","dir":"Articles","previous_headings":"","what":"ADMIXTOOLS analyses","title":"Tree-sequence processing and statistics","text":"case like verify f-statistics results using venerable ADMIXTOOLS software (see linked paper formally introduced statistics first place), can convert tree-sequence data file format called EIGENSTRAT using ts_eigenstrat() function. file conversion internally handled R package admixr returns EIGENSTRAT object ties individual EIGENSTRAT file components together (see tutorial admixr extensive overview). admixr R package running automated ADMIXTOOLS analyses entirely R makes types analyses convenient. Running admixr analysis easy plugging object admixr function. instance, can estimate proportion Neanderthal ancestry couple individuals \\(X\\) like (admixr calls proportion alpha): fact, lets compare values obtained tskit admixr/ADMIXTOOLS individuals: correspondence two looks good! 🎉 , note large amount variance around expected value 3% ancestry due extremely small amount sequence data simulated .","code":"snps <- ts_eigenstrat(ts, prefix = file.path(tempdir(), \"eigenstrat\", \"data\")) #> 1282 multiallelic sites (0.206% out of 621331 total) detected and removed library(admixr) f4ratio(data = snps, X = c(\"EUR_1\", \"EUR_2\", \"AFR_2\"), A = \"NEA_1\", B = \"NEA_2\", C = \"AFR_1\", O = \"CH_1\") #> Rows: 3 Columns: 12 #> ── Column specification ──────────────────────────────────────────────────────── #> Delimiter: \" \" #> chr (8): X1, X2, X3, X4, X5, X6, X7, X8 #> dbl (4): X9, X10, X11, X12 #> #> ℹ Use `spec()` to retrieve the full column specification for this data. #> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message. #> # A tibble: 3 × 8 #> A B X C O alpha stderr Zscore #> #> 1 NEA_1 NEA_2 EUR_1 AFR_1 CH_1 0.0218 0.00506 4.30 #> 2 NEA_1 NEA_2 EUR_2 AFR_1 CH_1 0.0328 0.00788 4.16 #> 3 NEA_1 NEA_2 AFR_2 AFR_1 CH_1 0.00408 0.00208 1.96 europeans <- inds[inds$pop == \"EUR\", ]$name # tskit result result_ts <- ts_f4ratio(ts, X = europeans, A = \"NEA_1\", B = \"NEA_2\", C = \"AFR_1\", O = \"CH_1\") %>% select(alpha_ts = alpha) # result obtained by admixr/ADMIXTOOLS result_admixr <- f4ratio(snps, X = europeans, A = \"NEA_1\", B = \"NEA_2\", C = \"AFR_1\", O = \"CH_1\") %>% select(alpha_admixr = alpha) #> Rows: 50 Columns: 12 #> ── Column specification ──────────────────────────────────────────────────────── #> Delimiter: \" \" #> chr (8): X1, X2, X3, X4, X5, X6, X7, X8 #> dbl (4): X9, X10, X11, X12 #> #> ℹ Use `spec()` to retrieve the full column specification for this data. #> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message. bind_cols(result_admixr, result_ts) %>% ggplot(aes(alpha_ts, alpha_admixr)) + geom_point() + geom_abline(slope = 1, linetype = 2, color = \"red\", linewidth = 0.5) + labs(x = \"f4-ratio statistic calculated with admixr/ADMIXTOOLS\", y = \"f4-ratio statistic calculated with tskit\")"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"vcf-output","dir":"Articles","previous_headings":"","what":"VCF output","title":"Tree-sequence processing and statistics","text":"case need process simulated data software, can use function ts_vcf() save simulated genotypes VCF format: can also specify subset individuals saved VCF:","code":"ts_vcf(ts, path = file.path(tempdir(), \"output.vcf.gz\")) ts_vcf(ts, path = file.path(tempdir(), \"output_subset.vcf.gz\"), individuals = c(\"CH_1\", \"NEA_1\", \"EUR_1\", \"AFR_1\"))"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"other-statistics","dir":"Articles","previous_headings":"","what":"Other statistics","title":"Tree-sequence processing and statistics","text":"follows brief overview statistics implemented tskit slendr provides easy--use R interface. see, goal functions get result using single function call, making convenient quick interactive exploratory analyses simulated data right R console. continue use simulated Neanderthal introgression tree-sequence data examples.","code":""},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"f_st","dir":"Articles","previous_headings":"Other statistics","what":"\\(F_{st}\\)","title":"Tree-sequence processing and statistics","text":"\\(F_{st}\\) statistic implemented function ts_fst(). single genome-wide \\(F_{st}\\) calculated (.e. window-based calculation), ts_fst() returns simple three-column data frame case non-named list sample sets provided, set names generated automatically: course, much less readable encourage name sample sets appropriately. case two sample sets specified, pairwise statistics computed: many statistics implemented tskit, ts_fst() accepts windows argument, specifying breakpoints windows. case, Fst column resulting data frame called “list-column”, item column vector \\(F_{st}\\) values, one per window. List-columns can little confusing new R users, highly encourage get used allow extremely concise elegant handling structured data within normal data frames (can start introduction). instance, window-based \\(F_st\\) values afr-vs-eur calculation (first row table ):","code":"ts_fst(ts, sample_sets = list(afr = c(\"AFR_1\", \"AFR_2\", \"AFR_3\"), eur = c(\"EUR_1\", \"EUR_2\"))) #> # A tibble: 1 × 3 #> x y Fst #> #> 1 afr eur 0.0495 ts_fst(ts, sample_sets = list(c(\"AFR_1\", \"AFR_2\", \"AFR_3\"), c(\"EUR_1\", \"EUR_2\"))) #> # A tibble: 1 × 3 #> x y Fst #> #> 1 set_1 set_2 0.0495 ts_fst(ts, sample_sets = list(afr = c(\"AFR_1\", \"AFR_2\", \"AFR_3\"), eur = c(\"EUR_1\", \"EUR_2\"), nea = c(\"NEA_1\", \"NEA_2\"))) #> # A tibble: 3 × 3 #> x y Fst #> #> 1 afr eur 0.0495 #> 2 afr nea 0.555 #> 3 eur nea 0.541 # define breakpoints between 20 windows breakpoints <- seq(0, ts$sequence_length, length.out = 21) # calculate window-based Fst statistic win_fst <- ts_fst( ts, windows = breakpoints, sample_sets = list(afr = c(\"AFR_1\", \"AFR_2\", \"AFR_3\"), eur = c(\"EUR_1\", \"EUR_2\"), nea = c(\"NEA_1\", \"NEA_2\")) ) # we get 20 values for each parwise calculation win_fst #> # A tibble: 3 × 3 #> x y Fst #> #> 1 afr eur #> 2 afr nea #> 3 eur nea win_fst[1, ]$Fst #> $`1` #> [1] 0.04241163 0.06803338 0.04129167 0.06031210 0.05516414 0.03059425 #> [7] 0.03320629 0.05755971 0.05271680 0.04346970 0.03659568 0.05432308 #> [13] 0.05913699 0.05905198 0.04119386 0.04389669 0.05086942 0.06181126 #> [19] 0.03929837 0.06373172"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"tajimas-d","dir":"Articles","previous_headings":"Other statistics","what":"Tajima’s \\(D\\)","title":"Tree-sequence processing and statistics","text":"function ts_tajima() nearly interface ts_fst() shown . non-window version calculated, get single genome-wide values sample set (named non-named list character vectors individual names): window-based version, function returns D column list column vectors \\(\\)-th element Tajima’s D value \\(\\)-th window:","code":"ts_tajima(ts, list(afr = c(\"AFR_1\", \"AFR_2\", \"AFR_3\"), eur = c(\"EUR_1\", \"EUR_2\"))) #> # A tibble: 2 × 2 #> set D #> #> 1 afr -0.000701 #> 2 eur -0.0140 ts_tajima(ts, list(afr = c(\"AFR_1\", \"AFR_2\"), eur = c(\"EUR_1\", \"EUR_2\")), windows = breakpoints) #> # A tibble: 2 × 2 #> set D #> #> 1 afr #> 2 eur "},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"diversity","dir":"Articles","previous_headings":"Other statistics","what":"Diversity","title":"Tree-sequence processing and statistics","text":"can calculate diversity within given groups individuals function ts_diversity(). instance, even extremely simplified example, expect highest levels diversity Africans, followed Europeans, Neanderthals “degenerate” single individual outgroup “chimpanzee”. true? Let’s find . First extract individuals populations, creating list character vectors group (functions ts_diversity() expects input): Now can calculate diversity population sort results increasing order diversity: Great! matches expectations. simulated chimp “population” one individual, expect essentially diversity millions years evolution.","code":"# get sampled individuals from all populations sample_sets <- ts_samples(ts) %>% split(., .$pop) %>% lapply(function(pop) pop$name) sample_sets #> $AFR #> [1] \"AFR_1\" \"AFR_2\" \"AFR_3\" \"AFR_4\" \"AFR_5\" #> #> $CH #> [1] \"CH_1\" #> #> $EUR #> [1] \"EUR_1\" \"EUR_2\" \"EUR_3\" \"EUR_4\" \"EUR_5\" \"EUR_6\" \"EUR_7\" \"EUR_8\" #> [9] \"EUR_9\" \"EUR_10\" \"EUR_11\" \"EUR_12\" \"EUR_13\" \"EUR_14\" \"EUR_15\" \"EUR_16\" #> [17] \"EUR_17\" \"EUR_18\" \"EUR_19\" \"EUR_20\" \"EUR_21\" \"EUR_22\" \"EUR_23\" \"EUR_24\" #> [25] \"EUR_25\" \"EUR_27\" \"EUR_26\" \"EUR_28\" \"EUR_29\" \"EUR_30\" \"EUR_31\" \"EUR_32\" #> [33] \"EUR_33\" \"EUR_34\" \"EUR_35\" \"EUR_36\" \"EUR_37\" \"EUR_38\" \"EUR_39\" \"EUR_40\" #> [41] \"EUR_41\" \"EUR_42\" \"EUR_43\" \"EUR_44\" \"EUR_45\" \"EUR_46\" \"EUR_47\" \"EUR_48\" #> [49] \"EUR_49\" \"EUR_50\" #> #> $NEA #> [1] \"NEA_1\" \"NEA_2\" ts_diversity(ts, sample_sets) %>% dplyr::arrange(diversity) #> # A tibble: 4 × 2 #> set diversity #> #> 1 CH 0.0000431 #> 2 NEA 0.0000455 #> 3 EUR 0.000394 #> 4 AFR 0.000400"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"divergence","dir":"Articles","previous_headings":"Other statistics","what":"Divergence","title":"Tree-sequence processing and statistics","text":"can calculate pairwise divergence groups individuals using function ts_divergence(). Given model, expect lowest divergence two modern human groups AFR EUR, Neanderthals two modern humans, three groups (AFR, EUR NEA) equal, much deeper divergence outgroup chimpanzee CH. sorting table based value divergence column, can see results fit expectations.","code":"ts_divergence(ts, sample_sets) %>% arrange(divergence) #> # A tibble: 6 × 3 #> x y divergence #> #> 1 AFR EUR 0.000449 #> 2 EUR NEA 0.000757 #> 3 AFR NEA 0.000780 #> 4 CH NEA 0.00401 #> 5 CH EUR 0.00402 #> 6 AFR CH 0.00402"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"more-information","dir":"Articles","previous_headings":"","what":"More information","title":"Tree-sequence processing and statistics","text":"couple examples statistical functions implemented tskit provide native R interface slendr. can find tree-sequence statistics reference manual project website. statistics tskit library implemented, intend expand selection provided slendr near future. functionality like use project missing slendr, please don’t hesitate let us now creating issue GitHub page. Finally, like see examples tskit interface action, take look vignette describes switching SLiM msprime back ends slendr package.","code":""},{"path":"https://www.slendr.net/articles/vignette-06-locations.html","id":"introduction","dir":"Articles","previous_headings":"","what":"Introduction","title":"Spatially annotated tree sequences","text":"main selling point slendr R package programming complex spatially explicit population genetic models. use SLiM simulation engine, can store simulated data efficiently tree sequence format allows us run large population-scale simulations. previous vignettes, described can specify spatial population dynamics can access tree sequence data calculate population genetic statistics (focusing non-spatial models simplicity). Now ’s time show work simulated tree sequence spatial context.","code":""},{"path":"https://www.slendr.net/articles/vignette-06-locations.html","id":"model-specification","dir":"Articles","previous_headings":"","what":"Model specification","title":"Spatially annotated tree sequences","text":"Let’s first load required R libraries: begin specifying spatial model. use demographic model modern human history West Eurasia, extensively discussed introductory tutorial main landing page. complete model definition script, without comments: sanity check defined demography correctly, can plot graph summarizing population divergences geneflow events calling plot_model(model): completeness, (slightly busy) overview spatial population ranges defined :","code":"library(slendr) library(dplyr) library(ggplot2) init_env() seed <- 314159 set.seed(seed) # simulated world map map <- world( xrange = c(-13, 70), # min-max longitude yrange = c(18, 65), # min-max latitude crs = \"EPSG:3035\" # coordinate reference system (CRS) for West Eurasia ) # couple of broad geographic regions africa <- region( \"Africa\", map, polygon = list(c(-18, 20), c(38, 20), c(30, 33), c(20, 33), c(10, 38), c(-6, 35)) ) europe <- region( \"Europe\", map, polygon = list( c(-8, 35), c(-5, 36), c(10, 38), c(20, 35), c(25, 35), c(33, 45), c(20, 58), c(-5, 60), c(-15, 50) ) ) anatolia <- region( \"Anatolia\", map, polygon = list(c(28, 35), c(40, 35), c(42, 40), c(30, 43), c(27, 40), c(25, 38)) ) # define population histories # African ancestral population afr <- population( \"AFR\", time = 52000, N = 3000, map = map, polygon = africa ) # population of the first migrants out of Africa ooa <- population( \"OOA\", parent = afr, time = 51000, N = 500, remove = 25000, center = c(33, 30), radius = 400e3 ) %>% move( trajectory = list(c(40, 30), c(50, 30), c(60, 40)), start = 50000, end = 40000, snapshots = 20 ) # Eastern hunter-gatherers ehg <- population( \"EHG\", parent = ooa, time = 28000, N = 1000, remove = 6000, polygon = list( c(26, 55), c(38, 53), c(48, 53), c(60, 53), c(60, 60), c(48, 63), c(38, 63), c(26, 60)) ) # European population eur <- population(name = \"EUR\", parent = ehg, time = 25000, N = 2000, polygon = europe) # Anatolian farmers ana <- population( name = \"ANA\", time = 28000, N = 3000, parent = ooa, remove = 4000, center = c(34, 38), radius = 500e3, polygon = anatolia ) %>% expand_range( by = 2500e3, start = 10000, end = 7000, polygon = join(europe, anatolia), snapshots = 20 ) # expand the range by 2.500 km # Yamnaya steppe population yam <- population( name = \"YAM\", time = 7000, N = 500, parent = ehg, remove = 2500, polygon = list(c(26, 50), c(38, 49), c(48, 50), c(48, 56), c(38, 59), c(26, 56)) ) %>% move(trajectory = list(c(15, 50)), start = 5000, end = 3000, snapshots = 10) # geneflow events gf <- list( gene_flow(from = ana, to = yam, rate = 0.5, start = 6000, end = 5000, overlap = FALSE), gene_flow(from = ana, to = eur, rate = 0.5, start = 8000, end = 6000), gene_flow(from = yam, to = eur, rate = 0.75, start = 4000, end = 3000) ) # compile the spatial model model <- compile_model( populations = list(afr, ooa, ehg, eur, ana, yam), gene_flow = gf, generation_time = 30, resolution = 10e3, competition = 150e3, mating = 120e3, dispersal = 90e3 ) plot_model(model) plot_map(afr, ooa, ehg, eur, ana, yam)"},{"path":"https://www.slendr.net/articles/vignette-06-locations.html","id":"scheduling-sampling-events-and-simulation","dir":"Articles","previous_headings":"","what":"Scheduling sampling events and simulation","title":"Spatially annotated tree sequences","text":"Now schedule sampling single individual population every two thousand years, starting 40 thousand years ago way present (feature discussed basic tree sequence overview): Finally, can simulate data model process output tree sequence (recapitate simplify ):","code":"# one ancient individual every two thousand years ancient <- schedule_sampling(model, times = seq(40000, 1, by = -500), list(ooa, 1), list(ehg, 1), list(eur, 1), list(ana, 1), list(yam, 1)) # present-day Africans and Europeans present <- schedule_sampling(model, times = 0, list(afr, 5), list(eur, 30)) samples <- rbind(ancient, present) ts <- slim( model, sequence_length = 100e3, recombination_rate = 1e-8, burnin = 200e3, samples = samples, method = \"batch\", random_seed = 314159, max_attempts = 1 ) %>% ts_recapitate(recombination_rate = 1e-8, Ne = 10000, random_seed = seed) %>% ts_simplify() ts #> ╔═════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═════════╣ #> ║Trees │ 87║ #> ╟───────────────┼─────────╢ #> ║Sequence Length│ 100000║ #> ╟───────────────┼─────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼─────────╢ #> ║Sample Nodes │ 432║ #> ╟───────────────┼─────────╢ #> ║Total Size │205.8 KiB║ #> ╚═══════════════╧═════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │1173│36.7 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 711│71.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 939│35.4 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 7│ 2.7 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 3│37.8 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Sites │ 0│16 Bytes│ No║ #> ╚═══════════╧════╧════════╧════════════╝"},{"path":"https://www.slendr.net/articles/vignette-06-locations.html","id":"extracting-spatial-tree-sequence-information","dir":"Articles","previous_headings":"","what":"Extracting spatial tree sequence information","title":"Spatially annotated tree sequences","text":"showed basic tutorial, important function data exploration ts_nodes(). function extracts information individuals nodes recorded tree sequence object loaded annotated slendr : completeness, also functions ts_individuals(), ts_nodes() ts_edges() extract tree sequence tables “raw” unprocessed form, ts_nodes() much convenient data exploration analyses. First, combined information low-level tables individuals nodes single table importantly, model generated data spatial model, ts_nodes() automatically annotates node/individual tables position node space (real projected coordinates) time. means can spatial data analysis directly table returned ts_nodes(). Even better, although can see returned object belongs slendr’s class slendr_ts_nodes, internally stored spatial sf object. means can use functionality powerful R package sf well many packages geospatial analyses directly data: Typing object R console presents user-friendly summary spatio-temporal data extracted tree sequence: first part summary, see many individuals (sampled retained) nodes present tree sequence together additional useful information, including section internally stored sf object. crucial point—**can always use internal sf object spatial data directly*. data returned ts_nodes() internally transformed projected CRS used model, can use returned object data class sf. instance, beginning vignette, specified world map model represented projected CRS (EPSG 3035) can verify typing: fact ts_nodes() result just another sf object makes easy visualize overlay contents map, see .","code":"data <- ts_nodes(ts) class(data) #> [1] \"slendr\" \"slendr_nodes\" \"sf\" \"tbl_df\" \"tbl\" #> [6] \"data.frame\" data #> Simple feature collection with 939 features and 12 fields (with 11 geometries empty) #> Geometry type: POINT #> Dimension: XY #> Bounding box: xmin: 2426565 ymin: 257945.3 xmax: 8576618 ymax: 4878988 #> Projected CRS: ETRS89-extended / LAEA Europe #> # A tibble: 939 × 13 #> name pop node_id time time_tskit location sampled #> #> 1 AFR_1 AFR 362 0 0 (3716841 1078277) TRUE #> 2 AFR_1 AFR 363 0 0 (3716841 1078277) TRUE #> 3 AFR_2 AFR 364 0 0 (3541863 257945.3) TRUE #> 4 AFR_2 AFR 365 0 0 (3541863 257945.3) TRUE #> 5 AFR_3 AFR 366 0 0 (3366331 688429.9) TRUE #> 6 AFR_3 AFR 367 0 0 (3366331 688429.9) TRUE #> 7 AFR_4 AFR 368 0 0 (3329518 1360326) TRUE #> 8 AFR_4 AFR 369 0 0 (3329518 1360326) TRUE #> 9 AFR_5 AFR 370 0 0 (3263687 1123829) TRUE #> 10 AFR_5 AFR 371 0 0 (3263687 1123829) TRUE #> # ℹ 929 more rows #> # ℹ 6 more variables: remembered , retained , alive , #> # pedigree_id , ind_id , pop_id map #> slendr 'map' object #> ------------------- #> map: internal coordinate reference system EPSG 3035 #> spatial limits (in degrees longitude and latitude): #> - vertical -13 ... 70 #> - horizontal 18 ... 65"},{"path":"https://www.slendr.net/articles/vignette-06-locations.html","id":"using-the-simple-features-interface","dir":"Articles","previous_headings":"","what":"Using the simple features interface","title":"Spatially annotated tree sequences","text":"’s hard overstate powerful R ecosystem around sf package . However, getting familiar package geospatial analysis general can bit hurdle, especially novice users takes time get familiar many new concepts. Although many slendr features encoding programming spatial models handling simulated tree sequence data discussed far designed abstract away complexities underlying low-level details let focus problem hand, spatial data analysis unfortunately whole another matter. Luckily, data generated slendr different source spatial data great free resources disposal. bottom line : spatio-temporal data extracted tree sequences slendr different normal sf object. resource find manipulating, plotting, analysing sf data can applied slendr results well. remainder vignette look couple examples.","code":""},{"path":"https://www.slendr.net/articles/vignette-06-locations.html","id":"plotting-locations-of-simulated-sampled-individuals","dir":"Articles","previous_headings":"","what":"Plotting locations of simulated sampled individuals","title":"Spatially annotated tree sequences","text":"Every spatial object slendr internally class sf. flexibility ggplot2 sf packages means can overlay locations sampled individuals (saved sf format ts_nodes()) top world map (also sf object): sf simple features objects (, extension, even slendr_spatial objects) internally stored normal data frames couple bells whistles top , powerful tools manipulating tabular data disposal. example, let’s say wanted split sampled individuals tree sequence epochs plot individually using standard ggplot2 features. simply first , adding new column specifying epoch simulated individual belong: chunk code simply adds new column epoch sf spatial data frame object called epochs . can use ggplot2 function geom_sf plot locations sampled individuals map, facet corresponding one epoch (warning can safely ignored): hope little excursion handling slendr spatial objects (, extension, sf objects) standard data frame manipulation functions ggplot2 visualisation convinced great flexibility analysing spatial slendr data. best introduction -called “tidy” data analysis, encourage read freely-available book R Data Science.","code":"sampled_data <- ts_nodes(ts) %>% filter(sampled) ggplot() + geom_sf(data = map, fill = \"lightgray\", color = NA) + geom_sf(data = sampled_data, aes(shape = pop, color = time)) + ggtitle(\"Locations of simulated sampled individuals\") + scale_color_continuous(type = \"viridis\") + theme_bw() epochs <- sampled_data %>% mutate(epoch = cut(time, breaks = c(40000, 30000, 10000, 4000, 0)), epoch = ifelse(is.na(epoch), 0, epoch), epoch = factor(epoch, labels = c(\"present\", \"(present, 4 ky]\", \"(4 ky, 10 ky]\", \"(10 ky, 30 y]\", \"(30 ky, 40 ky]\"))) ggplot() + geom_sf(data = map, fill = \"lightgray\", color = NA) + geom_sf(data = epochs, aes(shape = pop, color = pop)) + facet_wrap(~ epoch) + ggtitle(\"Locations of simulated sampled individuals in different epochs\") + theme_bw()"},{"path":"https://www.slendr.net/articles/vignette-06-locations.html","id":"extracting-spatio-temporal-ancestral-relationships","dir":"Articles","previous_headings":"","what":"Extracting spatio-temporal ancestral relationships","title":"Spatially annotated tree sequences","text":"Perhaps even useful plotting locations simulated individuals accessing locations (times) ancestors particular tree sequence node (“focal node”). Starting focal node individual, can trace geographical location nodes lineage going back way root function ts_ancestors(). record time location every individual happens ancestor least one sampled individual, means know true location every node tree sequence. simplest use case determining locations times every single node genealogical history individual along tree sequence (possible recover ancestral relationships multiple samples ): function starts given node (, name sampled diploid individual provided, two nodes), extracts information parent nodes node entire tree sequence, records locations times, proceeds one level “higher” genealogical history gather information parents parent nodes, etc., reaches root node. result process another sf object row table encodes information single branch genealogy “focal” node individual (example, \"EUR_25\"): row table, two columns location parent_location carry spatial location node (node_id) parent node (parent_id), respectively, columns time parent_time (times nodes) pop parent_pop (populations nodes belong). column connection contains sf geometry object line connecting two nodes coordinate reference system “model world”. column focal_id tells us focal node’s genealogy rows table belong , level column shows deep genealogical past branch (.e. row table) belong . table contains complete information spatio-temporal relationships nodes genealogy given focal sample. spirit demonstrating slendr tree sequence tables interact sf ggplot2 environments, let’s look immediate parent nodes two nodes sampled individual (.e. nodes level 1) using filter function R package dplyr: mentioned , three columns encoding spatial information: location parent_location carry information location child parent node (POINT class), connection object (LINESTRING class) contains line connecting two nodes (branch tree sequence also spatial connection). can plot three spatial features (two points line) individually map: figure can see red focal node immediate parents tree sequence genealogy (coalescent sense, immediate parents individual!). case ’re surprised see two parents, recall recombination events make history encoded sample complicated can involve ancestors “move ” tree sample, just two ancestors. Looking example detail, can see one node (chromosome) individual “EUR_67” two ancestors, covering portion individuals chromosome, chromosome covered single ancestor (columns left_pos right_pos): convenient way analysis companion function ts_ancestors() called plot_ancestors(). function accepts sf object spatial branching data created ts_ancestors() plots paths nodes map leading focal node root(s) tree sequence (instead just paths immediate parents shown previous figure). case, working single diploid individual, get two sets paths nodes (chromosomes) plot two facets: can compare result animation recapitulates simulation, presented first vignette. comparing spatial tree sequence figure animation, can immediately notice several things: spatial tree sequence paths trace ancestry single European individual back Africa. fact, also see cluster past ancestral nodes (.e. concentrated coalescent events) place Africa (OOA) migrant population settled around 40,000 thousand years ago (yellow population animation). One chromosome traces ancestry EHG population indicated green square expected programmed Yamnaya migration (descending EHG) east central Europe contribute significant part ancestry present-day Europeans (compare demographic graph top vignette). also see chromosome traces ancestry Anatolia (blue crosses). makes sense, simulated European ancestry part Anatolian. Let’s look spatial ancestry another sample. instance, know simulated history Anatolian population model much simpler. According demographic graph , Anatolians split ancestral population Eurasians Anatolia expanded wave Europe. sampled following individuals: Can see hint spatial dynamics Anatolians spatio-temporal distribution ancestral node locations one sampled individuals? Let’s pick last individual immediately plot spatial ancestry tidyverse-style using pipe operator %>%: might expect given late age sample, position map (red crossed circle) Anatolia Europe represents one descendants migrants moved Anatolia Europe. can clearly seen position parental nodes tree sequence: nodes represent real individuals lived point past, can see , indeed, lived Anatolia.","code":"ind <- \"EUR_67\" lineages <- ts_ancestors(ts, ind, verbose = TRUE) #> Collecting ancestors of EUR_67 [1/1]... #> #> Generating data about spatial relationships of nodes... lineages #> Simple feature collection with 112 features and 12 fields #> Active geometry column: connection #> Geometry type: LINESTRING #> Dimension: XY #> Bounding box: xmin: 2736603 ymin: 607014.9 xmax: 8374222 ymax: 4762949 #> Projected CRS: ETRS89-extended / LAEA Europe #> # A tibble: 112 × 15 #> name pop node_id level child_id parent_id child_time parent_time child_pop #> * #> 1 EUR_… EUR 406 1 406 456 0 1900 EUR #> 2 EUR_… EUR 406 2 456 460 1900 2020 EUR #> 3 EUR_… EUR 406 3 460 469 2020 3010 EUR #> 4 EUR_… EUR 406 4 469 488 3010 5080 EUR #> 5 EUR_… EUR 406 5 488 495 5080 5740 EUR #> 6 EUR_… EUR 406 6 495 543 5740 9760 EUR #> 7 EUR_… EUR 406 7 543 608 9760 16090 EUR #> 8 EUR_… EUR 406 7 543 695 9760 22960 EUR #> 9 EUR_… EUR 406 8 608 695 16090 22960 EUR #> 10 EUR_… EUR 406 8 695 704 22960 23560 EUR #> # ℹ 102 more rows #> # ℹ 6 more variables: parent_pop , child_location , #> # parent_location , connection , left_pos , #> # right_pos filter(lineages, level == 1) #> Simple feature collection with 2 features and 12 fields #> Active geometry column: connection #> Geometry type: LINESTRING #> Dimension: XY #> Bounding box: xmin: 3965813 ymin: 2689630 xmax: 4683571 ymax: 2918506 #> Projected CRS: ETRS89-extended / LAEA Europe #> # A tibble: 2 × 15 #> name pop node_id level child_id parent_id child_time parent_time child_pop #> * #> 1 EUR_67 EUR 406 1 406 456 0 1900 EUR #> 2 EUR_67 EUR 407 1 407 451 0 1390 EUR #> # ℹ 6 more variables: parent_pop , child_location , #> # parent_location , connection , left_pos , #> # right_pos level1_branches <- ts_ancestors(ts, \"EUR_67\") %>% filter(level == 1) ggplot() + geom_sf(data = map, fill = \"lightgray\", color = NA) + geom_sf(data = level1_branches[, ]$child_location, shape = 13, size = 3, color = \"red\") + geom_sf(data = level1_branches[, ]$connection, linetype = 3) + geom_sf(data = level1_branches[, ]$parent_location, shape = 20, color = \"blue\") + theme_bw() + ggtitle(\"Parent nodes (blue) of a focal individual (red)\") as_tibble(level1_branches)[, c(\"name\", \"node_id\", \"child_id\", \"parent_id\", \"left_pos\", \"right_pos\")] #> # A tibble: 2 × 6 #> name node_id child_id parent_id left_pos right_pos #> #> 1 EUR_67 406 406 456 0 100000 #> 2 EUR_67 407 407 451 0 100000 ggplot() + geom_sf(data = map) + geom_sf(data = lineages, size = 0.5, alpha = 0.2) + geom_sf(data = sf::st_set_geometry(lineages, \"parent_location\"), aes(shape = parent_pop, color = parent_pop)) + geom_sf(data = filter(ts_nodes(ts), name == ind), size = 3) + guides(alpha = \"none\") + coord_sf(expand = 0) + labs(x = \"longitude\", y = \"latitude\") + facet_grid(. ~ node_id) + ggtitle(\"Ancestry encoded by two nodes (chromosomes) of EUR_67\") ts_samples(ts) %>% filter(pop == \"ANA\") #> # A tibble: 48 × 3 #> name time pop #> #> 1 ANA_1 27500 ANA #> 2 ANA_2 27000 ANA #> 3 ANA_3 26500 ANA #> 4 ANA_4 26000 ANA #> 5 ANA_5 25500 ANA #> 6 ANA_6 25000 ANA #> 7 ANA_7 24500 ANA #> 8 ANA_8 24000 ANA #> 9 ANA_9 23500 ANA #> 10 ANA_10 23000 ANA #> # ℹ 38 more rows lineages <- ts_ancestors(ts, \"ANA_45\") ggplot() + geom_sf(data = map) + geom_sf(data = lineages, size = 0.5, alpha = 0.2) + geom_sf(data = sf::st_set_geometry(lineages, \"parent_location\"), aes(shape = parent_pop, color = parent_pop)) + geom_sf(data = filter(ts_nodes(ts), name == \"ANA_45\"), size = 3) + guides(alpha = \"none\") + coord_sf(expand = 0) + labs(x = \"longitude\", y = \"latitude\") + facet_grid(. ~ node_id) + ggtitle(\"Ancestry encoded by two nodes (chromosomes) of ANA_45\")"},{"path":"https://www.slendr.net/articles/vignette-06-locations.html","id":"calculating-distances-and-other-statistics-using-the-sf-package","dir":"Articles","previous_headings":"","what":"Calculating distances and other statistics using the sf package","title":"Spatially annotated tree sequences","text":"can summarise spatial ancestral dynamics figures using statistics? Lets take one look sf object locations times ancestral nodes sampled individuals, focusing following subset columns: can use standard dplyr table manipulation functions compute distances connected notes times separate (.e. branch lengths traditional phylogenetic sense). can use two quantities compute fast () movement ancestral individuals different time periods history sample: Let’s also convert data (absolute distances distance per generation – .e., “speed”) long format easier plotting side side: Let’s try summarise information distances “traveled” nodes different time period fitting spline (rather plotting raw data individual nodes):","code":"lineages <- ts_samples(ts) %>% pull(name) %>% ts_ancestors(ts, x = .) select(lineages, connection, child_time, parent_time) #> Simple feature collection with 20798 features and 2 fields #> Geometry type: LINESTRING #> Dimension: XY #> Bounding box: xmin: 2426565 ymin: 257945.3 xmax: 8576618 ymax: 4878988 #> Projected CRS: ETRS89-extended / LAEA Europe #> # A tibble: 20,798 × 3 #> connection child_time parent_time #> #> 1 (8481422 2958176, 8289917 2751867) 40000 40690 #> 2 (8289917 2751867, 8110419 2813524) 40690 41710 #> 3 (8110419 2813524, 3348636 939123) 41710 67030 #> 4 (8110419 2813524, 2736603 1136489) 41710 83530 #> 5 (8110419 2813524, 3202720 1100178) 41710 203980 #> 6 (8110419 2813524, 3475143 607014.9) 41710 205270 #> 7 (8110419 2813524, 4086614 772146.9) 41710 243100 #> 8 (3348636 939123, 3202720 1100178) 67030 203980 #> 9 (2736603 1136489, 3969941 671890.4) 83530 88810 #> 10 (3969941 671890.4, 3991115 816590.1) 88810 96730 #> # ℹ 20,788 more rows distances <- lineages %>% mutate(branch_length = abs(parent_time - child_time) / model$generation_time, distance = sf::st_length(connection) %>% units::set_units(km) %>% as.numeric(), speed = distance / branch_length, epoch = cut(parent_time, breaks = c(Inf, seq(60000, 0, by = -3000)), dig.lab = 10, include.lowest = TRUE)) %>% as_tibble() %>% # strip away the spatial annotation select(name, pop, node_id, branch_length, distance, speed, parent_pop, parent_time, child_pop, child_time, epoch) distances_long <- distances %>% filter(child_time < 60000) %>% filter(!pop %in% c(\"AFR\", \"OOA\")) %>% tidyr::pivot_longer(cols = c(distance, speed), names_to = \"stat\", values_to = \"value\") %>% mutate(facet = case_when( stat == \"distance\" ~ \"absolute distance of a node from parent\", stat == \"speed\" ~ \"distance traveled by a node per generation\")) distances_long %>% ggplot(aes(child_time, value, color = child_pop)) + geom_smooth(method = \"loess\", aes(group = child_pop)) + geom_hline(yintercept = 0, linetype = 2, linewidth = 0.5) + labs(y = \"kilometers\", x = \"time [years ago]\") + theme(axis.text.x = element_text(hjust = 1, angle = 45), legend.position = \"bottom\") + facet_wrap(~ facet, scales = \"free_y\") + guides(color = guide_legend(\"ancestral node population\")) #> `geom_smooth()` using formula = 'y ~ x'"},{"path":[]},{"path":"https://www.slendr.net/articles/vignette-07-backends.html","id":"defining-a-model","dir":"Articles","previous_headings":"Detecting gene flow from msprime and SLiM tree sequences","what":"Defining a model","title":"Simulating data with SLiM and msprime backends","text":"now define simple non-spatial model gene flow populations (also known population admixture introgression). involve essentially procedure shown another vignette introducing non-spatial slendr models. Note different normally specify spatial model, except left map argument making population() calls. demonstrate additional features slendr interface tskit Python library, perform gene flow detection test using -called \\(f_4\\) \\(f_4\\)-ratio statistics (briefly introduces vignette). make things little interesting, define two population models: one model without gene flow, another includes gene flow. defining model expressing \\(f\\)-statistics use nomenclature used first study Patterson et al. described \\(f_4-ratio\\) statistic first place. ’re familiar statistical tests gene flow, recommend take look relevant sections linked paper. shiny_graph Let’s start first defining populations splits established figure : Note Ne populations x1 x2 set much higher rest. set \\(N_e\\) populations lower values speed forward SLiM simulations (won’t affect results ’re interested anyway). Higher values \\(N_e\\) x1 x2 populations ensure effect drift acting two populations much smaller. simulate later measure proportion ancestry population b x1, ensure ancestry proportion drift far away expectation make interesting patterns stand clearly. (course, done demonstration purposes speed SLiM simulations making \\(N_e\\) populations smaller. practice, running kinds simulations using msprime back end.)","code":"seq_len <- 100e6 # amount of sequence to simulate rec_rate <- 1e-8 # uniform recombination rate mut_rate <- 1e-8 # mutation rate o <- population(\"outgroup\", time = 1, N = 100) c <- population(\"c\", time = 2500, N = 100, parent = o) a <- population(\"a\", time = 3000, N = 100, parent = c) b <- population(\"b\", time = 3500, N = 100, parent = a) x1 <- population(\"x1\", time = 3800, N = 5000, parent = c) x2 <- population(\"x2\", time = 4000, N = 5000, parent = x1)"},{"path":"https://www.slendr.net/articles/vignette-07-backends.html","id":"compiling-the-model-and-simulating-data","dir":"Articles","previous_headings":"","what":"Compiling the model and simulating data","title":"Simulating data with SLiM and msprime backends","text":"now use populations compile two models: first model without gene flow (left panel figure ), second model include 10% gene flow b x1 (right panel figure ). also schedule sampling couple individuals end simulation: 50 individuals populations x1 x2 capture bit natural variation b ancestry x1, one individual rest. running simulations, let’s first make sure models set correctly: Now run models (without gene flow) two slendr backends, SLiM msprime: Note using exactly model configuration object simulation runs! fact, even function interface looks nearly exactly . doesn’t matter specific details demographic models , slendr interpret correctly regardless back end simulation engine choose use.","code":"# no gene flow model model_nogf <- compile_model(populations = list(a, b, x1, x2, c, o), generation_time = 1, simulation_length = 4500) samples <- schedule_sampling( model_nogf, times = 4500, list(a, 1), list(b, 1), list(x1, 50), list(x2, 50), list(c, 1), list(o, 1) ) # model with gene flow gf <- gene_flow(from = b, to = x1, start = 4100, end = 4400, rate = 0.1) model_gf <- compile_model(populations = list(a, b, x1, x2, c, o), gene_flow = gf, generation_time = 1, simulation_length = 4500) samples <- schedule_sampling( model_gf, times = 4500, list(a, 1), list(b, 1), list(x1, 50), list(x2, 50), list(c, 1), list(o, 1) ) plot_model(model_nogf, sizes = FALSE) plot_model(model_gf, sizes = FALSE, proportions = TRUE) # model without gene flow slim_nogf <- slim(model_nogf, sequence_length = seq_len, recombination_rate = rec_rate, samples = samples, random_seed = seed) msprime_nogf <- msprime(model_nogf, sequence_length = seq_len, recombination_rate = rec_rate, samples = samples, random_seed = seed) # model with b -> x1 gene flow slim_gf <- slim(model_gf, sequence_length = seq_len, recombination_rate = rec_rate, samples = samples, random_seed = seed) msprime_gf <- msprime(model_gf, sequence_length = seq_len, recombination_rate = rec_rate, samples = samples, random_seed = seed)"},{"path":"https://www.slendr.net/articles/vignette-07-backends.html","id":"comparing-the-outputs-of-msprime-and-slim-runs-of-a-slendr-model","dir":"Articles","previous_headings":"Compiling the model and simulating data","what":"Comparing the outputs of msprime and SLiM runs of a slendr model","title":"Simulating data with SLiM and msprime backends","text":"run introgression models two simulation back ends, let’s load SLiM msprime tree sequence outputs compare contents (hoping !). can see , tree sequence summary data loaded processed slendr’s ts_load() function (data produced SLiM backend) similar got “manually” msprime-produced tree sequence using custom defined functions. somehow obvious nice cheap sanity check indicating tree sequence data structure produced two backends demographic model almost .","code":"# SLiM outputs -- we can use built-in slendr functions for those slim_nogf <- slim_nogf %>% ts_recapitate(Ne = 10, recombination_rate = rec_rate, random_seed = seed) %>% ts_mutate(mut_rate, random_seed = seed) slim_gf <- slim_gf %>% ts_recapitate(Ne = 10, recombination_rate = rec_rate, random_seed = seed) %>% ts_mutate(mut_rate, random_seed = seed) # msprime outputs (note that recapitation and simplification doesn't make # sense here because we already have fully coalesced genealogies for our # individuals of interest msprime_nogf <- ts_mutate(msprime_nogf, mut_rate, random_seed = seed) msprime_gf <- ts_mutate(msprime_gf, mut_rate, random_seed = seed) slim_nogf #> ╔═════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═════════╣ #> ║Trees │ 248158║ #> ╟───────────────┼─────────╢ #> ║Sequence Length│100000000║ #> ╟───────────────┼─────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼─────────╢ #> ║Sample Nodes │ 21008║ #> ╟───────────────┼─────────╢ #> ║Total Size │ 70.6 MiB║ #> ╚═══════════════╧═════════╝ #> ╔═══════════╤══════╤════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪════════╪════════════╣ #> ║Edges │972815│29.7 MiB│ No║ #> ╟───────────┼──────┼────────┼────────────╢ #> ║Individuals│131750│12.6 MiB│ Yes║ #> ╟───────────┼──────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼────────┼────────────╢ #> ║Mutations │257348│ 9.1 MiB│ No║ #> ╟───────────┼──────┼────────┼────────────╢ #> ║Nodes │157230│ 5.7 MiB│ Yes║ #> ╟───────────┼──────┼────────┼────────────╢ #> ║Populations│ 7│ 2.8 KiB│ Yes║ #> ╟───────────┼──────┼────────┼────────────╢ #> ║Provenances│ 3│38.0 KiB│ No║ #> ╟───────────┼──────┼────────┼────────────╢ #> ║Sites │257040│ 6.1 MiB│ No║ #> ╚═══════════╧══════╧════════╧════════════╝ msprime_nogf #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 62745║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 208║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 14.4 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │247454│ 7.6 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 104│ 2.9 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 69172│ 2.4 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │ 32685│893.7 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 6│414 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 2│ 3.9 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │ 69144│ 1.6 MiB│ No║ #> ╚═══════════╧══════╧═════════╧════════════╝"},{"path":"https://www.slendr.net/articles/vignette-07-backends.html","id":"comparing-results-of-population-genetics-statistics","dir":"Articles","previous_headings":"Compiling the model and simulating data","what":"Comparing results of population genetics statistics","title":"Simulating data with SLiM and msprime backends","text":"loaded msprime SLiM tree sequences generated model, let’s see can get comparable results calculate statistics interest. Let’s first extract individuals populations x1 x2 estimate values \\(f_4(c, x1 \\textrm{ } x2; b, o)\\) (significantly negative individuals population x1 due ’s ancestry coming b introgression models consistent zero x2) \\(f_4\\textrm{-ratio}(, b, \\textrm{ } x2; c, o)\\), estimates proportion b-like ancestry x1 x2: Now, let’s repeat analysis tree sequences produced msprime backend two slendr demographic models: Finally can proceed plotting SLiM msprime backend results two models compare together. noted , despite fact SLiM forward simulator msprime coalescent simulator, population genetic expectations gene flow gene flow models match closely (barring level uncertainty expected due randomness population genetic processes play). Things seem looking good behave expected! couple observations: model without gene flow, \\(f_4\\) statistic value zero x1 x2 populations. expected, \\(f_4\\) ~0 consistent relationship lineages conforming standard phylogenetic tree (admixture edges). Essentially, \\(f_4\\) hypothesis test “tree-ness” data. model includes gene flow b x1, \\(f_4\\) value significantly negative. means simple tree hypothesis can rejected gene flow must occurred b x1. Note test reveal direction gene flow, ’s presence. Consistently \\(f_4\\) results, \\(f_4-ratio\\) estimates match expectations. Specifically, statistic estimates around 10% ancestry b x1 gene flow model 0% ancestry cases. importantly, results obtained SLiM msprime back ends nearly exactly . means (non-spatial models) can use SLiM msprime backend interchangeably.","code":"# extract vector of names of the \"test individuals\" in populations `x1` and `x2` X <- ts_samples(slim_gf) %>% filter(pop %in% c(\"x1\", \"x2\")) %>% pull(name) X #> [1] \"x1_1\" \"x1_2\" \"x1_3\" \"x1_4\" \"x1_5\" \"x1_6\" \"x1_7\" \"x1_8\" \"x1_9\" #> [10] \"x1_10\" \"x1_11\" \"x1_12\" \"x1_13\" \"x1_14\" \"x1_15\" \"x1_16\" \"x1_17\" \"x1_18\" #> [19] \"x1_19\" \"x1_20\" \"x1_21\" \"x1_22\" \"x1_23\" \"x1_24\" \"x1_25\" \"x1_26\" \"x1_27\" #> [28] \"x1_28\" \"x1_29\" \"x1_30\" \"x1_31\" \"x1_32\" \"x1_33\" \"x1_34\" \"x1_35\" \"x1_36\" #> [37] \"x1_37\" \"x1_38\" \"x1_39\" \"x1_40\" \"x1_41\" \"x1_42\" \"x1_43\" \"x1_44\" \"x1_45\" #> [46] \"x1_46\" \"x1_47\" \"x1_48\" \"x1_49\" \"x1_50\" \"x2_1\" \"x2_2\" \"x2_3\" \"x2_4\" #> [55] \"x2_5\" \"x2_6\" \"x2_7\" \"x2_8\" \"x2_9\" \"x2_10\" \"x2_11\" \"x2_12\" \"x2_13\" #> [64] \"x2_14\" \"x2_15\" \"x2_16\" \"x2_17\" \"x2_18\" \"x2_19\" \"x2_20\" \"x2_21\" \"x2_22\" #> [73] \"x2_23\" \"x2_24\" \"x2_25\" \"x2_26\" \"x2_27\" \"x2_28\" \"x2_29\" \"x2_30\" \"x2_31\" #> [82] \"x2_32\" \"x2_33\" \"x2_34\" \"x2_35\" \"x2_36\" \"x2_37\" \"x2_38\" \"x2_39\" \"x2_40\" #> [91] \"x2_41\" \"x2_42\" \"x2_43\" \"x2_44\" \"x2_45\" \"x2_46\" \"x2_47\" \"x2_48\" \"x2_49\" #> [100] \"x2_50\" # calculate f4-statistics on individuals of `x1` and `x2` populations using data # from the two models (a model with no gene flow and a gene flow model) -- we use # map_dfr to iterate across all individuals from `X_individuals` and binding all # resulting data frames into a single data frame df_slim_f4 <- rbind( map_dfr(X, ~ ts_f4(slim_nogf, \"c_1\", .x, \"b_1\", \"outgroup_1\")) %>% mutate(model = \"no gene flow\"), map_dfr(X, ~ ts_f4(slim_gf, \"c_1\", .x, \"b_1\", \"outgroup_1\")) %>% mutate(model = \"gene flow\") ) %>% select(X, f4, model) %>% mutate(simulator = \"SLiM backend\") # compute the proportions of `b` ancestry in `x1` (expected 10%) and `x2` # (expected 0% because this population did not receive any gene flow from `b`) df_slim_f4ratio <- rbind( ts_f4ratio(slim_nogf, X, \"a_1\", \"b_1\", \"c_1\", \"outgroup_1\") %>% mutate(model = \"no gene flow\"), ts_f4ratio(slim_gf, X, \"a_1\", \"b_1\", \"c_1\", \"outgroup_1\") %>% mutate(model = \"gene flow\") ) %>% select(X, alpha, model) %>% mutate(simulator = \"SLiM backend\") df_msprime_f4 <- rbind( map_dfr(X, ~ ts_f4(msprime_nogf, \"c_1\", .x, \"b_1\", \"outgroup_1\")) %>% mutate(model = \"no gene flow\"), map_dfr(X, ~ ts_f4(msprime_gf, \"c_1\", .x, \"b_1\", \"outgroup_1\")) %>% mutate(model = \"gene flow\") ) %>% select(X, f4, model) %>% mutate(simulator = \"msprime backend\") # compute the proportions of `b` ancestry in `x1` (expected 10%) and `x2` # (expected 0% because this population did not receive any gene flow from `b`) df_msprime_f4ratio <- rbind( ts_f4ratio(msprime_nogf, X, \"a_1\", \"b_1\", \"c_1\", \"outgroup_1\") %>% mutate(model = \"no gene flow\"), ts_f4ratio(msprime_gf, X, \"a_1\", \"b_1\", \"c_1\", \"outgroup_1\") %>% mutate(model = \"gene flow\") ) %>% select(X, alpha, model) %>% mutate(simulator = \"msprime backend\") df_f4 <- rbind(df_slim_f4, df_msprime_f4) %>% mutate(population = ifelse(grepl(\"x1_\", X), \"x1 (received gene flow)\", \"x2 (no gene flow)\")) ggplot(df_f4, aes(f4, fill = population)) + geom_histogram(bins = 50) + facet_grid(simulator ~ model) + geom_vline(xintercept = 0, linetype = 2) + labs(y = \"number of individuals\", x = \"f4 statistic\", title = \"f4(c, x1 or x2; b, outgroup)\", subtitle = \"f4 ~0 is consistent with no gene flow, negative value indicates gene flow with 'b'\") + theme(legend.position = \"bottom\") df_f4ratio <- rbind(df_slim_f4ratio, df_msprime_f4ratio) %>% mutate(population = ifelse(grepl(\"x1_\", X), \"x1 (received gene flow)\", \"x2 (no gene flow)\")) ggplot(df_f4ratio, aes(alpha, fill = population)) + geom_histogram(bins = 30) + facet_grid(simulator ~ model) + geom_vline(xintercept = 0.1, linetype = 2) + labs(y = \"number of individuals\", x = \"ancestry proportion (f4-ratio statistic)\", title = \"f4-ratio estimate of 'b' ancestry calculated from simulated data\", subtitle = \"f4-ratio = f4(a, outgroup; x1 or x2, c) / f4(a, outgroup; b, c)\") + theme(legend.position = \"bottom\")"},{"path":"https://www.slendr.net/articles/vignette-07-backends.html","id":"computing-allele-frequency-spectra","dir":"Articles","previous_headings":"","what":"Computing allele frequency spectra","title":"Simulating data with SLiM and msprime backends","text":"Let’s look one example. Imagine following five demographic models describing changes population size abstract population: models population size change events , depending specifics project, defined using different time units. work radiocarbon-dated samples ancient DNA might used thinking population history units “years present”—case, “present” time (bottom figure) time 0 earlier events specified “5000 years present”, etc. hand, interested modelling theoretical population, might want concern quite happy starting simulation “generation 1” continue specified “generation X”. slendr package makes extremely easy, can specify times whatever direction units want, long kept consistent populations events model. rather unique feature among popgen simulation software programs either make express model “generations forward direction”, explicitly convert time generations going backwards. previous section vignette shown SLiM msprime can used simulation backend. remainder vignette present additional analysis, demonstrating fact can express time models forward backward direction still run models slendr’s SLiM (forward simulator) msprime (backward simulator). Specifically, define five demographic models figure twice, different orientations time – forward backward. compute allele frequency spectrum simulation (five models, forward backward) verify forward backward pairs give result regardless whether use SLiM back end msprime backend.","code":""},{"path":"https://www.slendr.net/articles/vignette-07-backends.html","id":"model-definition","dir":"Articles","previous_headings":"Computing allele frequency spectra","what":"Model definition","title":"Simulating data with SLiM and msprime backends","text":"First, let’s define five population histories forward time direction: Now let’s flip flow time around define population histories units “time ago”: convenience, write helper function , given population history object (ten objects just ), compile slendr model, run SLiM msprime back ends, load tree sequence, compute allele frequency spectrum (AFS) . save us lots code repetition (always good thing), minimize chance copy-pasting bugs (definitely good thing!) compare AFS patterns across different models two slendr simulation back ends (according population genetics theory). Now function doesn’t anything special. simply wraps standard slendr simulation pipeline (1. create population(s); 2. compile model object; 3. simulate model; 4. load results; 5. analyse data) single function. Now whole pipeline, can generate simulated data bind result single data frame: Finally, can plot allele frequency spectra models, two time directions, two simulation back ends: , couple things note: two models involve population contraction (single step exponential collapse), see decrease low frequency variants. hand, models population expansion show high proportion low frequency variants. model constant population size shows intermediate pattern. nice validation simulation works expected exactly predicted population genetics theory. forward backward time models give exactly result. unexpected anything else bug slendr. However, although unsurprising, hope makes clear free use whatever time unit specification want encode slendr models. non-spatial models, results obtained msprime SLiM back ends consistent one another. , makes sense although completely different software, population genetic theory governing shape allele frequency spectra applies equally . fact, example just implemented important part slendr unit test suite verifies simulations created slendr correct.","code":"N <- 1000 N_factor <- 5 # by what factor should Ne change seq_len <- 50e6 rec_rate <- 1e-8 mut_rate <- 1e-8 # constant Ne model forward_const <- population(\"const\", time = 1, N = N) # decreasing step Ne model forward_decr <- population(\"decr\", time = 1, N = N, map = FALSE) %>% resize(time = 2000, N = N / N_factor, how = \"step\") # increasing step Ne model forward_incr <- population(\"inc\", time = 1, N = N) %>% resize(time = 2000, N = N * N_factor, how = \"step\") # exponential increase in size forward_exp_incr <- population(\"exp_inc\", time = 1, N = N) %>% resize(time = 2000, end = 3000, N = N * N_factor, how = \"exponential\") # exponential decrease in size forward_exp_decr <- population(\"exp_decr\", time = 1, N = N) %>% resize(time = 2000, end = 3000, N = N / N_factor, how = \"exponential\") # constant Ne model backward_const <- population(\"const\", time = 5000, N = N) # decreasing step Ne model backward_decr <- population(\"decr\", time = 5000, N = N) %>% resize(time = 3000, N = N / N_factor, how = \"step\") # increasing step Ne model backward_incr <- population(\"inc\", time = 5000, N = N) %>% resize(time = 3000, N = N * N_factor, how = \"step\") # exponential increase in size backward_exp_incr <- population(\"exp_inc\", time = 5000, N = N) %>% resize(time = 3000, end = 2000, N = N * N_factor, how = \"exponential\") # exponential decrease in size backward_exp_decr <- population(\"exp_decr\", time = 5000, N = N) %>% resize(time = 3000, end = 2000, N = N / N_factor, how = \"exponential\") compile_run_afs <- function(model_name, pop, seed = 42) { # maximum length of the simulation (necessary for forward models which start # in generation 1) simulation_length <- 5000 # define sampling times given the direction of time if (attr(pop, \"history\")[[1]]$time == 1) { sampling_time <- simulation_length direction <- \"forward\" } else { sampling_time <- 0 direction <- \"backward\" } # compile model model <- compile_model(pop, generation_time = 15, direction = direction, simulation_length = simulation_length) samples <- schedule_sampling(model, times = sampling_time, list(pop, 50)) # run the model in SLiM ts_slim <- slim(model, sequence_length = seq_len, recombination_rate = rec_rate, samples = samples, random_seed = seed, verbose = FALSE) # run the same model in msprim ts_msprime <- msprime(model, sequence_length = seq_len, recombination_rate = rec_rate, samples = samples, random_seed = seed, verbose = FALSE) # load the SLiM tree sequence ts_slim <- ts_recapitate(ts_slim, Ne = N, recombination_rate = rec_rate, random_seed = seed) %>% ts_mutate(mut_rate, random_seed = seed) # load the msprime tree sequence ts_msprime <- ts_mutate(ts_msprime, mut_rate, random_seed = seed) # compute the AFS from the SLiM and msprime tree sequences and bind the # results (derived allele counts per frequency bin) in a data frame msprime_afs <- ts_afs(ts_msprime, polarised = TRUE)[-1] slim_afs <- ts_afs(ts_slim, polarised = TRUE)[-1] rbind( data.frame(simulator = \"msprime\", model = model_name, f = msprime_afs), data.frame(simulator = \"SLiM\", model = model_name, f = slim_afs) ) %>% group_by(simulator, model) %>% mutate(n = 1:n(), direction = direction) %>% ungroup() } afs <- bind_rows( compile_run_afs(\"constant\", forward_const), compile_run_afs(\"constant\", backward_const), compile_run_afs(\"step contraction\", forward_decr), compile_run_afs(\"step contraction\", backward_decr), compile_run_afs(\"step increase\", forward_incr), compile_run_afs(\"step increase\", backward_incr), compile_run_afs(\"exponential decrease\", forward_exp_decr), compile_run_afs(\"exponential decrease\", backward_exp_decr), compile_run_afs(\"exponential increase\", forward_exp_incr), compile_run_afs(\"exponential increase\", backward_exp_incr) ) %>% mutate(model = factor( model, levels = c(\"step contraction\", \"constant\", \"step increase\", \"exponential decrease\", \"exponential increase\")) ) ggplot(afs, aes(n, f, color = direction, linetype = simulator)) + geom_line(stat = \"identity\") + facet_wrap(~ model) + labs(x = \"number of derived alleles\", y = \"frequency\", title = \"Site frequency spectra obtained from five demographic models\", subtitle = \"Each model was specified in forward or backward direction of time and executed by two different backend scripts in slendr (SLiM and msprime)\") + guides(color = guide_legend(\"direction of\\ntime in slendr\"), linetype = guide_legend(\"slendr backend\\nengine used\")) + scale_linetype_manual(values = c(3, 2)) + scale_x_continuous(breaks = c(1, seq(20, 100, 20)), limits = c(1, 100)) + theme(legend.position = \"bottom\")"},{"path":"https://www.slendr.net/articles/vignette-07-backends.html","id":"conclusion","dir":"Articles","previous_headings":"","what":"Conclusion","title":"Simulating data with SLiM and msprime backends","text":"example shows standard, non-spatial demographic model like implement simulate R, slendr gives way efficiently using ’s msprime back end addition SLiM back end used throughout documentation.","code":""},{"path":"https://www.slendr.net/articles/vignette-08-nonslendr-tskit.html","id":"non-spatial-slim-tree-sequences","dir":"Articles","previous_headings":"","what":"Non-spatial SLiM tree sequences","title":"Analyzing non-slendr tree sequences","text":"Consider following SLiM script, creates couple populations (different \\(N_e\\)) splitting ancestral population p1 (lets save /tmp/nonspatial.slim): run script SLiM, can use slendr load output tree sequence (saved /tmp/nonspatial-slim.trees), simplify , overlay mutations using standard functionality originally developed slendr tree sequences. Note command use loading slendr tree sequences, except direct ts_load() function straight tree-sequence output file rather using ts_load() format used working standard slendr simulations. way, slendr can extract information individual’s names, nodes, population assignments, etc. just slendr tree sequence function ts_nodes(). standard slendr models, function loads “raw” node individual tree-sequences tables, performs couple join operations, presents whole thing nice unified form interactive data analysis (can also include spatial information—see ): Moving tskit statistics, can use data table extract list nodes belonging population (various tskit tree-sequence statistics operate , slendr follows design). computing nucleotide diversity four populations using ts_diversity() function, first creating list lists node IDs (.e. chromosomes) individuals population: Just slendr tree sequences (demonstrated paper) can get individual trees , extracted phylogenetic format provided ape R package. first simplify tree sequence even just 10 nodes make things manageable: R tree object, can use packages like ggtree visualize tree (phylogenetic package work ). Note nodes ‘ape phylo’ trees must conform strict format (must labelled 1...N), extract information node IDs tskit tree-sequence data able plot tree.","code":"initialize() { setSeed(42); initializeTreeSeq(); initializeMutationRate(0); initializeMutationType(\"m1\", 0.5, \"f\", 0.0); initializeGenomicElementType(\"g1\", m1, 1.0); initializeGenomicElement(g1, 0, 1e6); initializeRecombinationRate(1e-8); } 1 early() { sim.addSubpop(\"p1\", 10); } 1000 early() { sim.addSubpopSplit(\"p2\", 500, p1); } 3000 early() { sim.addSubpopSplit(\"p3\", 2500, p1); } 5000 early() { sim.addSubpopSplit(\"p4\", 10000, p1); } 6000 late() { sim.treeSeqOutput(\"/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpZrPslt/file1265571b28895\"); } ts <- ts_load(nonspatial_trees_file) %>% ts_simplify() %>% ts_mutate(mutation_rate = 1e-7, random_seed = SEED) data <- ts_nodes(ts) %>% dplyr::filter(sampled) data #> # A tibble: 26,020 × 11 #> pop node_id time time_tskit sampled remembered retained alive pedigree_id #> #> 1 p1 0 0 0 TRUE FALSE FALSE TRUE 20073000 #> 2 p1 1 0 0 TRUE FALSE FALSE TRUE 20073000 #> 3 p1 2 0 0 TRUE FALSE FALSE TRUE 20073001 #> 4 p1 3 0 0 TRUE FALSE FALSE TRUE 20073001 #> 5 p1 4 0 0 TRUE FALSE FALSE TRUE 20073002 #> 6 p1 5 0 0 TRUE FALSE FALSE TRUE 20073002 #> 7 p1 6 0 0 TRUE FALSE FALSE TRUE 20073003 #> 8 p1 7 0 0 TRUE FALSE FALSE TRUE 20073003 #> 9 p1 8 0 0 TRUE FALSE FALSE TRUE 20073004 #> 10 p1 9 0 0 TRUE FALSE FALSE TRUE 20073004 #> # ℹ 26,010 more rows #> # ℹ 2 more variables: ind_id , pop_id sample_sets <- split(data$node_id, data$pop) # compute nucleotide diversity in each population # (any other ts_*() tskit R interface function should work) ts_diversity(ts, sample_sets) #> # A tibble: 4 × 2 #> set diversity #> #> 1 p1 0.00000755 #> 2 p2 0.000241 #> 3 p3 0.000463 #> 4 p4 0.000201 samples <- sample(data$node_id, 10) ts_small <- ts_simplify(ts, simplify_to = samples) # extract the 42nd tree in the genealogy to an R 'phylo' format tree <- ts_phylo(ts_small, 42 - 1) #> Starting checking the validity of tree... #> Found number of tips: n = 10 #> Found number of nodes: m = 9 #> Done. tree #> #> Phylogenetic tree with 10 tips and 9 internal nodes. #> #> Tip labels: #> 1, 0, 9, 4, 8, 7, ... #> Node labels: #> 45, 28, 22, 31, 35, 36, ... #> #> Rooted; includes branch lengths. library(ggtree) #> ggtree v3.10.0 For help: https://yulab-smu.top/treedata-book/ #> #> If you use the ggtree package suite in published research, please cite #> the appropriate paper(s): #> #> Guangchuang Yu, David Smith, Huachen Zhu, Yi Guan, Tommy Tsan-Yuk Lam. #> ggtree: an R package for visualization and annotation of phylogenetic #> trees with their covariates and other associated data. Methods in #> Ecology and Evolution. 2017, 8(1):28-36. doi:10.1111/2041-210X.12628 #> #> Guangchuang Yu. Data Integration, Manipulation and Visualization of #> Phylogenetic Trees (1st edition). Chapman and Hall/CRC. 2022, #> doi:10.1201/9781003279242 #> #> LG Wang, TTY Lam, S Xu, Z Dai, L Zhou, T Feng, P Guo, CW Dunn, BR #> Jones, T Bradley, H Zhu, Y Guan, Y Jiang, G Yu. treeio: an R package #> for phylogenetic tree input and output with richly annotated and #> associated data. Molecular Biology and Evolution. 2020, 37(2):599-603. #> doi: 10.1093/molbev/msz240 #> #> Attaching package: 'ggtree' #> The following object is masked from 'package:magrittr': #> #> inset labels <- ts_nodes(tree) %>% select(node = phylo_id, tskit_id = node_id) ggtree(tree, branch.length = \"none\") %<+% labels + geom_label(aes(label = tskit_id)) library(ape) plot(tree, show.tip.label = FALSE) nodelabels() tiplabels()"},{"path":"https://www.slendr.net/articles/vignette-08-nonslendr-tskit.html","id":"msprime-non-slendr-tree-sequences","dir":"Articles","previous_headings":"","what":"msprime (non-slendr) tree sequences","title":"Analyzing non-slendr tree sequences","text":"applies also msprime tree sequences (really surprising, given ’s tskit hood). can start Python: can proceed loading msprime tree sequence R analyze slendr functionality:","code":"import msprime ts = msprime.sim_ancestry(100) ts.dump() ts <- ts_load(msprime_trees_file) ts_nodes(ts) #> # A tibble: 199 × 7 #> pop ind_id node_id time time_tskit sampled pop_id #> #> 1 0 NA 0 0 0 TRUE 0 #> 2 0 NA 1 0 0 TRUE 0 #> 3 0 NA 2 0 0 TRUE 0 #> 4 0 NA 3 0 0 TRUE 0 #> 5 0 NA 4 0 0 TRUE 0 #> 6 0 NA 5 0 0 TRUE 0 #> 7 0 NA 6 0 0 TRUE 0 #> 8 0 NA 7 0 0 TRUE 0 #> 9 0 NA 8 0 0 TRUE 0 #> 10 0 NA 9 0 0 TRUE 0 #> # ℹ 189 more rows"},{"path":"https://www.slendr.net/articles/vignette-08-nonslendr-tskit.html","id":"spatial-slim-non-slendr-tree-sequences","dir":"Articles","previous_headings":"","what":"Spatial SLiM (non-slendr) tree sequences","title":"Analyzing non-slendr tree sequences","text":"Furthermore, generalized interface also supports slendr’s spatial tree-sequence features, bells whistles. instance, lets take following spatial SLiM script (modified SLiM manual) execute SLiM usual way: can load simplify output tree sequence just vignette (anywhere slendr documentation): Finally, can access spatio-temporal data embedded output tree sequence standard slendr way (note spatial sf column location POINT data type): get tree sequence converted spatial sf data format, can use standard geospatial packages use spatial data analysis methods packages provide. briefly demonstrate means, can trivially plot location recorded node: can also collect spatio-temporal ancestry information particular node (.e. times locations ancestors way root, “link” plot signifying parent-child edge somewhere along tree sequence) plot 2D surface (x y dimensions [0, 1]). plot little chaotic, hopefully conveys idea (“focal node” 0 highlighted red). essentially plot last figure paper.","code":"initialize() { setSeed(42); initializeSLiMOptions(keepPedigrees=T, dimensionality=\"xy\"); initializeTreeSeq(); initializeMutationRate(1e-7); initializeMutationType(\"m1\", 0.5, \"f\", 0.0); initializeGenomicElementType(\"g1\", m1, 1.0); initializeGenomicElement(g1, 0, 1e6); initializeRecombinationRate(1e-8); } 1 early() { sim.addSubpop(\"p1\", 500); // initial positions are random in ([0,1], [0,1]) p1.individuals.x = runif(p1.individualCount); p1.individuals.y = runif(p1.individualCount); } modifyChild() { // draw a child position near the first parent, within bounds do child.x = parent1.x + rnorm(1, 0, 0.02); while ((child.x < 0.0) | (child.x > 1.0)); do child.y = parent1.y + rnorm(1, 0, 0.02); while ((child.y < 0.0) | (child.y > 1.0)); return T; } 1: late() { sim.treeSeqRememberIndividuals(sim.subpopulations.individuals, permanent = F); } 10000 late() { sim.treeSeqOutput(\"/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpZrPslt/file12655786f22f\"); } ts <- ts_load(spatial_trees_file) %>% ts_simplify() data <- ts_nodes(ts) data #> Simple feature collection with 1941 features and 11 fields #> Geometry type: POINT #> Dimension: XY #> Bounding box: xmin: 0.02032986 ymin: 0.001180405 xmax: 0.9990375 ymax: 0.9979969 #> CRS: NA #> # A tibble: 1,941 × 12 #> pop node_id time time_tskit location sampled remembered #> #> 1 p1 0 0 0 (0.3158008 0.8489413) TRUE FALSE #> 2 p1 1 0 0 (0.3158008 0.8489413) TRUE FALSE #> 3 p1 2 0 0 (0.5946915 0.5792152) TRUE FALSE #> 4 p1 3 0 0 (0.5946915 0.5792152) TRUE FALSE #> 5 p1 4 0 0 (0.8320243 0.5595862) TRUE FALSE #> 6 p1 5 0 0 (0.8320243 0.5595862) TRUE FALSE #> 7 p1 6 0 0 (0.5532792 0.1833623) TRUE FALSE #> 8 p1 7 0 0 (0.5532792 0.1833623) TRUE FALSE #> 9 p1 8 0 0 (0.7333698 0.01834573) TRUE FALSE #> 10 p1 9 0 0 (0.7333698 0.01834573) TRUE FALSE #> # ℹ 1,931 more rows #> # ℹ 5 more variables: retained , alive , pedigree_id , #> # ind_id , pop_id ggplot() + geom_sf(data = data, aes(color = time), alpha = 0.5) ancestral_links <- ts_ancestors(ts, 0) ggplot() + geom_sf(data = ancestral_links, size = 0.5, aes(alpha = parent_time)) + geom_sf(data = sf::st_set_geometry(ancestral_links, \"parent_location\"), aes(color = parent_time)) + geom_sf(data = data[data$node_id == 0, ], size = 3, color = \"red\")"},{"path":"https://www.slendr.net/articles/vignette-08-nonslendr-tskit.html","id":"conclusion","dir":"Articles","previous_headings":"","what":"Conclusion","title":"Analyzing non-slendr tree sequences","text":"vignette gave brief overview using slendr’s R-tskit interface loading, processing, analyzing “pure” non-slendr tree sequences produced msprime SLiM scripts. Although touched upon basic features R-tskit interface standard tree sequences, important note far slendr concerned, matter tree sequence produced, long conforms tskit specification. means regardless source tree sequence data, able use slendr’s tskit functionality run analyses.","code":""},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"note","dir":"Articles","previous_headings":"","what":"Note","title":"Examples from the slendr paper","text":"Since publication slendr paper, new versions SLiM slendr released. Specifically, results paper based SLiM version 4.0.1 slendr version 0.5. Whenever new version SLiM released, ’s always chance aspect randomness simulation changes slightly, affects results even though random seed kept value. , figures paper (specifically figure Example 4 paper) look slightly different. However, results still relevant applicable, just presentation changed.","code":"# workaround for GitHub actions getting \"Killed\" due to out of memory issues # -- when running unit tests on GitHub, smaller amount of sequence will be # simulated if (Sys.getenv(\"RUNNER_OS\") != \"\") { scaling <- 10 # use 10X less sequence on GitHub actions } else { scaling <- 1 # but simulate normal amount of data otherwise } library(slendr) library(dplyr) #> #> Attaching package: 'dplyr' #> The following objects are masked from 'package:stats': #> #> filter, lag #> The following objects are masked from 'package:base': #> #> intersect, setdiff, setequal, union library(ggplot2) library(purrr) library(tidyr) library(cowplot) library(forcats) init_env() #> The interface to all required Python modules has been activated. SEED <- 42 set.seed(SEED) # placeholder \"figure\" where a code chunk will be pasted p_code <- ggplot() + geom_text(aes(x = 1, y = 1), label = \"code will be here\") + theme_void()"},{"path":[]},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"script-from-panel-a","dir":"Articles","previous_headings":"Example 1 (Figure 2)","what":"Script from panel A","title":"Examples from the slendr paper","text":"","code":"o <- population(\"o\", time = 1, N = 100) c <- population(\"c\", time = 2500, N = 100, parent = o) a <- population(\"a\", time = 2800, N = 100, parent = c) b <- population(\"b\", time = 3700, N = 100, parent = a) x1 <- population(\"x1\", time = 4000, N = 15000, parent = c) x2 <- population(\"x2\", time = 4300, N = 15000, parent = x1) gf <- gene_flow(from = b, to = x1, start = 5400, end = 5800, 0.1) model <- compile_model( populations = list(o, a, b, c, x1, x2), gene_flow = gf, generation_time = 1, simulation_length = 6000 ) plot_model(model, sizes = FALSE, proportions = TRUE) # panel B ts <- msprime(model, sequence_length = 100e6 / scaling, recombination_rate = 1e-8, random_seed = SEED) %>% ts_mutate(mutation_rate = 1e-8, random_seed = SEED) samples <- ts_samples(ts) %>% group_by(pop) %>% sample_n(100) # panel C divergence <- ts_divergence(ts, split(samples$name, samples$pop)) # panel D f4ratio <- ts_f4ratio( ts, X = filter(samples, pop %in% c(\"x1\", \"x2\"))$name, A = \"a_1\", B = \"b_1\", C = \"c_1\", O = \"o_1\" )"},{"path":[]},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"plotting-code","dir":"Articles","previous_headings":"Example 1 (Figure 2)","what":"Plotting code","title":"Examples from the slendr paper","text":"","code":"divergence <- divergence %>% mutate(pair = paste(x, \"-\", y)) f4ratio <- f4ratio %>% mutate(population = gsub(\"^(.*)_.*$\", \"\\\\1\", X), alpha = alpha * 100) p_ex1_divergence <- divergence %>% ggplot(aes(fct_reorder(pair, divergence), divergence)) + geom_point(size = 2.5) + xlab(\"population pair\") + ylab(\"pairwise divergence\") + theme_minimal() + theme(legend.position = \"bottom\", legend.text = element_text(size = 10), axis.text.x = element_text(hjust = 1, angle = 45, size = 8), axis.title.x = element_blank()) p_ex1_f4ratio <- f4ratio %>% ggplot(aes(population, alpha)) + geom_hline(yintercept = 0, linetype = 2) + geom_jitter(alpha = 0.5) + geom_boxplot(outlier.shape = NA, alpha = 0.7) + ylab(base::expression(italic(\"f\")[4]~\"-ratio ancestry proportion [%]\")) + theme_minimal() + coord_cartesian(ylim = c(0, 20)) + theme(legend.position = \"none\", axis.text.x = element_text(size = 11), axis.title.x = element_blank(), panel.grid.major.x = element_blank())#; p_ex3_f4ratio # let's avoid ggpubr as another dependency: # https://github.com/kassambara/ggpubr/blob/master/R/as_ggplot.R#L27 p_ex1_legend <- ggdraw() + draw_grob(grid::grobTree(get_legend(p_ex1_divergence))) p_ex1_model <- plot_model(model, sizes = FALSE, proportions = TRUE) p_ex1 <- plot_grid( p_code, plot_grid( p_ex1_model, plot_grid( p_ex1_divergence + theme(legend.position = \"none\"), p_ex1_f4ratio, ncol = 2, rel_widths = c(1, 0.8), labels = c(\"C\", \"D\") ), p_ex1_legend, nrow = 3, rel_heights = c(1, 1, 0.1), labels = \"B\" ), nrow = 1, labels = c(\"A\", \"\") ) p_ex1"},{"path":[]},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"script-from-panel-a-1","dir":"Articles","previous_headings":"Example 2 (Figure 3)","what":"Script from panel A","title":"Examples from the slendr paper","text":"","code":"map <- world(xrange = c(0, 10), yrange = c(0, 10), landscape = region(center = c(5, 5), radius = 5)) p1 <- population(\"pop1\", time = 1, N = 2000, map = map, competition = 0) p2 <- population(\"pop2\", time = 1, N = 2000, map = map, competition = 9) p3 <- population(\"pop3\", time = 1, N = 2000, map = map, competition = 6) p4 <- population(\"pop4\", time = 1, N = 2000, map = map, competition = 5) p5 <- population(\"pop5\", time = 1, N = 2000, map = map, competition = 4) p6 <- population(\"pop6\", time = 1, N = 2000, map = map, competition = 3) p7 <- population(\"pop7\", time = 1, N = 2000, map = map, competition = 2) p8 <- population(\"pop8\", time = 1, N = 2000, map = map, competition = 1) model <- compile_model( populations = list(p1, p2, p3, p4, p5, p6, p7, p8), generation_time = 1, simulation_length = 5000, resolution = 0.1, mating = 0.1, dispersal = 0.05 ) ts <- slim(model, sequence_length = 10e6 / scaling, recombination_rate = 1e-8, random_seed = SEED) %>% ts_simplify() %>% ts_mutate(mutation_rate = 1e-7, random_seed = SEED) #> Warning: Simplifying a non-recapitated tree sequence. Make sure this is what #> you really want locations <- ts_nodes(ts) %>% filter(time == max(time)) heterozygosity <- ts_samples(ts) %>% group_by(pop) %>% sample_n(100) %>% mutate(pi = ts_diversity(ts, name)$diversity)"},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"plotting-code-1","dir":"Articles","previous_headings":"Example 2 (Figure 3)","what":"Plotting code","title":"Examples from the slendr paper","text":"","code":"p_ex2_clustering <- ggplot() + geom_sf(data = map) + geom_sf(data = locations, aes(color = pop), size = 0.05, alpha = 0.25) + facet_grid(. ~ pop, switch = \"x\") + xlab(\"spatial distributions emerged in the simulation\") + theme( strip.background = element_blank(), strip.text = element_text(size = 11), panel.grid = element_blank(), axis.ticks = element_blank(), axis.text = element_blank(), panel.background = element_blank() ) + guides(color = \"none\") p_ex2_diversity <- ggplot(heterozygosity, aes(pop, pi, color = pop)) + geom_violin(color = \"black\") + geom_jitter(alpha = 0.5) + labs(y = \"individual heterozygosity\") + guides(color = \"none\") + theme_minimal() + theme(axis.title.x = element_blank(), axis.text.x = element_blank(), panel.grid.major.x = element_blank(), plot.margin = margin(t = 0.2, r = 0.2, b = -0.1, l = 0.2, \"cm\")) p_ex2 <- plot_grid( p_code, plot_grid( p_ex2_diversity, p_ex2_clustering + theme(plot.margin = margin(t = 0, r = 0.4, b = 0, l = 1.8, \"cm\")), nrow = 2, rel_heights = c(1, 0.5), labels = c(\"B\", \"C\") ), nrow = 2, labels = c(\"A\", \"\"), rel_heights = c(1.5, 1) ) p_ex2"},{"path":[]},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"script-from-panel-a-2","dir":"Articles","previous_headings":"Example 3 (Figure 4)","what":"Script from panel A","title":"Examples from the slendr paper","text":"","code":"map <- world(xrange = c(-13, 70), yrange = c(18, 65), crs = 3035) #> Reading layer `ne_110m_land' from data source #> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/Rtmp6dsC0I/naturalearth/ne_110m_land.shp' #> using driver `ESRI Shapefile' #> Simple feature collection with 127 features and 3 fields #> Geometry type: POLYGON #> Dimension: XY #> Bounding box: xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513 #> Geodetic CRS: WGS 84 R1 <- region( \"EHG range\", map, polygon = list(c(26, 55), c(38, 53), c(48, 53), c(60, 53), c(60, 60), c(48, 63), c(38, 63), c(26, 60)) ) R2 <- region( \"Europe\", map, polygon = list( c(-8, 35), c(-5, 36), c(10, 38), c(20, 35), c(25, 35), c(33, 45), c(20, 58), c(-5, 60), c(-15, 50) ) ) R3 <- region( \"Anatolia\", map, polygon = list(c(28, 35), c(40, 35), c(42, 40), c(30, 43), c(27, 40), c(25, 38)) ) R4 <- join(R2, R3) R5 <- region( \"YAM range\", map, polygon = list(c(26, 50), c(38, 49), c(48, 50), c(48, 56), c(38, 59), c(26, 56)) ) ooa_trajectory <- list(c(40, 30), c(50, 30), c(60, 40), c(45, 55)) map <- world(xrange = c(-13, 70), yrange = c(18, 65), crs = 3035) #> Reading layer `ne_110m_land' from data source #> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/Rtmp6dsC0I/naturalearth/ne_110m_land.shp' #> using driver `ESRI Shapefile' #> Simple feature collection with 127 features and 3 fields #> Geometry type: POLYGON #> Dimension: XY #> Bounding box: xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513 #> Geodetic CRS: WGS 84 ooa <- population( \"OOA\", time = 50000, N = 500, remove = 23000, map = map, center = c(33, 30), radius = 400e3 ) %>% move(trajectory = ooa_trajectory, start = 50000, end = 40000, snapshots = 30) ehg <- population( \"EHG\", time = 28000, N = 1000, parent = ooa, remove = 6000, map = map, polygon = R1 ) eur <- population( \"EUR\", time = 30000, N = 2000, parent = ooa, map = map, polygon = R2 ) %>% resize(N = 10000, time = 5000, end = 0, how = \"exponential\") ana <- population( \"ANA\", time = 25000, N = 4000, parent = ooa, remove = 3000, map = map, polygon = R3 ) %>% expand_range(by = 3e6, start = 10000, end = 7000, polygon = R4, snapshots = 15) yam <- population( \"YAM\", time = 7000, N = 600, parent = ehg, remove = 2500, map = map, polygon = R5 ) %>% move(trajectory = list(c(15, 50)), start = 5000, end = 3000, snapshots = 10) gf <- list( gene_flow(ana, to = yam, rate = 0.5, start = 6500, end = 5000), gene_flow(ana, to = eur, rate = 0.6, start = 8000, end = 6000), gene_flow(yam, to = eur, rate = 0.7, start = 3500, end = 3000) ) model <- compile_model( populations = list(ooa, ehg, eur, ana, yam), gene_flow = gf, generation_time = 30, resolution = 10e3, competition = 150e3, mating = 120e3, dispersal = 90e3 ) samples <- schedule_sampling( model, times = seq(0, 50000, by = 1000), list(ehg, 20), list(ana, 20), list(yam, 20), list(eur, 20) ) plot_model(model, sizes = FALSE) plot_map(model) ts <- slim( model, burnin = 200000, samples = samples, random_seed = SEED, sequence_length = 200000, recombination_rate = 1e-8 )"},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"plotting-code-2","dir":"Articles","previous_headings":"Example 3 (Figure 4)","what":"Plotting code","title":"Examples from the slendr paper","text":"","code":"p_map <- plot_map(model) + theme(legend.position = \"bottom\") + guides(alpha = \"none\") p_ex3 <- plot_grid( p_code, plot_grid( plot_model(model, sizes = FALSE), p_map, labels = c(\"B\", \"C\"), nrow = 2, rel_heights = c(1, 1) ), ncol = 2, labels = c(\"A\", \"\"), rel_widths = c(1, 1.2) ) p_ex3"},{"path":[]},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"script-from-panel-a-3","dir":"Articles","previous_headings":"Example 4 (Figure 5)","what":"Script from panel A","title":"Examples from the slendr paper","text":"","code":"ts_small <- ts_simplify(ts, simplify_to = c(\"EUR_578\", \"YAM_75\", \"ANA_163\", \"EHG_208\")) # tskit uses zero-based indexing tree <- ts_phylo(ts_small, i = 15 / scaling) #> Starting checking the validity of tree... #> Found number of tips: n = 8 #> Found number of nodes: m = 7 #> Done. nodes <- ts_nodes(tree) edges <- ts_edges(tree) ancestors <- ts_ancestors(ts, \"EUR_578\")"},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"plotting-code-3","dir":"Articles","previous_headings":"Example 4 (Figure 5)","what":"Plotting code","title":"Examples from the slendr paper","text":"explained top page, random number generation current SLiM slightly different version 4.0.1 available time writing paper. figure looks little different well (different random generation implies different movement individuals, different individuals sampled). record, ’s original figure used paper also originally part vignette:","code":"library(ggtree) #> ggtree v3.10.0 For help: https://yulab-smu.top/treedata-book/ #> #> If you use the ggtree package suite in published research, please cite #> the appropriate paper(s): #> #> Guangchuang Yu, David Smith, Huachen Zhu, Yi Guan, Tommy Tsan-Yuk Lam. #> ggtree: an R package for visualization and annotation of phylogenetic #> trees with their covariates and other associated data. Methods in #> Ecology and Evolution. 2017, 8(1):28-36. doi:10.1111/2041-210X.12628 #> #> Guangchuang Yu. Data Integration, Manipulation and Visualization of #> Phylogenetic Trees (1st edition). Chapman and Hall/CRC. 2022, #> doi:10.1201/9781003279242 #> #> Guangchuang Yu. Using ggtree to visualize data on tree-like structures. #> Current Protocols in Bioinformatics. 2020, 69:e96. doi:10.1002/cpbi.96 #> #> #> Attaching package: 'ggtree' #> The following object is masked from 'package:tidyr': #> #> expand # prepare annotation table for ggtree linking R phylo node ID (not tskit integer # ID!) of each node with its population name df <- as_tibble(nodes) %>% select(node = phylo_id, pop) abs_comma <- function (x, ...) { format(abs(x) / 1000, ..., scientific = FALSE, trim = TRUE) } highlight_nodes <- as_tibble(nodes) %>% dplyr::filter(name == \"EUR_578\") %>% .$phylo_id p_tree <- ggtree(tree, aes(color = pop, fill = pop)) %<+% df + geom_tiplab(align = TRUE, geom = \"label\", offset = 2000, color = \"white\", fontface = \"bold\", size = 2.7) + geom_tiplab(align = TRUE, geom = NULL, linetype = \"dotted\", size = 0) + geom_point2(aes(subset = (node %in% highlight_nodes)), color = \"black\", size = 2.7) + geom_label2(aes(label = label, subset = !isTip), color = \"black\", size = 2.7) + theme_tree2() + theme(legend.position = \"none\") + xlab(\"time before present [thousand years ago]\") + scale_x_continuous(limits = c(-80000, 31000), labels = abs_comma, breaks = -c(100, 80, 60, 40, 20, 0) * 1000) p_tree <- revts(p_tree) # nodes$label <- ifelse(is.na(nodes$name), nodes$node_id, nodes$name) nodes$label <- sapply(1:nrow(nodes), function(i) { if (is.na(nodes[i, ]$name)) nodes[i, ]$node_id else { ind <- nodes[i, ]$name paste(nodes[!is.na(nodes$name) & nodes$name == ind, ]$node_id, collapse = \"&\") } }) p_map <- ggplot() + geom_sf(data = map) + geom_sf(data = edges, aes(color = parent_pop), size = 0.5) + geom_sf_label(data = nodes[!nodes$sampled, ], aes(label = node_id, fill = pop), size = 3) + geom_sf_label(data = nodes[nodes$sampled, ], aes(label = label, fill = pop), size = 3, fontface = \"bold\", color = \"white\") + coord_sf(xlim = c(3177066.1, 7188656.9), ylim = c(757021.7, 5202983.3), expand = 0) + guides(fill = guide_legend(\"\", override.aes = aes(label = \"\"))) + guides(color = \"none\") + scale_colour_discrete(drop = FALSE) + scale_fill_discrete(drop = FALSE) + theme_bw() + theme(legend.position = \"bottom\", axis.title.x = element_blank(), axis.title.y = element_blank()) chrom_names <- stats::setNames( c(\"EUR_578 (node 6)\", \"EUR_578 (node 7)\"), unique(ancestors$node_id) ) p_ancestors <- ggplot() + geom_sf(data = map) + geom_sf(data = ancestors, size = 0.5, alpha = 0.25) + geom_sf(data = sf::st_set_geometry(ancestors, \"parent_location\"), aes(shape = parent_pop, color = parent_pop)) + geom_sf(data = filter(ts_nodes(ts), name == \"EUR_578\"), size = 3) + coord_sf(expand = 0) + labs(x = \"longitude\", y = \"latitude\") + theme_bw() + facet_grid(. ~ node_id, labeller = labeller(node_id = chrom_names)) + theme(legend.position = \"none\") p_legend <- ggdraw() + draw_grob(grid::grobTree(get_legend(p_map))) p_ex4 <- plot_grid( p_code, plot_grid(p_tree + theme(legend.position = \"none\"), p_map + theme(legend.position = \"none\"), labels = c(\"B\", \"C\"), rel_widths = c(1, 0.9)), p_ancestors, p_legend, labels = c(\"A\", \"\", \"D\", \"\"), nrow = 4, rel_heights = c(0.5, 1, 1, 0.1) ) p_ex4"},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"run-time-of-each-code-example-from-the-paper","dir":"Articles","previous_headings":"","what":"Run time of each code example from the paper","title":"Examples from the slendr paper","text":"following times measured 16’’ MacBook Pro Apple M1 Pro chip (2021 model), 32 GB RAM, running macOS Ventura Version 13.1. table , ex1, ex2, ex3, ex4 correspond runtimes code shown one four example figures slendr paper.","code":""},{"path":"https://www.slendr.net/articles/vignette-10-tracts.html","id":"demographic-model","dir":"Articles","previous_headings":"","what":"Demographic model","title":"Extracting true ancestry tracts","text":"Let’s imagine following demographic model Neanderthal introgression ancestors non-Africans (represented “EUR” “PAP” populations, approximating European Papuan people living today), followed Denisovan introgression ancestors Papuans:","code":"anc_all <- population(\"ancestor_all\", time = 700e3, N = 10000, remove = 640e3) afr <- population(\"AFR\", parent = anc_all, time = 650e3, N = 10000) anc_arch <- population(\"ancestor_archaics\", parent = anc_all, time = 650e3, N = 10000, remove = 390e3) nea <- population(\"NEA\", parent = anc_arch, time = 400e3, N = 2000, remove = 30e3) den <- population(\"DEN\", parent = anc_arch, time = 400e3, N = 2000, remove = 30e3) nonafr <- population(\"nonAFR\", parent = afr, time = 100e3, N = 3000, remove = 39e3) eur <- population(\"EUR\", parent = nonafr, time = 45e3, N = 5000) pap <- population(\"PAP\", parent = nonafr, time = 45e3, N = 5000) gf <- list( gene_flow(from = nea, to = nonafr, rate = 0.03, start = 55000, end = 50000), gene_flow(from = den, to = pap, rate = 0.07, start = 35000, end = 30000) ) model <- compile_model( populations = list(anc_all, afr, anc_arch, nea, den, nonafr, eur, pap), gene_flow = gf, generation_time = 30, serialize = FALSE ) plot_model( model, sizes = FALSE, order = c(\"AFR\", \"EUR\", \"nonAFR\", \"PAP\", \"ancestor_all\", \"DEN\", \"ancestor_archaics\", \"NEA\") )"},{"path":"https://www.slendr.net/articles/vignette-10-tracts.html","id":"tree-sequence-simulation","dir":"Articles","previous_headings":"","what":"Tree sequence simulation","title":"Extracting true ancestry tracts","text":"Let’s now simulate 50Mb tree sequence model, recording 50 diploid individuals EUR PAP populations:","code":"samples <- schedule_sampling(model, times = 0, list(eur, 50), list(pap, 50)) ts <- msprime(model, sequence_length = 100e6, recombination_rate = 1e-8, samples = samples, random_seed = 42)"},{"path":"https://www.slendr.net/articles/vignette-10-tracts.html","id":"extracting-ancestry-tracts","dir":"Articles","previous_headings":"","what":"Extracting ancestry tracts","title":"Extracting true ancestry tracts","text":"order extract tracts Neanderthal Denisovan ancestry, can use slendr’s new function ts_tracts() serves simplified R-friendly interface Python method tspop.get_pop_ancestry(). important piece information used function -called “census time”, records time recording “ancestral population” identity node ancestral subsegment sample set. Please see excellent vignette tspop information inner workings algorithm. case, let’s extract ancestry tracts corresponding ancestral nodes present 55 thousand years ago – time corresponds moment start archaic introgression: table ancestry tracts looks like. expect, see column indicating name individual, left right coordinates tract individual, well population name source ancestry tract:","code":"nea_tracts <- ts_tracts(ts, census = 55000) #> #> PopAncestry summary #> Number of ancestral populations: 3 #> Number of sample chromosomes: 200 #> Number of ancestors: 44052 #> Total length of genomes: 20000000000.000000 #> Ancestral coverage: 20000000000.000000 den_tracts <- ts_tracts(ts, census = 35000) #> #> PopAncestry summary #> Number of ancestral populations: 3 #> Number of sample chromosomes: 200 #> Number of ancestors: 55373 #> Total length of genomes: 20000000000.000000 #> Ancestral coverage: 20000000000.000000 tracts <- bind_rows(nea_tracts, den_tracts) tracts #> # A tibble: 17,002 × 8 #> name node_id pop source_pop left right length source_pop_id #> #> 1 EUR_1 0 EUR NEA 781887 852668 70781 3 #> 2 EUR_1 0 EUR NEA 1451389 1463837 12448 3 #> 3 EUR_1 0 EUR NEA 1596995 1601441 4446 3 #> 4 EUR_1 0 EUR NEA 1629857 1689656 59799 3 #> 5 EUR_1 0 EUR NEA 3203711 3339565 135854 3 #> 6 EUR_1 0 EUR NEA 3850629 3947923 97294 3 #> 7 EUR_1 0 EUR NEA 6190700 6205627 14927 3 #> 8 EUR_1 0 EUR NEA 10394211 10426667 32456 3 #> 9 EUR_1 0 EUR NEA 13044685 13180258 135573 3 #> 10 EUR_1 0 EUR NEA 14858956 14912068 53112 3 #> # ℹ 16,992 more rows"},{"path":"https://www.slendr.net/articles/vignette-10-tracts.html","id":"summaries-of-ancestral-proportions","dir":"Articles","previous_headings":"","what":"Summaries of ancestral proportions","title":"Extracting true ancestry tracts","text":"summarise ancestry proportions target EUR PAP populations, see EUR population carries ~3% Neanderthal ancestry also true PAP population. However, also see Papuans carry 7% Denisovan ancestry. consistent model, also expectation empirical data. Let’s visualize proportions individual level:","code":"summary <- tracts %>% group_by(name, node_id, pop, source_pop) %>% summarise(prop = sum(length) / 100e6) #> `summarise()` has grouped output by 'name', 'node_id', 'pop'. You can override #> using the `.groups` argument. summary %>% group_by(pop, source_pop) %>% summarise(mean(prop)) %>% arrange(source_pop, pop) #> `summarise()` has grouped output by 'pop'. You can override using the `.groups` #> argument. #> # A tibble: 3 × 3 #> # Groups: pop [2] #> pop source_pop `mean(prop)` #> #> 1 EUR NEA 0.0303 #> 2 PAP NEA 0.0348 #> 3 PAP DEN 0.0739 summary %>% ggplot(aes(source_pop, prop, color = source_pop, fill = source_pop)) + geom_jitter() + coord_cartesian(ylim = c(0, 0.2)) + geom_hline(yintercept = c(0.03, 0.08), linetype = 2) + ylab(\"ancestry proportion\") + facet_wrap(~ pop) + ggtitle(\"Ancestry proportions in each individual\", \"(vertical lines represent 3% and 7% baseline expectations\")"},{"path":"https://www.slendr.net/articles/vignette-10-tracts.html","id":"chromosome-painting-of-ancestry-tracts","dir":"Articles","previous_headings":"","what":"“Chromosome painting” of ancestry tracts","title":"Extracting true ancestry tracts","text":"tracts object contains coordinates every single ancestry segment simulated individuals, can “paint” chromosome two archaic human ancestries: lining NEA & DEN ancestry tracts EUR PAP populations, can see common origin Neanderthal ancestry non-African populations manifests significant overlap NEA tracts populations.","code":"tracts %>% mutate(chrom = paste(name, \" (node\", node_id, \")\")) %>% ggplot(aes(x = left, xend = right, y = chrom, yend = chrom, color = source_pop)) + geom_segment(linewidth = 3) + theme_minimal() + labs(x = \"position [bp]\", y = \"haplotype\") + ggtitle(\"True ancestry tracts along each chromosome\") + theme(axis.text.y = element_blank(), panel.grid = element_blank()) + facet_grid(pop ~ ., scales = \"free_y\")"},{"path":"https://www.slendr.net/articles/vignette-10-tracts.html","id":"average-tract-lengths","dir":"Articles","previous_headings":"","what":"Average tract lengths:","title":"Extracting true ancestry tracts","text":"Let’s compute simple summaries tract lengths simulated data, compare theoretical expectations. Theoretical expectations (Racimo Slatkin 2015, Box 1) Neanderthal tracts: Denisovan tracts: can see, simulations far theoretical expectations, giving us confidence simulations (ancestry tract extraction algorithm) working expected.","code":"tracts %>% group_by(pop, source_pop) %>% summarise(mean(length)) #> `summarise()` has grouped output by 'pop'. You can override using the `.groups` #> argument. #> # A tibble: 3 × 3 #> # Groups: pop [2] #> pop source_pop `mean(length)` #> #> 1 EUR NEA 65765. #> 2 PAP NEA 69204. #> 3 PAP DEN 100317. m <- 0.03 t <- 52500 / 30 r <- 1e-8 mean_nea <- 1 / ((1 - m) * r * (t - 1)) mean_nea #> [1] 58943.84 m <- 0.07 t <- 37500 / 30 r <- 1e-8 mean_den <- 1 / ((1 - m) * r * (t - 1)) mean_den #> [1] 86090.38"},{"path":"https://www.slendr.net/articles/vignette-10-tracts.html","id":"distribution-of-ancestry-tract-lengths","dir":"Articles","previous_headings":"","what":"Distribution of ancestry tract lengths","title":"Extracting true ancestry tracts","text":"Finally, let’s plot distributions lengths ancestry tracts. case archaic human introgression well studied ’s perhaps exciting look figures. said, less well studied species, might interesting use kinds simulations inference introgression times proportions via Approximate Bayesian Computation another method:","code":"expectation_df <- data.frame( pop = c(\"EUR\", \"PAP\", \"PAP\"), source_pop = c(\"NEA\", \"NEA\", \"DEN\"), length = c(mean_nea, mean_nea, mean_den) ) p_densities <- tracts %>% ggplot(aes(length, color = source_pop)) + geom_density() + geom_vline(data = expectation_df, aes(xintercept = length, color = source_pop), linetype = 2) + facet_wrap(~ pop) + ggtitle(\"Distribution of tract lengths per different ancestries\") cowplot::plot_grid(p_densities, p_densities + scale_x_log10(), nrow = 2)"},{"path":"https://www.slendr.net/articles/vignette-10-tracts.html","id":"pure-msprime-tree-sequence","dir":"Articles","previous_headings":"","what":"Pure msprime tree sequence","title":"Extracting true ancestry tracts","text":"Finally, sanity check, let’s use pure msprime simulation example official tspop documentation test ts_tracts() behaves expected even standard msprime tree-sequence object. First, let’s run simulation code exactly : Let’s save msprime tree sequence disk can load R (.e., approximating might want want use ts_tracts() without running slendr simulation first): Now let’s move R , load tree sequence slendr extract ancestry tracts using ts_tracts(): setting squashed = FALSE, get full, un-squashed ancestry segments, appropriate ancestral node ID: comparing two tables pandas data frames tspop documentation, can see obtained results.","code":"import msprime pop_size = 500 sequence_length = 1e7 seed = 98765 rho = 3e-8 # Make the Demography object. demography = msprime.Demography() demography.add_population(name=\"RED\", initial_size=pop_size) #> Population(initial_size=500, growth_rate=0, name='RED', description='', extra_metadata={}, default_sampling_time=None, initially_active=None, id=0) demography.add_population(name=\"BLUE\", initial_size=pop_size) #> Population(initial_size=500, growth_rate=0, name='BLUE', description='', extra_metadata={}, default_sampling_time=None, initially_active=None, id=1) demography.add_population(name=\"ADMIX\", initial_size=pop_size) #> Population(initial_size=500, growth_rate=0, name='ADMIX', description='', extra_metadata={}, default_sampling_time=None, initially_active=None, id=2) demography.add_population(name=\"ANC\", initial_size=pop_size) #> Population(initial_size=500, growth_rate=0, name='ANC', description='', extra_metadata={}, default_sampling_time=None, initially_active=None, id=3) demography.add_admixture( time=100, derived=\"ADMIX\", ancestral=[\"RED\", \"BLUE\"], proportions=[0.5, 0.5] ) #> Admixture(time=100, derived='ADMIX', ancestral=['RED', 'BLUE'], proportions=[0.5, 0.5]) demography.add_census(time=100.01) # Census is here! #> CensusEvent(time=100.01) demography.add_population_split( time=1000, derived=[\"RED\", \"BLUE\"], ancestral=\"ANC\" ) #> PopulationSplit(time=1000, derived=['RED', 'BLUE'], ancestral='ANC') # Simulate. ts = msprime.sim_ancestry( samples={\"RED\": 0, \"BLUE\": 0, \"ADMIX\" : 2}, demography=demography, random_seed=seed, sequence_length=sequence_length, recombination_rate=rho ) import tempfile path = tempfile.NamedTemporaryFile(suffix=\".trees\").name ts.dump(path) sim_ts <- ts_load(reticulate::py$path) squashed_tracts <- ts_tracts(sim_ts, census = 100.01, squashed = TRUE) #> #> PopAncestry summary #> Number of ancestral populations: 2 #> Number of sample chromosomes: 4 #> Number of ancestors: 118 #> Total length of genomes: 40000000.000000 #> Ancestral coverage: 40000000.000000 head(squashed_tracts) #> # A tibble: 6 × 4 #> sample left right population #> #> 1 0 0 419848 0 #> 2 0 419848 483009 1 #> 3 0 483009 1475765 0 #> 4 0 1475765 2427904 1 #> 5 0 2427904 3635390 0 #> 6 0 3635390 4606954 1 tail(squashed_tracts) #> # A tibble: 6 × 4 #> sample left right population #> #> 1 3 7134130 7362300 1 #> 2 3 7362300 7369409 0 #> 3 3 7369409 7596783 1 #> 4 3 7596783 8289015 0 #> 5 3 8289015 8918727 1 #> 6 3 8918727 10000000 0 full_tracts <- ts_tracts(sim_ts, census = 100.01, squashed = FALSE) #> #> PopAncestry summary #> Number of ancestral populations: 2 #> Number of sample chromosomes: 4 #> Number of ancestors: 118 #> Total length of genomes: 40000000.000000 #> Ancestral coverage: 40000000.000000 head(full_tracts) #> # A tibble: 6 × 5 #> sample left right ancestor population #> #> 1 0 0 33027 74 0 #> 2 0 33027 155453 33 0 #> 3 0 155453 290542 46 0 #> 4 0 290542 419848 18 0 #> 5 0 419848 483009 83 1 #> 6 0 483009 1475765 28 0 tail(full_tracts) #> # A tibble: 6 × 5 #> sample left right ancestor population #> #> 1 3 8477625 8672850 94 1 #> 2 3 8672850 8849756 95 1 #> 3 3 8849756 8918727 131 1 #> 4 3 8918727 9165035 44 0 #> 5 3 9165035 9176562 47 0 #> 6 3 9176562 10000000 58 0"},{"path":"https://www.slendr.net/authors.html","id":null,"dir":"","previous_headings":"","what":"Authors","title":"Authors and Citation","text":"Martin Petr. Author, maintainer.","code":""},{"path":"https://www.slendr.net/authors.html","id":"citation","dir":"","previous_headings":"","what":"Citation","title":"Authors and Citation","text":"Petr M (2024). slendr: Simulation Framework Spatiotemporal Population Genetics. R package version 0.9.0, https://github.com/bodkan/slendr.","code":"@Manual{, title = {slendr: A Simulation Framework for Spatiotemporal Population Genetics}, author = {Martin Petr}, year = {2024}, note = {R package version 0.9.0}, url = {https://github.com/bodkan/slendr}, }"},{"path":[]},{"path":"https://www.slendr.net/index.html","id":"overview-","dir":"","previous_headings":"","what":"Overview","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"slendr R package toolbox defining population genetic models simulating genomic data entirely R. originally conceived framework simulating spatially-explicit genomic data real geographic landscapes grown much . page briefly summarizes slendr’s important features. much detailed description slendr architecture extensive set practical code examples can found paper PCI journal website.","code":""},{"path":"https://www.slendr.net/index.html","id":"citing-slendr","dir":"","previous_headings":"","what":"Citing slendr","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"slendr paper now published Peer Community Journal! use slendr work, please cite : Petr, Martin; Haller, Benjamin C.; Ralph, Peter L.; Racimo, Fernando. slendr: framework spatio-temporal population genomic simulations geographic landscapes. Peer Community Journal, Volume 3 (2023), article . e121. doi : 10.24072/pcjournal.354. Citations help justify development fixing bugs! Thank ! ❤️","code":""},{"path":"https://www.slendr.net/index.html","id":"main-features","dir":"","previous_headings":"","what":"Main features","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"brief summary slendr’s important features. R package allows : Program demographic models, including population splits, population size changes, gene-flow events using extremely simple declarative language entirely R (see vignette example model-definition interface). Even complex models can written little code require bare minimum R programming knowledge (thing user needs know call R function R data frame look like). Execute slendr models using efficient, tailor-made SLiM msprime simulation scripts bundled R package. simulation engines save outputs form efficient tree-sequence data structure. SLiM msprime programming needed! Load, process, analyse tree-sequence outputs via slendr’s built-R interface tree-sequence library tskit. can compute many population genetic statistics R immediately simulation finishes directly output tree sequences, without convert files formats (VCF, EIGENSTRAT) analysis different software. Encode complex models population movements landscape (see brief example model , extended explanation tutorial). knowledge cartographic geospatial analysis concepts needed. Simulate dynamic spatial demographic models using SLiM’s continuous-space simulation capabilities directly R (, SLiM programming required). outputs simulations saved tree sequences can analysed using standard R geospatial data analysis libraries. slendr performs conversion tree sequence tables appropriate spatial R data type automatically. Specify within-population individual dispersal dynamics R interface leveraging SLiM’s individual interaction parameters implemented SLiM back-end script. Schedule sampling events specify many individuals’ genomes, populations, times (optionally, locations) recorded simulation engine (SLiM msprime) output tree-sequence files. Utilizing flexibility R wealth libraries statistics, geospatial analysis graphics, combining power population genetic simulation frameworks SLiM msprime, slendr R package makes possible write entire simulation analytic pipelines without need leave R environment.","code":""},{"path":"https://www.slendr.net/index.html","id":"testing-the-r-package-in-an-online-rstudio-session","dir":"","previous_headings":"","what":"Testing the R package in an online RStudio session","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"can open RStudio session test examples vignettes directly web browser clicking button (installation needed!): case RStudio instance appears starting slowly, please patient (Binder freely available service limited computational resources provided community). Binder crashes, try reloading web page, restart cloud session. get browser-based RStudio session, can navigate vignettes/ directory test examples !","code":""},{"path":"https://www.slendr.net/index.html","id":"installation","dir":"","previous_headings":"","what":"Installation","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"slendr now available CRAN means can install simply entering install.packages(\"slendr\") R console. like test latest features software (perhaps need bug fixes), can install devtools::install_github(\"bodkan/slendr\") (note requires R package devtools). ⚠️⚠️⚠️ Note: default slendr installation longer hard dependency geospatial R packages sf, stars, rnaturalearth. indend use slendr spatial genomic simulations data analysis, run install.packages(c(\"sf\", \"stars\", \"rnaturalearth\")) first. made change ease installation burden researchers might need slendr’s support traditional, non-spatial simulations (represent majority use-cases population genetics general). geospatial R packages imply non-negligible amount software dependencies , proven unnecessary hurdle many users might need (least first). ⚠️⚠️⚠️ software active development! like stay updated: Click “Watch” button project’s GitHub website. Follow social media posting progress updates (can find links homepage). time time, take look changelog post updates new features, breaking changes, etc.","code":""},{"path":"https://www.slendr.net/index.html","id":"example","dir":"","previous_headings":"","what":"Example","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"brief demonstration kind spatial model slendr originally designed simulate data . Please note although spatially-explicit population genetic model, slendr extensive support traditional, non-spatial simulations well. Furthermore, example shows specify simulate model R. doesn’t show analyse tree-sequence outputs compute population genetic statistics (important feature demonstrated tutorial).","code":""},{"path":"https://www.slendr.net/index.html","id":"id_1-setup-the-spatial-context","dir":"","previous_headings":"Example","what":"1. Setup the spatial context","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"Imagine wanted simulate spatio-temporal genomic data toy model history modern humans West Eurasia Africa migration. First, define spatial context simulation. represent “world” occupied populations model. can visualize defined world map using function plot_map provided package. Although example use real Earth landscape, map can completely abstract (either blank user-defined landscape features continents, islands, corridors barriers).","code":"library(slendr) # this sets up internal Python environment and needs to be ran only once! # (do not put this in your R scripts, run this command in the R console # after you (re-)install slendr) setup_env() # activate the internal Python environment needed for simulation and # tree-sequence processing init_env() map <- world( xrange = c(-13, 70), # min-max longitude yrange = c(18, 65), # min-max latitude crs = \"EPSG:3035\" # coordinate reference system (CRS) for West Eurasia ) plot_map(map)"},{"path":"https://www.slendr.net/index.html","id":"id_2-define-broader-geographic-regions","dir":"","previous_headings":"Example","what":"2. Define broader geographic regions","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"order make definitions population ranges () easier, can define smaller regions map using function region. Note coordinates slendr specified geographic coordinate system (.e., degrees longitude latitude), internally represented projected CRS (case, EPSG 3035 specified ). makes easier us define spatial features simply reading coordinates regular map internal projected CRS makes simulations accurate (distances shapes distorted can use CRS tailored region world working ). projected CRS takes care projection part world ’re interested three-dimensional Earth surface two-dimensional map. , can use generic plot_map function visualize objects, making sure specified correctly:","code":"africa <- region( \"Africa\", map, polygon = list(c(-18, 20), c(38, 20), c(30, 33), c(20, 33), c(10, 38), c(-6, 35)) ) europe <- region( \"Europe\", map, polygon = list( c(-8, 35), c(-5, 36), c(10, 38), c(20, 35), c(25, 35), c(33, 45), c(20, 58), c(-5, 60), c(-15, 50) ) ) anatolia <- region( \"Anatolia\", map, polygon = list(c(28, 35), c(40, 35), c(42, 40), c(30, 43), c(27, 40), c(25, 38)) ) plot_map(africa, europe, anatolia)"},{"path":"https://www.slendr.net/index.html","id":"id_3-define-demographic-history-and-population-boundaries","dir":"","previous_headings":"Example","what":"3. Define demographic history and population boundaries","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"important function slendr package population(), used define names, split times, sizes spatial ranges populations. , specify times years present, distances kilometers. makes sense models, times can also given forward direction. also note functions move() expand_range() designed take slendr population object schedule spatial dynamics appropriate times model simulation (happen later step). Note order make example executable reasonable time extremely old laptop, decreased sizes populations unrealistic levels. speed SLiM simulation later step. can use function plot_map get “compressed” overview spatio-temporal range dynamics encoded model far (prior simulation ).","code":"afr <- population( # African ancestral population \"AFR\", time = 52000, N = 3000, map = map, polygon = africa ) ooa <- population( # population of the first migrants out of Africa \"OOA\", parent = afr, time = 51000, N = 500, remove = 25000, center = c(33, 30), radius = 400e3 ) %>% move( trajectory = list(c(40, 30), c(50, 30), c(60, 40)), start = 50000, end = 40000, snapshots = 20 ) ehg <- population( # Eastern hunter-gatherers \"EHG\", parent = ooa, time = 28000, N = 1000, remove = 6000, polygon = list( c(26, 55), c(38, 53), c(48, 53), c(60, 53), c(60, 60), c(48, 63), c(38, 63), c(26, 60)) ) eur <- population( # European population name = \"EUR\", parent = ehg, time = 25000, N = 2000, polygon = europe ) ana <- population( # Anatolian farmers name = \"ANA\", time = 28000, N = 3000, parent = ooa, remove = 4000, center = c(34, 38), radius = 500e3, polygon = anatolia ) %>% expand_range( # expand the range by 2.500 km by = 2500e3, start = 10000, end = 7000, polygon = join(europe, anatolia), snapshots = 20 ) yam <- population( # Yamnaya steppe population name = \"YAM\", time = 7000, N = 500, parent = ehg, remove = 2500, polygon = list(c(26, 50), c(38, 49), c(48, 50), c(48, 56), c(38, 59), c(26, 56)) ) %>% move(trajectory = list(c(15, 50)), start = 5000, end = 3000, snapshots = 10) plot_map(afr, ooa, ehg, eur, ana, yam)"},{"path":"https://www.slendr.net/index.html","id":"id_4-define-gene-flow-events","dir":"","previous_headings":"Example","what":"4. Define gene-flow events","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"default, populations slendr mix even overlapping. order schedule gene-flow event two populations, can use function gene_flow. want specify multiple events , can collect events simple R list:","code":"gf <- list( gene_flow(from = ana, to = yam, rate = 0.5, start = 6500, end = 6400, overlap = FALSE), gene_flow(from = ana, to = eur, rate = 0.5, start = 8000, end = 6000), gene_flow(from = yam, to = eur, rate = 0.75, start = 4000, end = 3000) )"},{"path":"https://www.slendr.net/index.html","id":"id_5-compile-the-model-to-a-set-of-configuration-files","dir":"","previous_headings":"Example","what":"5. Compile the model to a set of configuration files","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"run simulation, compile individual model components (population objects gene-flow events) single R object, specifying additional model parameters. Additionally, performs internal consistency checks, making sure model parameters (split times, gene flow times, etc.) make sense (potentially quite computationally costly) simulation even run. Compiled model kept R object can passed different functions. example, simulate data slim() engine (also run simulation coalescent engine via msprime() function).","code":"model <- compile_model( populations = list(afr, ooa, ehg, eur, ana, yam), # populations defined above gene_flow = gf, generation_time = 30, resolution = 10e3, # resolution in meters per pixel competition = 130e3, mating = 100e3, # spatial interaction parameters dispersal = 70e3, # how far can offspring end up from their parents )"},{"path":"https://www.slendr.net/index.html","id":"id_6-visualize-the-model","dir":"","previous_headings":"Example","what":"6. Visualize the model","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"package provides R shiny-based browser app explore_model() checking model dynamics interactively visually. complex models, much better static spatial plots one showed step 2 : function two modes: Plotting (“playing”) spatial map dynamics: Displaying demographic history graph (splits gene-flow events) embedded specified model:","code":"explore_model(model)"},{"path":"https://www.slendr.net/index.html","id":"id_7-run-the-model-in-slim","dir":"","previous_headings":"Example","what":"7. Run the model in SLiM","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"Finally, can execute compiled model SLiM. run simulation batch mode, also run SLiMgui setting method = \"gui\". allow us inspect spatial simulation happens real time. slim function generates complete SLiM script tailored run spatial model defined . saves , user, tremendous amount time, don’t write new SLiM code every time design new demographic model. output simulation run slendr model always tree sequence, loaded object ts_slim. specified , slendr’s SLiM backend simulate 10 Mb sequence individual, produce tree sequence output simulation run can analysed many built-population genetic functions. default, individuals living end simulation recorded samples tree sequence. specific set samples (ancient modern) needed, can defined accordingly using dedicated function. Note although defined spatial model, just easily simulated standard, non-spatial data running model slendr’s msprime() back end without need make changes: quick overview SLiM simulation run summarised GIF animation. , please note simulation extremely simplified. simulated small number individuals population, also didn’t specify dispersal dynamics populations look clumped. point, either compute population genetic statistics interest perhaps analyse spatial features genealogies simulated model.","code":"ts_slim <- slim(model, sequence_length = 10e6, recombination_rate = 1e-8, method = \"batch\", random_seed = 314159) ts_msprime <- msprime(model, sequence_length = 10e6, recombination_rate = 1e-8) animate_model(model = model, file = locations_file, steps = 50, width = 500, height = 300)"},{"path":"https://www.slendr.net/index.html","id":"further-information","dir":"","previous_headings":"","what":"Further information","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"example provides brief incomplete overview full functionality slendr package. much slendr demonstrated . instance: can tweak parameters influencing dispersal dynamics (“clumpy” populations , far can offspring migrate parents, etc.) define change time. instance, can see animation , African population forms single “blob” really isn’t spread across entire population range. Tweaking dispersal parameters show vignette helps avoid . can use slendr program non-spatial models, means conceivable traditional, random-mating demographic model can simulated lines R code. can learn vignette (detail vignette). SLiM simulations can often quite slow compared coalescent counterparts, also provide functionality allowing simulate slendr models (without change!) using built-msprime back end script. See vignette tutorial works. can build complex spatial models still abstract (assuming real geographic location), including traditional simulations demes lattice structure. complete example shown vignette. slendr & SLiM save data tree-sequence file format, thanks R package reticulate interfacing Python code, full power tskit pyslim manipulating tree-sequence data right fingertips, within convenient environment R. extended example can found vignette. spatially explicit population models, slendr package automatically converts simulated output data format makes possible analyse many available R packages geospatial data analysis. brief description functionality can found vignette. can find complete reproducible code behind examples paper dedicated R vignette .","code":""},{"path":"https://www.slendr.net/reference/animate_model.html","id":null,"dir":"Reference","previous_headings":"","what":"Animate the simulated population dynamics — animate_model","title":"Animate the simulated population dynamics — animate_model","text":"Animate simulated population dynamics","code":""},{"path":"https://www.slendr.net/reference/animate_model.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Animate the simulated population dynamics — animate_model","text":"","code":"animate_model(model, file, steps, gif = NULL, width = 800, height = 560)"},{"path":"https://www.slendr.net/reference/animate_model.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Animate the simulated population dynamics — animate_model","text":"model Compiled slendr_model model object file Path table saved individual locations steps many frames animation ? gif Path output GIF file (animation object returned default) width, height Dimensions animation pixels","code":""},{"path":"https://www.slendr.net/reference/animate_model.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Animate the simulated population dynamics — animate_model","text":"gif = NULL, return gganimate animation object. Otherwise GIF file saved value returned.","code":""},{"path":"https://www.slendr.net/reference/area.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate the area covered by the given slendr object — area","title":"Calculate the area covered by the given slendr object — area","text":"Calculate area covered given slendr object","code":""},{"path":"https://www.slendr.net/reference/area.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate the area covered by the given slendr object — area","text":"","code":"area(x)"},{"path":"https://www.slendr.net/reference/area.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate the area covered by the given slendr object — area","text":"x Object class slendr","code":""},{"path":"https://www.slendr.net/reference/area.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate the area covered by the given slendr object — area","text":"Area covered input object. slendr_pop given, table population range area time point returned. slendr_region slendr_world object specified, total area covered object's spatial boundary returned.","code":""},{"path":"https://www.slendr.net/reference/area.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate the area covered by the given slendr object — area","text":"","code":"region_a <- region(\"A\", center = c(20, 50), radius = 20) region_b <- region(\"B\", polygon = list(c(50, 40), c(70, 40), c(70, 60), c(50, 60))) plot_map(region_a, region_b) # note that area won't be *exactly* equal to pi*r^2: # https://stackoverflow.com/a/65280376 area(region_a) #> [1] 1256.063 area(region_b) #> [1] 400"},{"path":"https://www.slendr.net/reference/as.phylo.slendr_phylo.html","id":null,"dir":"Reference","previous_headings":"","what":"Convert an annotated slendr_phylo object to a phylo object — as.phylo.slendr_phylo","title":"Convert an annotated slendr_phylo object to a phylo object — as.phylo.slendr_phylo","text":"function servers workaround around ggtree error: Error UseMethod(\".phylo\") : applicable method '.phylo' applied object class \"c('phylo', 'slendr_phylo')\"","code":""},{"path":"https://www.slendr.net/reference/as.phylo.slendr_phylo.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Convert an annotated slendr_phylo object to a phylo object — as.phylo.slendr_phylo","text":"","code":"# S3 method for slendr_phylo as.phylo(x, ...)"},{"path":"https://www.slendr.net/reference/as.phylo.slendr_phylo.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Convert an annotated slendr_phylo object to a phylo object — as.phylo.slendr_phylo","text":"x Tree object class slendr_phylo ... Additional (unused) arguments .phylo S3 method","code":""},{"path":"https://www.slendr.net/reference/as.phylo.slendr_phylo.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Convert an annotated slendr_phylo object to a phylo object — as.phylo.slendr_phylo","text":"Standard phylogenetic tree object implemented R package ape","code":""},{"path":"https://www.slendr.net/reference/check_dependencies.html","id":null,"dir":"Reference","previous_headings":"","what":"Check that the required dependencies are available for slendr to work — check_dependencies","title":"Check that the required dependencies are available for slendr to work — check_dependencies","text":"Check required dependencies available slendr work","code":""},{"path":"https://www.slendr.net/reference/check_dependencies.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Check that the required dependencies are available for slendr to work — check_dependencies","text":"","code":"check_dependencies(python = FALSE, slim = FALSE, quit = FALSE)"},{"path":"https://www.slendr.net/reference/check_dependencies.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Check that the required dependencies are available for slendr to work — check_dependencies","text":"python slendr Python environment required? slim SLiM required? quit R interpreter quit required slendr dependencies missing? option (turned default, set FALSE) used mainly avoiding running slendr man page examples machines lack dependencies. set TRUE, logical value returned.","code":""},{"path":"https://www.slendr.net/reference/check_dependencies.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Check that the required dependencies are available for slendr to work — check_dependencies","text":"quit = TRUE, values returned, quit = FALSE, scalar logical value returned indicating whether dependencies present.","code":""},{"path":"https://www.slendr.net/reference/check_env.html","id":null,"dir":"Reference","previous_headings":"","what":"Check that the active Python environment is setup for slendr — check_env","title":"Check that the active Python environment is setup for slendr — check_env","text":"function inspects Python environment activated reticulate package prints versions slendr Python dependencies console.","code":""},{"path":"https://www.slendr.net/reference/check_env.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Check that the active Python environment is setup for slendr — check_env","text":"","code":"check_env(verbose = TRUE)"},{"path":"https://www.slendr.net/reference/check_env.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Check that the active Python environment is setup for slendr — check_env","text":"verbose log message printed? FALSE, logical value returned (invisibly).","code":""},{"path":"https://www.slendr.net/reference/check_env.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Check that the active Python environment is setup for slendr — check_env","text":"Either TRUE (slendr Python environment present) FALSE (slendr Python environment present).","code":""},{"path":"https://www.slendr.net/reference/check_env.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Check that the active Python environment is setup for slendr — check_env","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. check_env() #> Summary of the currently active Python environment: #> #> Python binary: /Users/mp/Library/r-miniconda-arm64/envs/Python-3.12_msprime-1.3.0_tskit-0.5.6_pyslim-1.0.4_tspop-0.0.2/bin/python #> Python version: 3.12.1 | packaged by conda-forge | (main, Dec 23 2023, 08:01:35) [Clang 16.0.6 ] #> #> slendr requirements: #> - tskit: version 0.5.6 ✓ #> - msprime: version 1.3.0 ✓ #> - pyslim: version 1.0.4 ✓ #> - tspop: present ✓"},{"path":"https://www.slendr.net/reference/clear_env.html","id":null,"dir":"Reference","previous_headings":"","what":"Remove the automatically created slendr Python environment — clear_env","title":"Remove the automatically created slendr Python environment — clear_env","text":"Remove automatically created slendr Python environment","code":""},{"path":"https://www.slendr.net/reference/clear_env.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Remove the automatically created slendr Python environment — clear_env","text":"","code":"clear_env(force = FALSE)"},{"path":"https://www.slendr.net/reference/clear_env.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Remove the automatically created slendr Python environment — clear_env","text":"force Ask deleting environment?","code":""},{"path":"https://www.slendr.net/reference/clear_env.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Remove the automatically created slendr Python environment — clear_env","text":"return value, called side effects","code":""},{"path":"https://www.slendr.net/reference/compile_model.html","id":null,"dir":"Reference","previous_headings":"","what":"Compile a slendr demographic model — compile_model","title":"Compile a slendr demographic model — compile_model","text":"First, compiles vectorized population spatial maps series binary raster PNG files, format SLiM understands uses define population boundaries. extracts demographic model defined user (.e. population divergences gene flow events) series tables later used built-SLiM script program timing simulation events.","code":""},{"path":"https://www.slendr.net/reference/compile_model.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Compile a slendr demographic model — compile_model","text":"","code":"compile_model( populations, generation_time, path = NULL, resolution = NULL, competition = NULL, mating = NULL, dispersal = NULL, gene_flow = list(), overwrite = FALSE, force = FALSE, simulation_length = NULL, direction = NULL, serialize = TRUE, slim_script = NULL, description = \"\", sim_length = NULL )"},{"path":"https://www.slendr.net/reference/compile_model.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Compile a slendr demographic model — compile_model","text":"populations Object(s) slendr_pop class (multiple objects need specified list) generation_time Generation time (model time units) path Output directory model configuration files loaded backend SLiM script. NULL, model configuration files saved temporary directory. resolution many distance units per pixel? competition, mating Maximum spatial competition mating choice distance dispersal Standard deviation normal distribution parent-offspring distance gene_flow Gene flow events generated gene_flow function (either list data.frame objects format defined gene_flow function, single data.frame) overwrite Completely delete specified directory, case already exists, create new one? force Force deletion model directory already present? Useful non-interactive uses. interactive mode, user asked confirm deletion manually. simulation_length Total length simulation (required forward time models, optional models specified backward time units default run \"present time\") direction Intended direction time. normal circumstances parameter inferred model need set manually. serialize model files serialized disk? , R model object returned files created. speeds simulation msprime prevents using SLiM back end. slim_script Path SLiM script used executing model (default, bundled backend script used). NULL, SLiM script bundled slendr used. description Optional short description model sim_length Deprecated. Use simulation_length instead.","code":""},{"path":"https://www.slendr.net/reference/compile_model.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Compile a slendr demographic model — compile_model","text":"Compiled slendr_model model object encapsulates information specified model (populations involved, much gene flow occur, spatial resolution map, spatial dispersal mating parameters used SLiM simulation, applicable)","code":""},{"path":"https://www.slendr.net/reference/compile_model.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Compile a slendr demographic model — compile_model","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/distance.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate the distance between a pair of spatial boundaries — distance","title":"Calculate the distance between a pair of spatial boundaries — distance","text":"Calculate distance pair spatial boundaries","code":""},{"path":"https://www.slendr.net/reference/distance.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate the distance between a pair of spatial boundaries — distance","text":"","code":"distance(x, y, measure, time = NULL)"},{"path":"https://www.slendr.net/reference/distance.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate the distance between a pair of spatial boundaries — distance","text":"x, y Objects class slendr measure measure distance? can either 'border' (distance borders x y) 'center' (distance centroids). time Time closest spatial maps x y represent slendr_pop population boundaries (ignored general slendr_region objects)","code":""},{"path":"https://www.slendr.net/reference/distance.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate the distance between a pair of spatial boundaries — distance","text":"coordinate reference system specified, distance projected units (.e. meters) returned. Otherwise function returns normal Euclidean distance.","code":""},{"path":"https://www.slendr.net/reference/distance.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate the distance between a pair of spatial boundaries — distance","text":"","code":"# create two regions on a blank abstract landscape region_a <- region(\"A\", center = c(20, 50), radius = 20) region_b <- region(\"B\", center = c(80, 50), radius = 20) plot_map(region_a, region_b) # compute the distance between the centers of both population ranges distance(region_a, region_b, measure = \"center\") #> [1] 60 # compute the distance between the borders of both population ranges distance(region_a, region_b, measure = \"border\") #> [1] 20"},{"path":"https://www.slendr.net/reference/expand_range.html","id":null,"dir":"Reference","previous_headings":"","what":"Expand the population range — expand_range","title":"Expand the population range — expand_range","text":"Expands spatial population range specified distance given time-window","code":""},{"path":"https://www.slendr.net/reference/expand_range.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Expand the population range — expand_range","text":"","code":"expand_range( pop, by, end, start, overlap = 0.8, snapshots = NULL, polygon = NULL, lock = FALSE, verbose = TRUE )"},{"path":"https://www.slendr.net/reference/expand_range.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Expand the population range — expand_range","text":"pop Object class slendr_pop many units distance expand ? start, end expansion start/end? overlap Minimum overlap subsequent spatial boundaries snapshots number intermediate snapshots (overrides overlap parameter) polygon Geographic region restrict expansion lock Maintain density individuals. FALSE (default), number individuals population change. TRUE, number individuals simulated changed (increased decreased) appropriately, match new population range area. verbose Report progress generating intermediate spatial boundaries?","code":""},{"path":"https://www.slendr.net/reference/expand_range.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Expand the population range — expand_range","text":"Object class slendr_pop, contains population parameters name, time appearance simulation, parent population (), spatial parameters map spatial boundary.","code":""},{"path":"https://www.slendr.net/reference/expand_range.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Expand the population range — expand_range","text":"Note slendr models accomodate SLiM msprime back ends, population sizes times events rounded nearest integer value.","code":""},{"path":"https://www.slendr.net/reference/expand_range.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Expand the population range — expand_range","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/explore_model.html","id":null,"dir":"Reference","previous_headings":"","what":"Open an interactive browser of the spatial model — explore_model","title":"Open an interactive browser of the spatial model — explore_model","text":"Open interactive browser spatial model","code":""},{"path":"https://www.slendr.net/reference/explore_model.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Open an interactive browser of the spatial model — explore_model","text":"","code":"explore_model(model)"},{"path":"https://www.slendr.net/reference/explore_model.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Open an interactive browser of the spatial model — explore_model","text":"model Compiled slendr_model model object","code":""},{"path":"https://www.slendr.net/reference/explore_model.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Open an interactive browser of the spatial model — explore_model","text":"return value, called order start interactive browser-based interface explore dynamics slendr model","code":""},{"path":"https://www.slendr.net/reference/gene_flow.html","id":null,"dir":"Reference","previous_headings":"","what":"Define a gene-flow event between two populations — gene_flow","title":"Define a gene-flow event between two populations — gene_flow","text":"Define gene-flow event two populations","code":""},{"path":"https://www.slendr.net/reference/gene_flow.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Define a gene-flow event between two populations — gene_flow","text":"","code":"gene_flow(from, to, rate, start, end, overlap = TRUE)"},{"path":"https://www.slendr.net/reference/gene_flow.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Define a gene-flow event between two populations — gene_flow","text":", Objects class slendr_pop rate Scalar value range (0, 1] specifying proportion migration given time period start, end Start end gene-flow event overlap Require spatial overlap admixing populations? (default TRUE)","code":""},{"path":"https://www.slendr.net/reference/gene_flow.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Define a gene-flow event between two populations — gene_flow","text":"Object class data.frame containing parameters specified gene-flow event.","code":""},{"path":"https://www.slendr.net/reference/gene_flow.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Define a gene-flow event between two populations — gene_flow","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/init_env.html","id":null,"dir":"Reference","previous_headings":"","what":"Activate slendr's own dedicated Python environment — init_env","title":"Activate slendr's own dedicated Python environment — init_env","text":"function attempts activate dedicated slendr Miniconda Python environment previously set via setup_env.","code":""},{"path":"https://www.slendr.net/reference/init_env.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Activate slendr's own dedicated Python environment — init_env","text":"","code":"init_env(quiet = FALSE)"},{"path":"https://www.slendr.net/reference/init_env.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Activate slendr's own dedicated Python environment — init_env","text":"quiet informative messages printed console? Default FALSE.","code":""},{"path":"https://www.slendr.net/reference/init_env.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Activate slendr's own dedicated Python environment — init_env","text":"return value, called side effects","code":""},{"path":"https://www.slendr.net/reference/join.html","id":null,"dir":"Reference","previous_headings":"","what":"Merge two spatial slendr objects into one — join","title":"Merge two spatial slendr objects into one — join","text":"Merge two spatial slendr objects one","code":""},{"path":"https://www.slendr.net/reference/join.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Merge two spatial slendr objects into one — join","text":"","code":"join(x, y, name = NULL)"},{"path":"https://www.slendr.net/reference/join.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Merge two spatial slendr objects into one — join","text":"x Object class slendr y Object class slendr name Optional name resulting geographic region. missing, name constructed function arguments.","code":""},{"path":"https://www.slendr.net/reference/join.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Merge two spatial slendr objects into one — join","text":"Object class slendr_region encodes standard spatial object class sf several additional attributes (importantly corresponding slendr_map object, applicable).","code":""},{"path":"https://www.slendr.net/reference/join.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Merge two spatial slendr objects into one — join","text":"","code":"# create a blank abstract world 1000x1000 distance units in size blank_map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # it is possible to construct custom landscapes (islands, corridors, etc.) island1 <- region(\"island1\", polygon = list(c(10, 30), c(50, 30), c(40, 50), c(0, 40))) island2 <- region(\"island2\", polygon = list(c(60, 60), c(80, 40), c(100, 60), c(80, 80))) island3 <- region(\"island3\", center = c(20, 80), radius = 10) archipelago <- island1 %>% join(island2) %>% join(island3) custom_map <- world(xrange = c(1, 100), c(1, 100), landscape = archipelago) # real Earth landscapes can be defined using freely-available Natural Earth # project data and with the possibility to specify an appropriate Coordinate # Reference System, such as this example of a map of Europe real_map <- world(xrange = c(-15, 40), yrange = c(30, 60), crs = \"EPSG:3035\") #> Reading layer `ne_110m_land' from data source #> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmphADFZn/naturalearth/ne_110m_land.shp' #> using driver `ESRI Shapefile' #> Simple feature collection with 127 features and 3 fields #> Geometry type: POLYGON #> Dimension: XY #> Bounding box: xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513 #> Geodetic CRS: WGS 84"},{"path":"https://www.slendr.net/reference/move.html","id":null,"dir":"Reference","previous_headings":"","what":"Move the population to a new location in a given amount of time — move","title":"Move the population to a new location in a given amount of time — move","text":"function defines displacement population along given trajectory given time frame","code":""},{"path":"https://www.slendr.net/reference/move.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Move the population to a new location in a given amount of time — move","text":"","code":"move( pop, trajectory, end, start, overlap = 0.8, snapshots = NULL, verbose = TRUE )"},{"path":"https://www.slendr.net/reference/move.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Move the population to a new location in a given amount of time — move","text":"pop Object class slendr_pop trajectory List two-dimensional vectors (longitude, latitude) specifying migration trajectory start, end Start/end points population migration overlap Minimum overlap subsequent spatial boundaries snapshots number intermediate snapshots (overrides overlap parameter) verbose Show progress searching number sufficient snapshots?","code":""},{"path":"https://www.slendr.net/reference/move.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Move the population to a new location in a given amount of time — move","text":"Object class slendr_pop, contains population parameters name, time appearance simulation, parent population (), spatial parameters map spatial boundary.","code":""},{"path":"https://www.slendr.net/reference/move.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Move the population to a new location in a given amount of time — move","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/msprime.html","id":null,"dir":"Reference","previous_headings":"","what":"Run a slendr model in msprime — msprime","title":"Run a slendr model in msprime — msprime","text":"function execute built-msprime script run compiled slendr demographic model.","code":""},{"path":"https://www.slendr.net/reference/msprime.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Run a slendr model in msprime — msprime","text":"","code":"msprime( model, sequence_length, recombination_rate, samples = NULL, output = NULL, random_seed = NULL, load = TRUE, verbose = FALSE, debug = FALSE, run = TRUE )"},{"path":"https://www.slendr.net/reference/msprime.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Run a slendr model in msprime — msprime","text":"model Model object created compile function sequence_length Total length simulated sequence (base-pairs) recombination_rate Recombination rate simulated sequence (recombinations per basepair per generation) samples data frame times given number individuals remembered tree-sequence (see schedule_sampling function can generate sampling schedule correct format). missing, individuals present end simulation recorded tree-sequence output file. output Path output tree-sequence file. NULL (default), tree sequence saved temporary file. random_seed Random seed (NULL, seed generated 0 maximum integer number available) load final tree sequence immediately loaded returned? Default TRUE. alternative (FALSE) useful tree-sequence file written custom location loaded later point. verbose Write output log console (default FALSE)? debug Write msprime's debug log console (default FALSE)? run msprime engine run? FALSE, command line msprime command printed (returned invisibly character vector) executed.","code":""},{"path":"https://www.slendr.net/reference/msprime.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Run a slendr model in msprime — msprime","text":"tree-sequence object loaded via Python-R reticulate interface function ts_load (internally represented Python object tskit.trees.TreeSequence). Optionally, depending value arguments load = run =, nothing character vector, respectively.","code":""},{"path":"https://www.slendr.net/reference/msprime.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Run a slendr model in msprime — msprime","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # afr and eur objects would normally be created before slendr model compilation, # but here we take them out of the model object already compiled for this # example (in a standard slendr simulation pipeline, this wouldn't be necessary) afr <- model$populations[[\"AFR\"]] eur <- model$populations[[\"EUR\"]] chimp <- model$populations[[\"CH\"]] # schedule the sampling of a couple of ancient and present-day individuals # given model at 20 ky, 10 ky, 5ky ago and at present-day (time 0) modern_samples <- schedule_sampling(model, times = 0, list(afr, 10), list(eur, 100), list(chimp, 1)) ancient_samples <- schedule_sampling(model, times = c(40000, 30000, 20000, 10000), list(eur, 1)) # sampling schedules are just data frames and can be merged easily samples <- rbind(modern_samples, ancient_samples) # run a simulation using the msprime back end from a compiled slendr model object ts <- msprime(model, sequence_length = 1e5, recombination_rate = 0, samples = samples) # automatic loading of a simulated output can be prevented by `load = FALSE`, which can be # useful when a custom path to a tree-sequence output is given for later downstream analyses output_file <- tempfile(fileext = \".trees\") msprime(model, sequence_length = 1e5, recombination_rate = 0, samples = samples, output = output_file, load = FALSE, random_seed = 42) # ... at a later stage: ts <- ts_load(output_file, model) summary(ts) #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 1║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 230║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 39.4 KiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤════╤═════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪═════════╪════════════╣ #> ║Edges │ 471│ 14.7 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Individuals│ 115│ 3.2 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Nodes │ 472│ 12.9 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Provenances│ 1│ 2.9 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧════╧═════════╧════════════╝ #>"},{"path":"https://www.slendr.net/reference/overlap.html","id":null,"dir":"Reference","previous_headings":"","what":"Generate the overlap of two slendr objects — overlap","title":"Generate the overlap of two slendr objects — overlap","text":"Generate overlap two slendr objects","code":""},{"path":"https://www.slendr.net/reference/overlap.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Generate the overlap of two slendr objects — overlap","text":"","code":"overlap(x, y, name = NULL)"},{"path":"https://www.slendr.net/reference/overlap.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Generate the overlap of two slendr objects — overlap","text":"x Object class slendr y Object class slendr name Optional name resulting geographic region. missing, name constructed function arguments.","code":""},{"path":"https://www.slendr.net/reference/overlap.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Generate the overlap of two slendr objects — overlap","text":"Object class slendr_region encodes standard spatial object class sf several additional attributes (importantly corresponding slendr_map object, applicable).","code":""},{"path":"https://www.slendr.net/reference/pipe.html","id":null,"dir":"Reference","previous_headings":"","what":"Pipe operator — %>%","title":"Pipe operator — %>%","text":"Pipe operator","code":""},{"path":"https://www.slendr.net/reference/pipe.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Pipe operator — %>%","text":"","code":"lhs %>% rhs"},{"path":"https://www.slendr.net/reference/pipe.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Pipe operator — %>%","text":"See magrittr::%>% details.","code":""},{"path":"https://www.slendr.net/reference/plot_map.html","id":null,"dir":"Reference","previous_headings":"","what":"Plot slendr geographic features on a map — plot_map","title":"Plot slendr geographic features on a map — plot_map","text":"Plots objects three slendr spatial classes (slendr_map, slendr_region, slendr_pop).","code":""},{"path":"https://www.slendr.net/reference/plot_map.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Plot slendr geographic features on a map — plot_map","text":"","code":"plot_map( ..., time = NULL, gene_flow = FALSE, graticules = \"original\", intersect = TRUE, show_map = TRUE, title = NULL, interpolated_maps = NULL )"},{"path":"https://www.slendr.net/reference/plot_map.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Plot slendr geographic features on a map — plot_map","text":"... Objects classes slendr_map, slendr_region, slendr_pop time Plot concrete time point gene_flow Indicate geneflow events arrow graticules Plot graticules original Coordinate Reference System (longitude-latitude), internal CRS (meters)? intersect Intersect population boundaries landscape geographic boundaries (default TRUE)? show_map Show underlying world map title Title plot interpolated_maps Interpolated spatial boundaries populations time points (used plotting using explore shiny app)","code":""},{"path":"https://www.slendr.net/reference/plot_map.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Plot slendr geographic features on a map — plot_map","text":"ggplot2 object visualized slendr map","code":""},{"path":"https://www.slendr.net/reference/plot_model.html","id":null,"dir":"Reference","previous_headings":"","what":"Plot demographic history encoded in a slendr model — plot_model","title":"Plot demographic history encoded in a slendr model — plot_model","text":"Plot demographic history encoded slendr model","code":""},{"path":"https://www.slendr.net/reference/plot_model.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Plot demographic history encoded in a slendr model — plot_model","text":"","code":"plot_model( model, sizes = TRUE, proportions = FALSE, gene_flow = TRUE, log = FALSE, order = NULL, file = NULL, ... )"},{"path":"https://www.slendr.net/reference/plot_model.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Plot demographic history encoded in a slendr model — plot_model","text":"model Compiled slendr_model model object sizes population size changes visualized? proportions gene flow proportions visualized (FALSE default prevent cluttering overplotting) gene_flow gene-flow arrows visualized (default TRUE). log y-axis plotted log scale? Useful models long time-scales. order Order populations along x-axis, given character vector population names. NULL (default), default plotting algorithm used, ordering populations ancestral recent using -order tree traversal. file Output file figure saved via ggsave ... Optional argument passed ggsave","code":""},{"path":"https://www.slendr.net/reference/plot_model.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Plot demographic history encoded in a slendr model — plot_model","text":"ggplot2 object visualized slendr model","code":""},{"path":"https://www.slendr.net/reference/plot_model.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Plot demographic history encoded in a slendr model — plot_model","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence path <- system.file(\"extdata/models/introgression\", package = \"slendr\") model <- read_model(path) plot_model(model, sizes = FALSE, log = TRUE)"},{"path":"https://www.slendr.net/reference/population.html","id":null,"dir":"Reference","previous_headings":"","what":"Define a population — population","title":"Define a population — population","text":"Defines parameters population (non-spatial spatial).","code":""},{"path":"https://www.slendr.net/reference/population.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Define a population — population","text":"","code":"population( name, time, N, parent = NULL, map = FALSE, center = NULL, radius = NULL, polygon = NULL, remove = NULL, intersect = TRUE, competition = NA, mating = NA, dispersal = NA, dispersal_fun = NULL, aquatic = FALSE )"},{"path":"https://www.slendr.net/reference/population.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Define a population — population","text":"name Name population time Time population's first appearance N Number individuals time first appearance parent Parent population object NULL (indicates population ancestor, first population \"lineage\") map Object type slendr_map defines world context (created using world function). value FALSE provided, non-spatial model run. center Two-dimensional vector specifying center circular range radius Radius circular range polygon List vector pairs, defining corners polygon range geographic region class slendr_region polygon coordinates extracted (see region() function) remove Time population removed intersect Intersect population's boundaries landscape features? competition, mating Maximum spatial competition mating choice distance dispersal Standard deviation normal distribution distance offspring disperses parent dispersal_fun Distribution function governing dispersal offspring. One \"normal\", \"uniform\", \"cauchy\", \"exponential\", \"brownian\" (vertical horizontal displacements drawn normal distribution independently). aquatic species aquatic (FALSE default, .e. terrestrial species)?","code":""},{"path":"https://www.slendr.net/reference/population.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Define a population — population","text":"Object class slendr_pop, contains population parameters name, time appearance simulation, parent population (), spatial parameters map spatial boundary.","code":""},{"path":"https://www.slendr.net/reference/population.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Define a population — population","text":"four ways specify spatial boundary: ) circular range specified using center coordinate radius, ii) polygon specified list two-dimensional vector coordinates, iii) polygon ii), defined (named) using region function, iv) just world map specified (circular polygon range parameters set default NULL value), population allowed occupy entire landscape. Note slendr models accomodate SLiM msprime back ends, population sizes split times rounded nearest integer value.","code":""},{"path":"https://www.slendr.net/reference/population.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Define a population — population","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/print.slendr_pop.html","id":null,"dir":"Reference","previous_headings":"","what":"Print a short summary of a slendr object — print.slendr_pop","title":"Print a short summary of a slendr object — print.slendr_pop","text":"spatial objects slendr package internally represented Simple Features (sf) objects. fact hidden circumstances , goal slendr package provide functionality much higher level (population boundaries, geographic regions, instead individual polygons \"low-level\" geometric objects), without users worry low-level details involved handling spatial geometries. However, full sf object representation can always printed calling x[].","code":""},{"path":"https://www.slendr.net/reference/print.slendr_pop.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Print a short summary of a slendr object — print.slendr_pop","text":"","code":"# S3 method for slendr_pop print(x, ...) # S3 method for slendr_region print(x, ...) # S3 method for slendr_map print(x, ...) # S3 method for slendr_model print(x, ...)"},{"path":"https://www.slendr.net/reference/print.slendr_pop.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Print a short summary of a slendr object — print.slendr_pop","text":"x Object class slendr (either slendr_pop, slendr_map, slendr_region, slendr_table) ... Additional arguments passed print","code":""},{"path":"https://www.slendr.net/reference/print.slendr_pop.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Print a short summary of a slendr object — print.slendr_pop","text":"return value, used printing","code":""},{"path":"https://www.slendr.net/reference/print.slendr_ts.html","id":null,"dir":"Reference","previous_headings":"","what":"Print tskit's summary table of the Python tree-sequence object — print.slendr_ts","title":"Print tskit's summary table of the Python tree-sequence object — print.slendr_ts","text":"Print tskit's summary table Python tree-sequence object","code":""},{"path":"https://www.slendr.net/reference/print.slendr_ts.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Print tskit's summary table of the Python tree-sequence object — print.slendr_ts","text":"","code":"# S3 method for slendr_ts print(x, ...)"},{"path":"https://www.slendr.net/reference/print.slendr_ts.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Print tskit's summary table of the Python tree-sequence object — print.slendr_ts","text":"x Tree object class slendr_phylo ... Additional arguments normally passed print (used case)","code":""},{"path":"https://www.slendr.net/reference/print.slendr_ts.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Print tskit's summary table of the Python tree-sequence object — print.slendr_ts","text":"return value, simply prints tskit summary table terminal","code":""},{"path":"https://www.slendr.net/reference/read_model.html","id":null,"dir":"Reference","previous_headings":"","what":"Read a previously serialized model configuration — read_model","title":"Read a previously serialized model configuration — read_model","text":"Reads configuration tables model data location previously compiled compile function.","code":""},{"path":"https://www.slendr.net/reference/read_model.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Read a previously serialized model configuration — read_model","text":"","code":"read_model(path)"},{"path":"https://www.slendr.net/reference/read_model.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Read a previously serialized model configuration — read_model","text":"path Directory required configuration files","code":""},{"path":"https://www.slendr.net/reference/read_model.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Read a previously serialized model configuration — read_model","text":"Compiled slendr_model model object encapsulates information specified model (populations involved, much gene flow occur, spatial resolution map, spatial dispersal mating parameters used SLiM simulation, applicable)","code":""},{"path":"https://www.slendr.net/reference/read_model.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Read a previously serialized model configuration — read_model","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence path <- system.file(\"extdata/models/introgression\", package = \"slendr\") model <- read_model(path) plot_model(model, sizes = FALSE, log = TRUE)"},{"path":"https://www.slendr.net/reference/region.html","id":null,"dir":"Reference","previous_headings":"","what":"Define a geographic region — region","title":"Define a geographic region — region","text":"Creates geographic region (polygon) given map gives name. can used define objects can reused multiple places slendr script (region arguments population) without repeatedly define polygon coordinates.","code":""},{"path":"https://www.slendr.net/reference/region.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Define a geographic region — region","text":"","code":"region(name = NULL, map = NULL, center = NULL, radius = NULL, polygon = NULL)"},{"path":"https://www.slendr.net/reference/region.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Define a geographic region — region","text":"name Name geographic region map Object type sf defines map center Two-dimensional vector specifying center circular range radius Radius circular range polygon List vector pairs, defining corners polygon range geographic region class slendr_region polygon coordinates extracted (see region() function)","code":""},{"path":"https://www.slendr.net/reference/region.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Define a geographic region — region","text":"Object class slendr_region encodes standard spatial object class sf several additional attributes (importantly corresponding slendr_map object, applicable).","code":""},{"path":"https://www.slendr.net/reference/region.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Define a geographic region — region","text":"","code":"# create a blank abstract world 1000x1000 distance units in size blank_map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # it is possible to construct custom landscapes (islands, corridors, etc.) island1 <- region(\"island1\", polygon = list(c(10, 30), c(50, 30), c(40, 50), c(0, 40))) island2 <- region(\"island2\", polygon = list(c(60, 60), c(80, 40), c(100, 60), c(80, 80))) island3 <- region(\"island3\", center = c(20, 80), radius = 10) archipelago <- island1 %>% join(island2) %>% join(island3) custom_map <- world(xrange = c(1, 100), c(1, 100), landscape = archipelago) # real Earth landscapes can be defined using freely-available Natural Earth # project data and with the possibility to specify an appropriate Coordinate # Reference System, such as this example of a map of Europe real_map <- world(xrange = c(-15, 40), yrange = c(30, 60), crs = \"EPSG:3035\") #> Reading layer `ne_110m_land' from data source #> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmphADFZn/naturalearth/ne_110m_land.shp' #> using driver `ESRI Shapefile' #> Simple feature collection with 127 features and 3 fields #> Geometry type: POLYGON #> Dimension: XY #> Bounding box: xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513 #> Geodetic CRS: WGS 84"},{"path":"https://www.slendr.net/reference/reproject.html","id":null,"dir":"Reference","previous_headings":"","what":"Reproject coordinates between coordinate systems — reproject","title":"Reproject coordinates between coordinate systems — reproject","text":"Converts coordinates compiled raster map (.e. pixel units) different Geographic Coordinate Systems (CRS).","code":""},{"path":"https://www.slendr.net/reference/reproject.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Reproject coordinates between coordinate systems — reproject","text":"","code":"reproject( from, to, x = NULL, y = NULL, coords = NULL, model = NULL, add = FALSE, input_prefix = \"\", output_prefix = \"new\" )"},{"path":"https://www.slendr.net/reference/reproject.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Reproject coordinates between coordinate systems — reproject","text":", Either CRS code accepted GDAL, valid integer EPSG value, object class crs, value \"raster\" (converting /pixel coordinates), \"world\" (converting /whatever CRS set underlying map) x, y Coordinates two dimensions (missing, coordinates expected data.frame specified coords parameter columns \"x\" \"y\") coords data.frame-like object coordinates columns \"x\" \"y\" model Object class slendr_model add Add column coordinates input data.frame coords (coordinates otherwise returned separate object)? input_prefix, output_prefix Input output prefixes data frame columns spatial coordinates","code":""},{"path":"https://www.slendr.net/reference/reproject.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Reproject coordinates between coordinate systems — reproject","text":"Data.frame converted two-dimensional coordinates given input","code":""},{"path":"https://www.slendr.net/reference/reproject.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Reproject coordinates between coordinate systems — reproject","text":"","code":"lon_lat_df <- data.frame(x = c(30, 0, 15), y = c(60, 40, 10)) reproject( from = \"epsg:4326\", to = \"epsg:3035\", coords = lon_lat_df, add = TRUE # add converted [lon,lat] coordinates as a new column ) #> # A tibble: 3 × 4 #> x y newx newy #> #> 1 30 60 5422493. 4256803. #> 2 0 40 3465349. 1934879. #> 3 15 10 4907297. -1328914."},{"path":"https://www.slendr.net/reference/resize.html","id":null,"dir":"Reference","previous_headings":"","what":"Change the population size — resize","title":"Change the population size — resize","text":"Resizes population starting current value N individuals specified value","code":""},{"path":"https://www.slendr.net/reference/resize.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Change the population size — resize","text":"","code":"resize(pop, N, how, time, end = NULL)"},{"path":"https://www.slendr.net/reference/resize.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Change the population size — resize","text":"pop Object class slendr_pop N Population size change change population size (options \"step\" \"exponential\") time Time population size change end End population size change period (used exponential change events)","code":""},{"path":"https://www.slendr.net/reference/resize.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Change the population size — resize","text":"Object class slendr_pop, contains population parameters name, time appearance simulation, parent population (), spatial parameters map spatial boundary.","code":""},{"path":"https://www.slendr.net/reference/resize.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Change the population size — resize","text":"case exponential size change, final N larger current size, population exponentially growing specified time period reaches N individuals. N smaller, population shrink exponentially. Note slendr models accomodate SLiM msprime back ends, population sizes split times rounded nearest integer value.","code":""},{"path":"https://www.slendr.net/reference/resize.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Change the population size — resize","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/schedule_sampling.html","id":null,"dir":"Reference","previous_headings":"","what":"Define sampling events for a given set of populations — schedule_sampling","title":"Define sampling events for a given set of populations — schedule_sampling","text":"Schedule sampling events specified times , optionally, given set locations landscape","code":""},{"path":"https://www.slendr.net/reference/schedule_sampling.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Define sampling events for a given set of populations — schedule_sampling","text":"","code":"schedule_sampling(model, times, ..., locations = NULL, strict = FALSE)"},{"path":"https://www.slendr.net/reference/schedule_sampling.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Define sampling events for a given set of populations — schedule_sampling","text":"model Object class slendr_model times Integer vector times (model time units) schedule remembering individuals tree-sequence ... Lists two elements (slendr_pop population object- The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence path <- system.file(\"extdata/models/introgression\", package = \"slendr\") model <- read_model(path) # afr and eur objects would normally be created before slendr model compilation, # but here we take them out of the model object already compiled for this # example (in a standard slendr simulation pipeline, this wouldn't be necessary) afr <- model$populations[[\"AFR\"]] eur <- model$populations[[\"EUR\"]] # schedule the recording of 10 African and 100 European individuals from a # given model at 20 ky, 10 ky, 5ky ago and at present-day (time 0) schedule <- schedule_sampling( model, times = c(20000, 10000, 5000, 0), list(afr, 10), list(eur, 100) ) # the result of `schedule_sampling` is a simple data frame (note that the locations # of sampling locations have `NA` values because the model is non-spatial) schedule #> # A tibble: 8 × 7 #> time pop n y_orig x_orig y x #> #> 1 0 AFR 10 NA NA NA NA #> 2 0 EUR 100 NA NA NA NA #> 3 5000 AFR 10 NA NA NA NA #> 4 5000 EUR 100 NA NA NA NA #> 5 10000 AFR 10 NA NA NA NA #> 6 10000 EUR 100 NA NA NA NA #> 7 20000 AFR 10 NA NA NA NA #> 8 20000 EUR 100 NA NA NA NA"},{"path":"https://www.slendr.net/reference/set_dispersal.html","id":null,"dir":"Reference","previous_headings":"","what":"Change dispersal parameters — set_dispersal","title":"Change dispersal parameters — set_dispersal","text":"Changes either competition interactive distance, mating choice distance, dispersal offspring parent","code":""},{"path":"https://www.slendr.net/reference/set_dispersal.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Change dispersal parameters — set_dispersal","text":"","code":"set_dispersal( pop, time, competition = NA, mating = NA, dispersal = NA, dispersal_fun = NULL )"},{"path":"https://www.slendr.net/reference/set_dispersal.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Change dispersal parameters — set_dispersal","text":"pop Object class slendr_pop time Time population size change competition, mating Maximum spatial competition mating choice distance dispersal Standard deviation normal distribution distance offspring disperses parent dispersal_fun Distribution function governing dispersal offspring. One \"normal\", \"uniform\", \"cauchy\", \"exponential\", \"brownian\" (vertical horizontal displacements drawn normal distribution independently).","code":""},{"path":"https://www.slendr.net/reference/set_dispersal.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Change dispersal parameters — set_dispersal","text":"Object class slendr_pop, contains population parameters name, time appearance simulation, parent population (), spatial parameters map spatial boundary.","code":""},{"path":"https://www.slendr.net/reference/set_dispersal.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Change dispersal parameters — set_dispersal","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/set_range.html","id":null,"dir":"Reference","previous_headings":"","what":"Update the population range — set_range","title":"Update the population range — set_range","text":"function allows manual control spatial map changes addition expand move functions","code":""},{"path":"https://www.slendr.net/reference/set_range.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Update the population range — set_range","text":"","code":"set_range( pop, time, center = NULL, radius = NULL, polygon = NULL, lock = FALSE )"},{"path":"https://www.slendr.net/reference/set_range.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Update the population range — set_range","text":"pop Object class slendr_pop time Time change center Two-dimensional vector specifying center circular range radius Radius circular range polygon List vector pairs, defining corners polygon range (see also region argument) geographic region class slendr_region polygon coordinates extracted lock Maintain density individuals. FALSE (default), number individuals population change. TRUE, number individuals simulated changed (increased decreased) appropriately, match new population range area.","code":""},{"path":"https://www.slendr.net/reference/set_range.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Update the population range — set_range","text":"Object class slendr_pop, contains population parameters name, time appearance simulation, parent population (), spatial parameters map spatial boundary.","code":""},{"path":"https://www.slendr.net/reference/set_range.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Update the population range — set_range","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/setup_env.html","id":null,"dir":"Reference","previous_headings":"","what":"Setup a dedicated Python virtual environment for slendr — setup_env","title":"Setup a dedicated Python virtual environment for slendr — setup_env","text":"function automatically download Python miniconda distribution dedicated R-Python interface. also create slendr-specific Python environment required Python dependencies.","code":""},{"path":"https://www.slendr.net/reference/setup_env.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Setup a dedicated Python virtual environment for slendr — setup_env","text":"","code":"setup_env(quiet = FALSE, agree = FALSE, pip = NULL)"},{"path":"https://www.slendr.net/reference/setup_env.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Setup a dedicated Python virtual environment for slendr — setup_env","text":"quiet informative messages printed console? Default FALSE. agree Automatically agree questions? pip pip used instead conda installing slendr's Python dependencies? Note still use conda distribution install Python , change repository slendr install Python dependencies. Unless explicitly set TRUE, Python dependencies installed conda repositories default, expect case osx-arm64 Mac architecture, conda dependencies broken.","code":""},{"path":"https://www.slendr.net/reference/setup_env.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Setup a dedicated Python virtual environment for slendr — setup_env","text":"return value, called side effects","code":""},{"path":"https://www.slendr.net/reference/shrink_range.html","id":null,"dir":"Reference","previous_headings":"","what":"Shrink the population range — shrink_range","title":"Shrink the population range — shrink_range","text":"Shrinks spatial population range specified distance given time-window","code":""},{"path":"https://www.slendr.net/reference/shrink_range.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Shrink the population range — shrink_range","text":"","code":"shrink_range( pop, by, end, start, overlap = 0.8, snapshots = NULL, lock = FALSE, verbose = TRUE )"},{"path":"https://www.slendr.net/reference/shrink_range.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Shrink the population range — shrink_range","text":"pop Object class slendr_pop many units distance shrink ? start, end boundary shrinking start/end? overlap Minimum overlap subsequent spatial boundaries snapshots number intermediate snapshots (overrides overlap parameter) lock Maintain density individuals. FALSE (default), number individuals population change. TRUE, number individuals simulated changed (increased decreased) appropriately, match new population range area. verbose Report progress generating intermediate spatial boundaries?","code":""},{"path":"https://www.slendr.net/reference/shrink_range.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Shrink the population range — shrink_range","text":"Object class slendr_pop, contains population parameters name, time appearance simulation, parent population (), spatial parameters map spatial boundary.","code":""},{"path":"https://www.slendr.net/reference/shrink_range.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Shrink the population range — shrink_range","text":"Note slendr models accomodate SLiM msprime back ends, population sizes split times rounded nearest integer value.","code":""},{"path":"https://www.slendr.net/reference/shrink_range.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Shrink the population range — shrink_range","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/slendr.html","id":null,"dir":"Reference","previous_headings":"","what":"A Simulation Framework for Spatiotemporal Population Genetics — slendr","title":"A Simulation Framework for Spatiotemporal Population Genetics — slendr","text":"framework simulating spatially explicit genomic data leverages real cartographic information programmatic visual encoding spatiotemporal population dynamics real geographic landscapes. Population genetic models automatically executed 'SLiM' software behind scenes, using custom built-simulation 'SLiM' script. Additionally, fully abstract spatial models tied specific geographic location supported, users can also simulate data standard, non-spatial, random-mating models. can simulated either 'SLiM' built-back-end script, using efficient coalescent population genetics simulator 'msprime' custom-built 'Python' script bundled R package. Simulated genomic data saved tree-sequence format can loaded, manipulated, summarised using tree-sequence functionality via R interface 'Python' module 'tskit'. Complete model configuration, simulation analysis pipelines can therefore constructed without need leave R environment, eliminating friction disparate tools population genetic simulations data analysis.","code":""},{"path":"https://www.slendr.net/reference/slendr.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"A Simulation Framework for Spatiotemporal Population Genetics — slendr","text":"can find installation instructions, reference manual, tutorials https://www.slendr.net.","code":""},{"path":[]},{"path":"https://www.slendr.net/reference/slendr.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"A Simulation Framework for Spatiotemporal Population Genetics — slendr","text":"Maintainer: Martin Petr contact@bodkan.net (ORCID)","code":""},{"path":"https://www.slendr.net/reference/slim.html","id":null,"dir":"Reference","previous_headings":"","what":"Run a slendr model in SLiM — slim","title":"Run a slendr model in SLiM — slim","text":"function execute SLiM script generated compile function compilation slendr demographic model.","code":""},{"path":"https://www.slendr.net/reference/slim.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Run a slendr model in SLiM — slim","text":"","code":"slim( model, sequence_length, recombination_rate, samples = NULL, output = NULL, burnin = 0, max_attempts = 1, spatial = !is.null(model$world), coalescent_only = TRUE, method = c(\"batch\", \"gui\"), random_seed = NULL, run = TRUE, verbose = FALSE, load = TRUE, locations = NULL, slim_path = NULL )"},{"path":"https://www.slendr.net/reference/slim.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Run a slendr model in SLiM — slim","text":"model Model object created compile function sequence_length Total length simulated sequence (base-pairs) recombination_rate Recombination rate simulated sequence (recombinations per basepair per generation) samples data frame times given number individuals remembered tree-sequence (see schedule_sampling function can generate sampling schedule correct format). missing, individuals present end simulation recorded tree-sequence output file. output Path output tree-sequence file. NULL (default), tree sequence saved temporary file. burnin Length burnin (model's time units, .e. years) max_attempts many attempts made place offspring near one parents? Serves prevent infinite loops SLiM backend. Default value 1. spatial model executed spatial mode? default, world map specified model definition, simulation proceed spatial mode. coalescent_only initializeTreeSeq(retainCoalescentOnly = <...>) set TRUE (default) FALSE? See \"retainCoalescentOnly\" SLiM manual detail. method run script? (\"gui\" - open SLiMgui, \"batch\" - run command line) random_seed Random seed (NULL, seed generated 0 maximum integer number available) run SLiM engine run? FALSE, command line SLiM command printed (returned invisibly character vector) executed. verbose Write SLiM output log console (default FALSE)? load final tree sequence immediately loaded returned? Default TRUE. alternative (FALSE) useful tree-sequence file written custom location loaded later point. locations NULL, locations saved. Otherwise, path file locations individual throughout simulation saved (likely use animate_model). slim_path Path appropriate SLiM binary (useful slim binary $PATH). Note argument must specified function run Windows.","code":""},{"path":"https://www.slendr.net/reference/slim.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Run a slendr model in SLiM — slim","text":"tree-sequence object loaded via Python-R reticulate interface function ts_load (internally represented Python object tskit.trees.TreeSequence). Optionally, depending value arguments load = run =, nothing character vector, respectively.","code":""},{"path":"https://www.slendr.net/reference/slim.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Run a slendr model in SLiM — slim","text":"","code":"check_dependencies(python = TRUE, slim = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # afr and eur objects would normally be created before slendr model compilation, # but here we take them out of the model object already compiled for this # example (in a standard slendr simulation pipeline, this wouldn't be necessary) afr <- model$populations[[\"AFR\"]] eur <- model$populations[[\"EUR\"]] chimp <- model$populations[[\"CH\"]] # schedule the sampling of a couple of ancient and present-day individuals # given model at 20 ky, 10 ky, 5ky ago and at present-day (time 0) modern_samples <- schedule_sampling(model, times = 0, list(afr, 5), list(eur, 5), list(chimp, 1)) ancient_samples <- schedule_sampling(model, times = c(30000, 20000, 10000), list(eur, 1)) # sampling schedules are just data frames and can be merged easily samples <- rbind(modern_samples, ancient_samples) # run a simulation using the SLiM back end from a compiled slendr model object and return # a tree-sequence output ts <- slim(model, sequence_length = 1e5, recombination_rate = 0, samples = samples) # automatic loading of a simulated output can be prevented by `load = FALSE`, which can be # useful when a custom path to a tree-sequence output is given for later downstream analyses output_file <- tempfile(fileext = \".trees\") slim(model, sequence_length = 1e5, recombination_rate = 0, samples = samples, output = output_file, load = FALSE) # ... at a later stage: ts <- ts_load(output_file, model) ts #> ╔═══════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════╣ #> ║Trees │ 1║ #> ╟───────────────┼───────╢ #> ║Sequence Length│ 100000║ #> ╟───────────────┼───────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼───────╢ #> ║Sample Nodes │ 10046║ #> ╟───────────────┼───────╢ #> ║Total Size │2.6 MiB║ #> ╚═══════════════╧═══════╝ #> ╔═══════════╤═════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪═════╪═════════╪════════════╣ #> ║Edges │18361│573.8 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Individuals│12858│ 1.2 MiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Nodes │18362│682.1 KiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Populations│ 4│ 2.5 KiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Provenances│ 1│ 34.7 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧═════╧═════════╧════════════╝ #>"},{"path":"https://www.slendr.net/reference/subtract.html","id":null,"dir":"Reference","previous_headings":"","what":"Generate the difference between two slendr objects — subtract","title":"Generate the difference between two slendr objects — subtract","text":"Generate difference two slendr objects","code":""},{"path":"https://www.slendr.net/reference/subtract.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Generate the difference between two slendr objects — subtract","text":"","code":"subtract(x, y, name = NULL)"},{"path":"https://www.slendr.net/reference/subtract.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Generate the difference between two slendr objects — subtract","text":"x Object class slendr y Object class slendr name Optional name resulting geographic region. missing, name constructed function arguments.","code":""},{"path":"https://www.slendr.net/reference/subtract.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Generate the difference between two slendr objects — subtract","text":"Object class slendr_region encodes standard spatial object class sf several additional attributes (importantly corresponding slendr_map object, applicable).","code":""},{"path":"https://www.slendr.net/reference/summary.slendr_nodes.html","id":null,"dir":"Reference","previous_headings":"","what":"Summarise the contents of a ts_nodes result — summary.slendr_nodes","title":"Summarise the contents of a ts_nodes result — summary.slendr_nodes","text":"Summarise contents ts_nodes result","code":""},{"path":"https://www.slendr.net/reference/summary.slendr_nodes.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Summarise the contents of a ts_nodes result — summary.slendr_nodes","text":"","code":"# S3 method for slendr_nodes summary(object, ...)"},{"path":"https://www.slendr.net/reference/summary.slendr_nodes.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Summarise the contents of a ts_nodes result — summary.slendr_nodes","text":"object Data frame produced function ts_nodes ... Additional formal arguments summary method (unused )","code":""},{"path":"https://www.slendr.net/reference/summary.slendr_nodes.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Summarise the contents of a ts_nodes result — summary.slendr_nodes","text":"Used output terminal","code":""},{"path":"https://www.slendr.net/reference/ts_afs.html","id":null,"dir":"Reference","previous_headings":"","what":"Compute the allele frequency spectrum (AFS) — ts_afs","title":"Compute the allele frequency spectrum (AFS) — ts_afs","text":"function computes AFS respect given set individuals nodes.","code":""},{"path":"https://www.slendr.net/reference/ts_afs.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Compute the allele frequency spectrum (AFS) — ts_afs","text":"","code":"ts_afs( ts, sample_sets = NULL, mode = c(\"site\", \"branch\", \"node\"), windows = NULL, span_normalise = FALSE, polarised = TRUE )"},{"path":"https://www.slendr.net/reference/ts_afs.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Compute the allele frequency spectrum (AFS) — ts_afs","text":"ts Tree sequence object class slendr_ts sample_sets list (optionally named list) character vectors individual names (one vector per set). NULL, allele frequency spectrum individuals tree sequence computed. mode mode calculation (\"sites\" \"branch\") windows Coordinates breakpoints windows. first coordinate (0) last coordinate (equal ts$sequence_length) added automatically) span_normalise Argument passed tskit's allele_frequency_spectrum method polarised TRUE (default) allele frequency spectrum folded (.e. counts assume knowledge allele ancestral, derived, known simulation)","code":""},{"path":"https://www.slendr.net/reference/ts_afs.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Compute the allele frequency spectrum (AFS) — ts_afs","text":"Allele frequency spectrum values given sample set. Note contents first last elements AFS might surprise . Read links description detail tskit handles things.","code":""},{"path":"https://www.slendr.net/reference/ts_afs.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Compute the allele frequency spectrum (AFS) — ts_afs","text":"information format result dimensions, particular interpretation first last element AFS (complete = TRUE), please see tskit manual https://tskit.dev/tskit/docs/stable/python-api.html example section dedicated AFS https://tskit.dev/tutorials/analysing_tree_sequences.html#allele-frequency-spectra.","code":""},{"path":"https://www.slendr.net/reference/ts_afs.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Compute the allele frequency spectrum (AFS) — ts_afs","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) %>% ts_mutate(mutation_rate = 1e-8, random_seed = 42) samples <- ts_samples(ts) %>% .[.$pop %in% c(\"AFR\", \"EUR\"), ] # compute AFS for the given set of individuals ts_afs(ts, sample_sets = list(samples$name)) #> [1] 1080 73 21 8 1 4 0 0 0 0 11 0 0 0 0 #> [16] 1 0 3 5 10 935"},{"path":"https://www.slendr.net/reference/ts_ancestors.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract (spatio-)temporal ancestral history for given nodes/individuals — ts_ancestors","title":"Extract (spatio-)temporal ancestral history for given nodes/individuals — ts_ancestors","text":"Extract (spatio-)temporal ancestral history given nodes/individuals","code":""},{"path":"https://www.slendr.net/reference/ts_ancestors.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract (spatio-)temporal ancestral history for given nodes/individuals — ts_ancestors","text":"","code":"ts_ancestors(ts, x, verbose = FALSE, complete = TRUE)"},{"path":"https://www.slendr.net/reference/ts_ancestors.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract (spatio-)temporal ancestral history for given nodes/individuals — ts_ancestors","text":"ts Tree sequence object class slendr_ts x Either individual name integer node ID verbose Report progress ancestry path generation? complete every individual tree sequence need complete metadata recorded? TRUE, individuals/nodes complete metadata included reconstruction ancestral relationships. instance, nodes added coalescent recapitation phase included spatial information associated .","code":""},{"path":"https://www.slendr.net/reference/ts_ancestors.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract (spatio-)temporal ancestral history for given nodes/individuals — ts_ancestors","text":"table ancestral nodes given tree-sequence node way root tree sequence","code":""},{"path":"https://www.slendr.net/reference/ts_ancestors.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract (spatio-)temporal ancestral history for given nodes/individuals — ts_ancestors","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # find the complete ancestry information for a given individual ts_ancestors(ts, \"EUR_1\", verbose = TRUE) #> Collecting ancestors of EUR_1 [1/1]... #> #> Generating data about spatial relationships of nodes... #> # A tibble: 222 × 12 #> name pop node_id level child_id parent_id child_time parent_time child_pop #> #> 1 EUR_1 EUR 16 1 16 33 0 500 EUR #> 2 EUR_1 EUR 16 2 33 43 500 21830 EUR #> 3 EUR_1 EUR 16 2 33 47 500 28730 EUR #> 4 EUR_1 EUR 16 2 33 49 500 30380 EUR #> 5 EUR_1 EUR 16 2 33 51 500 35360 EUR #> 6 EUR_1 EUR 16 2 33 54 500 39380 EUR #> 7 EUR_1 EUR 16 2 33 57 500 41510 EUR #> 8 EUR_1 EUR 16 2 33 58 500 44810 EUR #> 9 EUR_1 EUR 16 2 33 59 500 46040 EUR #> 10 EUR_1 EUR 16 2 33 62 500 51680 EUR #> # ℹ 212 more rows #> # ℹ 3 more variables: parent_pop , left_pos , right_pos "},{"path":"https://www.slendr.net/reference/ts_coalesced.html","id":null,"dir":"Reference","previous_headings":"","what":"Check that all trees in the tree sequence are fully coalesced — ts_coalesced","title":"Check that all trees in the tree sequence are fully coalesced — ts_coalesced","text":"Check trees tree sequence fully coalesced","code":""},{"path":"https://www.slendr.net/reference/ts_coalesced.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Check that all trees in the tree sequence are fully coalesced — ts_coalesced","text":"","code":"ts_coalesced(ts, return_failed = FALSE)"},{"path":"https://www.slendr.net/reference/ts_coalesced.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Check that all trees in the tree sequence are fully coalesced — ts_coalesced","text":"ts Tree sequence object class slendr_ts return_failed Report back trees failed coalescence check?","code":""},{"path":"https://www.slendr.net/reference/ts_coalesced.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Check that all trees in the tree sequence are fully coalesced — ts_coalesced","text":"TRUE FALSE value return_failed = FALSE, otherwise vector (tskit Python 0-based) indices trees failed coalescence test","code":""},{"path":"https://www.slendr.net/reference/ts_coalesced.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Check that all trees in the tree sequence are fully coalesced — ts_coalesced","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) ts_coalesced(ts) # is the tree sequence fully coalesced? (TRUE or FALSE) #> [1] TRUE # returns a vector of tree sequence segments which are not coalesced not_coalesced <- ts_coalesced(ts, return_failed = TRUE)"},{"path":"https://www.slendr.net/reference/ts_descendants.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract all descendants of a given tree-sequence node — ts_descendants","title":"Extract all descendants of a given tree-sequence node — ts_descendants","text":"Extract descendants given tree-sequence node","code":""},{"path":"https://www.slendr.net/reference/ts_descendants.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract all descendants of a given tree-sequence node — ts_descendants","text":"","code":"ts_descendants(ts, x, verbose = FALSE, complete = TRUE)"},{"path":"https://www.slendr.net/reference/ts_descendants.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract all descendants of a given tree-sequence node — ts_descendants","text":"ts Tree sequence object class slendr_ts x integer node ID ancestral node verbose Report progress ancestry path generation? complete every individual tree sequence need complete metadata recorded? TRUE, individuals/nodes complete metadata included reconstruction ancestral relationships. instance, nodes added coalescent recapitation phase included spatial information associated .","code":""},{"path":"https://www.slendr.net/reference/ts_descendants.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract all descendants of a given tree-sequence node — ts_descendants","text":"table descendant nodes given tree-sequence node way leaves tree sequence","code":""},{"path":"https://www.slendr.net/reference/ts_descendants.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract all descendants of a given tree-sequence node — ts_descendants","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # find the complete descendancy information for a given individual ts_descendants(ts, x = 62, verbose = TRUE) #> #> Generating data about spatial relationships of nodes... #> # A tibble: 4 × 12 #> name pop node_id level child_id parent_id child_time parent_time child_pop #> #> 1 EUR_4 EUR 62 1 22 62 0 51680 EUR #> 2 NA EUR 62 1 33 62 500 51680 EUR #> 3 EUR_1 EUR 62 2 16 33 0 500 EUR #> 4 EUR_2 EUR 62 2 18 33 0 500 EUR #> # ℹ 3 more variables: parent_pop , left_pos , right_pos "},{"path":"https://www.slendr.net/reference/ts_divergence.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate pairwise divergence between sets of individuals — ts_divergence","title":"Calculate pairwise divergence between sets of individuals — ts_divergence","text":"Calculate pairwise divergence sets individuals","code":""},{"path":"https://www.slendr.net/reference/ts_divergence.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate pairwise divergence between sets of individuals — ts_divergence","text":"","code":"ts_divergence( ts, sample_sets, mode = c(\"site\", \"branch\", \"node\"), windows = NULL, span_normalise = TRUE )"},{"path":"https://www.slendr.net/reference/ts_divergence.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate pairwise divergence between sets of individuals — ts_divergence","text":"ts Tree sequence object class slendr_ts sample_sets list (optionally named list) character vectors individual names (one vector per set) mode mode calculation (\"sites\" \"branch\") windows Coordinates breakpoints windows. first coordinate (0) last coordinate (equal ts$sequence_length) specified added automatically. span_normalise Divide result span window? Default TRUE, see tskit documentation detail.","code":""},{"path":"https://www.slendr.net/reference/ts_divergence.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate pairwise divergence between sets of individuals — ts_divergence","text":"pairwise calculation, either single divergence value vector divergence values (one window)","code":""},{"path":"https://www.slendr.net/reference/ts_divergence.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate pairwise divergence between sets of individuals — ts_divergence","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) %>% ts_mutate(mutation_rate = 1e-8, random_seed = 42) # collect sampled individuals from all populations in a list sample_sets <- ts_samples(ts) %>% split(., .$pop) %>% lapply(function(pop) pop$name) # compute the divergence between individuals from each sample set (list of # individual names generated in the previous step) ts_divergence(ts, sample_sets) %>% .[order(.$divergence), ] #> # A tibble: 6 × 3 #> x y divergence #> #> 1 AFR EUR 0.0000602 #> 2 EUR NEA 0.000289 #> 3 AFR NEA 0.000305 #> 4 CH NEA 0.00397 #> 5 AFR CH 0.00398 #> 6 CH EUR 0.00398"},{"path":"https://www.slendr.net/reference/ts_diversity.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate diversity in given sets of individuals — ts_diversity","title":"Calculate diversity in given sets of individuals — ts_diversity","text":"Calculate diversity given sets individuals","code":""},{"path":"https://www.slendr.net/reference/ts_diversity.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate diversity in given sets of individuals — ts_diversity","text":"","code":"ts_diversity( ts, sample_sets, mode = c(\"site\", \"branch\", \"node\"), windows = NULL, span_normalise = TRUE )"},{"path":"https://www.slendr.net/reference/ts_diversity.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate diversity in given sets of individuals — ts_diversity","text":"ts Tree sequence object class slendr_ts sample_sets list (optionally named list) character vectors individual names (one vector per set). simple vector provided, interpreted .list(sample_sets), meaning given statistic calculated individual separately. mode mode calculation (\"sites\" \"branch\") windows Coordinates breakpoints windows. first coordinate (0) last coordinate (equal ts$sequence_length) added automatically) span_normalise Divide result span window? Default TRUE, see tskit documentation detail.","code":""},{"path":"https://www.slendr.net/reference/ts_diversity.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate diversity in given sets of individuals — ts_diversity","text":"set individuals either single diversity value vector diversity values (one window)","code":""},{"path":"https://www.slendr.net/reference/ts_diversity.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate diversity in given sets of individuals — ts_diversity","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) %>% ts_mutate(mutation_rate = 1e-8, random_seed = 42) # collect sampled individuals from all populations in a list sample_sets <- ts_samples(ts) %>% split(., .$pop) %>% lapply(function(pop) pop$name) # compute diversity in each population based on sample sets extracted # in the previous step ts_diversity(ts, sample_sets) %>% .[order(.$diversity), ] #> # A tibble: 4 × 2 #> set diversity #> #> 1 CH 0 #> 2 AFR 0.0000004 #> 3 NEA 0.00000933 #> 4 EUR 0.0000661"},{"path":"https://www.slendr.net/reference/ts_draw.html","id":null,"dir":"Reference","previous_headings":"","what":"Plot a graphical representation of a single tree — ts_draw","title":"Plot a graphical representation of a single tree — ts_draw","text":"function first obtains SVG representation tree calling draw_svg method tskit renders bitmap image R. many optional keyword arguments draw_svg method can provided automatically passed method behind scenes.","code":""},{"path":"https://www.slendr.net/reference/ts_draw.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Plot a graphical representation of a single tree — ts_draw","text":"","code":"ts_draw( x, width = 1000, height = 1000, labels = FALSE, sampled_only = TRUE, title = NULL, ... )"},{"path":"https://www.slendr.net/reference/ts_draw.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Plot a graphical representation of a single tree — ts_draw","text":"x single tree extracted ts_tree width, height Pixel dimensions rendered bitmap labels Label node individual name? sampled_only individuals explicitly sampled simplification labeled? relevant situations sampled individuals can among ancestral nodes. title Optional title figure ... Keyword arguments tskit draw_svg function.","code":""},{"path":"https://www.slendr.net/reference/ts_draw.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Plot a graphical representation of a single tree — ts_draw","text":"return value, called side effects","code":""},{"path":"https://www.slendr.net/reference/ts_draw.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Plot a graphical representation of a single tree — ts_draw","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # extract the first tree in the tree sequence and draw it tree <- ts_tree(ts, i = 1) # ts_draw accepts various optional arguments of tskit.Tree.draw_svg ts_draw(tree, time_scale = \"rank\")"},{"path":"https://www.slendr.net/reference/ts_edges.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract spatio-temporal edge annotation table from a given tree or tree\nsequence — ts_edges","title":"Extract spatio-temporal edge annotation table from a given tree or tree\nsequence — ts_edges","text":"Extract spatio-temporal edge annotation table given tree tree sequence","code":""},{"path":"https://www.slendr.net/reference/ts_edges.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract spatio-temporal edge annotation table from a given tree or tree\nsequence — ts_edges","text":"","code":"ts_edges(x)"},{"path":"https://www.slendr.net/reference/ts_edges.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract spatio-temporal edge annotation table from a given tree or tree\nsequence — ts_edges","text":"x Tree object generated ts_phylo slendr tree sequence object produced ts_load, ts_recapitate, ts_simplify, ts_mutate","code":""},{"path":"https://www.slendr.net/reference/ts_edges.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract spatio-temporal edge annotation table from a given tree or tree\nsequence — ts_edges","text":"Data frame sf type containing times nodes start-end coordinates edges across space","code":""},{"path":"https://www.slendr.net/reference/ts_edges.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract spatio-temporal edge annotation table from a given tree or tree\nsequence — ts_edges","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # extract an annotated table with (spatio-)temporal edge information ts_edges(ts) #> # A tibble: 298 × 6 #> child_node_id parent_node_id child_time parent_time child_pop parent_pop #> #> 1 0 74 70000 70040 NEA NEA #> 2 1 74 70000 70040 NEA NEA #> 3 2 55 40000 40220 NEA NEA #> 4 3 55 40000 40220 NEA NEA #> 5 4 34 0 740 AFR AFR #> 6 5 28 0 80 AFR AFR #> 7 6 26 0 20 AFR AFR #> 8 7 27 0 80 AFR AFR #> 9 8 27 0 80 AFR AFR #> 10 9 36 0 1160 AFR AFR #> # ℹ 288 more rows"},{"path":"https://www.slendr.net/reference/ts_eigenstrat.html","id":null,"dir":"Reference","previous_headings":"","what":"Convert genotypes to the EIGENSTRAT file format — ts_eigenstrat","title":"Convert genotypes to the EIGENSTRAT file format — ts_eigenstrat","text":"EIGENSTRAT data produced function can used admixr R package (https://bodkan.net/admixr/).","code":""},{"path":"https://www.slendr.net/reference/ts_eigenstrat.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Convert genotypes to the EIGENSTRAT file format — ts_eigenstrat","text":"","code":"ts_eigenstrat(ts, prefix, chrom = \"chr1\", outgroup = NULL)"},{"path":"https://www.slendr.net/reference/ts_eigenstrat.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Convert genotypes to the EIGENSTRAT file format — ts_eigenstrat","text":"ts Tree sequence object class slendr_ts prefix EIGENSTRAT trio prefix chrom name chromosome EIGENSTRAT snp file (default \"chr1\") outgroup formal, artificial outgroup added? NULL (default), outgroup added. non-NULL character name serve name outgroup ind file.","code":""},{"path":"https://www.slendr.net/reference/ts_eigenstrat.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Convert genotypes to the EIGENSTRAT file format — ts_eigenstrat","text":"Object class EIGENSTRAT created admixr package","code":""},{"path":"https://www.slendr.net/reference/ts_eigenstrat.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Convert genotypes to the EIGENSTRAT file format — ts_eigenstrat","text":"case outgroup formally specified slendr model generated tree sequence data, possible artificially create outgroup sample name specified outgroup argument, carry ancestral alleles (.e. value \"2\" geno file position snp file).","code":""},{"path":"https://www.slendr.net/reference/ts_f4ratio.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate the f2, f3, f4, and f4-ratio statistics — ts_f2","title":"Calculate the f2, f3, f4, and f4-ratio statistics — ts_f2","text":"functions present R interface corresponding f-statistics methods tskit.","code":""},{"path":"https://www.slendr.net/reference/ts_f4ratio.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate the f2, f3, f4, and f4-ratio statistics — ts_f2","text":"","code":"ts_f2( ts, A, B, mode = c(\"site\", \"branch\", \"node\"), span_normalise = TRUE, windows = NULL ) ts_f3( ts, A, B, C, mode = c(\"site\", \"branch\", \"node\"), span_normalise = TRUE, windows = NULL ) ts_f4( ts, W, X, Y, Z, mode = c(\"site\", \"branch\", \"node\"), span_normalise = TRUE, windows = NULL ) ts_f4ratio( ts, X, A, B, C, O, mode = c(\"site\", \"branch\"), span_normalise = TRUE )"},{"path":"https://www.slendr.net/reference/ts_f4ratio.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate the f2, f3, f4, and f4-ratio statistics — ts_f2","text":"ts Tree sequence object class slendr_ts mode mode calculation (\"sites\" \"branch\") span_normalise Divide result span window? Default TRUE, see tskit documentation detail. windows Coordinates breakpoints windows. first coordinate (0) last coordinate (equal ts$sequence_length) specified added automatically. W, X, Y, Z, , B, C, O Character vectors individual names (largely following nomenclature Patterson 2021, see crucial differences tskit ADMIXTOOLS Details)","code":""},{"path":"https://www.slendr.net/reference/ts_f4ratio.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate the f2, f3, f4, and f4-ratio statistics — ts_f2","text":"Data frame statistics calculated given sets individuals","code":""},{"path":"https://www.slendr.net/reference/ts_f4ratio.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Calculate the f2, f3, f4, and f4-ratio statistics — ts_f2","text":"Note order populations f3 statistic implemented tskit (https://tskit.dev/tskit/docs/stable/python-api.html#tskit.TreeSequence.f3) different might expect ADMIXTOOLS, defined Patterson 2012 (see https://academic.oup.com/genetics/article/192/3/1065/5935193 heading \"three-population test introduction f-statistics\", well ADMIXTOOLS documentation https://github.com/DReichLab/AdmixTools/blob/master/README.3PopTest#L5). Specifically, widely used notation introduced Patterson assumes population triplet f3(C; , B), C \"focal\" sample (.e., either outgroup sample tested admixture). contrast, tskit implements f3(; B, C), \"focal sample\" . Although likely confuse many ADMIXTOOLS users, slendr much choice , ts_*() functions designed broadly compatible raw tskit methods.","code":""},{"path":"https://www.slendr.net/reference/ts_f4ratio.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate the f2, f3, f4, and f4-ratio statistics — ts_f2","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk and add mutations to it ts <- ts_load(slendr_ts, model) %>% ts_mutate(mutation_rate = 1e-8, random_seed = 42) # calculate f2 for two individuals in a previously loaded tree sequence ts_f2(ts, A = \"AFR_1\", B = \"EUR_1\") #> # A tibble: 1 × 3 #> A B f2 #> #> 1 AFR_1 EUR_1 0.000024 # calculate f2 for two sets of individuals ts_f2(ts, A = c(\"AFR_1\", \"AFR_2\"), B = c(\"EUR_1\", \"EUR_3\")) #> # A tibble: 1 × 3 #> A B f2 #> #> 1 AFR_1+AFR_2 EUR_1+EUR_3 0.0000247 # calculate f3 for two individuals in a previously loaded tree sequence ts_f3(ts, A = \"EUR_1\", B = \"AFR_1\", C = \"NEA_1\") #> # A tibble: 1 × 4 #> A B C f3 #> #> 1 EUR_1 AFR_1 NEA_1 -0.000012 # calculate f3 for two sets of individuals ts_f3(ts, A = c(\"AFR_1\", \"AFR_2\", \"EUR_1\", \"EUR_2\"), B = c(\"NEA_1\", \"NEA_2\"), C = \"CH_1\") #> # A tibble: 1 × 4 #> A B C f3 #> #> 1 AFR_1+AFR_2+EUR_1+EUR_2 NEA_1+NEA_2 CH_1 0.000126 # calculate f4 for single individuals ts_f4(ts, W = \"EUR_1\", X = \"AFR_1\", Y = \"NEA_1\", Z = \"CH_1\") #> # A tibble: 1 × 5 #> W X Y Z f4 #> #> 1 EUR_1 AFR_1 NEA_1 CH_1 0.000009 # calculate f4 for sets of individuals ts_f4(ts, W = c(\"EUR_1\", \"EUR_2\"), X = c(\"AFR_1\", \"AFR_2\"), Y = \"NEA_1\", Z = \"CH_1\") #> # A tibble: 1 × 5 #> W X Y Z f4 #> #> 1 EUR_1+EUR_2 AFR_1+AFR_2 NEA_1 CH_1 0.000018 # calculate f4-ratio for a given set of target individuals X ts_f4ratio(ts, X = c(\"EUR_1\", \"EUR_2\", \"EUR_4\", \"EUR_5\"), A = \"NEA_1\", B = \"NEA_2\", C = \"AFR_1\", O = \"CH_1\") #> # A tibble: 4 × 6 #> X A B C O alpha #> #> 1 EUR_1 NEA_1 NEA_2 AFR_1 CH_1 0.0486 #> 2 EUR_2 NEA_1 NEA_2 AFR_1 CH_1 0.181 #> 3 EUR_4 NEA_1 NEA_2 AFR_1 CH_1 0.0417 #> 4 EUR_5 NEA_1 NEA_2 AFR_1 CH_1 0"},{"path":"https://www.slendr.net/reference/ts_fst.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate pairwise statistics between sets of individuals — ts_fst","title":"Calculate pairwise statistics between sets of individuals — ts_fst","text":"discussion difference \"site\", \"branch\", \"node\" options mode argument, please see tskit documentation https://tskit.dev/tskit/docs/stable/stats.html#sec-stats-mode.","code":""},{"path":"https://www.slendr.net/reference/ts_fst.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate pairwise statistics between sets of individuals — ts_fst","text":"","code":"ts_fst( ts, sample_sets, mode = c(\"site\", \"branch\", \"node\"), windows = NULL, span_normalise = TRUE )"},{"path":"https://www.slendr.net/reference/ts_fst.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate pairwise statistics between sets of individuals — ts_fst","text":"ts Tree sequence object class slendr_ts sample_sets list (optionally named list) character vectors individual names (one vector per set) mode mode calculation (\"sites\" \"branch\") windows Coordinates breakpoints windows. first coordinate (0) last coordinate (equal ts$sequence_length) specified added automatically. span_normalise Divide result span window? Default TRUE, see tskit documentation detail.","code":""},{"path":"https://www.slendr.net/reference/ts_fst.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate pairwise statistics between sets of individuals — ts_fst","text":"pairwise calculation, either single Fst value vector Fst values (one window)","code":""},{"path":"https://www.slendr.net/reference/ts_fst.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate pairwise statistics between sets of individuals — ts_fst","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) %>% ts_mutate(mutation_rate = 1e-8, random_seed = 42) # compute F_st between two sets of individuals in a given tree sequence ts ts_fst(ts, sample_sets = list(afr = c(\"AFR_1\", \"AFR_2\", \"AFR_3\"), eur = c(\"EUR_1\", \"EUR_2\"))) #> # A tibble: 1 × 3 #> x y Fst #> #> 1 afr eur 0.303"},{"path":"https://www.slendr.net/reference/ts_genotypes.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract genotype table from the tree sequence — ts_genotypes","title":"Extract genotype table from the tree sequence — ts_genotypes","text":"Extract genotype table tree sequence","code":""},{"path":"https://www.slendr.net/reference/ts_genotypes.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract genotype table from the tree sequence — ts_genotypes","text":"","code":"ts_genotypes(ts)"},{"path":"https://www.slendr.net/reference/ts_genotypes.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract genotype table from the tree sequence — ts_genotypes","text":"ts Tree sequence object class slendr_ts","code":""},{"path":"https://www.slendr.net/reference/ts_genotypes.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract genotype table from the tree sequence — ts_genotypes","text":"Data frame object class tibble containing genotypes simulated individuals columns","code":""},{"path":"https://www.slendr.net/reference/ts_genotypes.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract genotype table from the tree sequence — ts_genotypes","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk, recapitate it, simplify it, and mutate it ts <- ts_load(slendr_ts, model) %>% ts_recapitate(Ne = 10000, recombination_rate = 1e-8) %>% ts_simplify() %>% ts_mutate(mutation_rate = 1e-8) # extract the genotype matrix (this could take a long time consume lots # of memory!) gts <- ts_genotypes(ts) #> 3 multiallelic sites (0.138% out of 2173 total) detected and removed"},{"path":"https://www.slendr.net/reference/ts_ibd.html","id":null,"dir":"Reference","previous_headings":"","what":"Collect Identity-by-Descent (IBD) segments (EXPERIMENTAL) — ts_ibd","title":"Collect Identity-by-Descent (IBD) segments (EXPERIMENTAL) — ts_ibd","text":"function iterates tree sequence returns IBD tracts pairs individuals nodes","code":""},{"path":"https://www.slendr.net/reference/ts_ibd.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Collect Identity-by-Descent (IBD) segments (EXPERIMENTAL) — ts_ibd","text":"","code":"ts_ibd( ts, coordinates = FALSE, within = NULL, between = NULL, squash = FALSE, minimum_length = NULL, maximum_time = NULL, sf = TRUE )"},{"path":"https://www.slendr.net/reference/ts_ibd.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Collect Identity-by-Descent (IBD) segments (EXPERIMENTAL) — ts_ibd","text":"ts Tree sequence object class slendr_ts coordinates coordinates detected IBD tracts reported? FALSE (default), total length shared IBD segments numbers reported. TRUE, coordinates segment returned (note can massive impact memory usage). See details information. within character vector individual names integer vector node IDs indicating set nodes within look IBD segments. list lists character vectors individual names integer vectors node IDs, indicating set nodes look shared IBD segments. squash adjacent IBD segments pairs nodes squashed differ 'genealogical paths' MRCA? Default FALSE. context, see https://github.com/tskit-dev/tskit/issues/2459. option EXPERIMENTAL! minimum_length Minimum length IBD segment return results. useful reducing total amount IBD returned (see Details). maximum_time Oldest MRCA node considered IBD ancestor return IBD segment results. useful reducing total amount IBD returned. sf IBD segments spatial tree sequence analyzed, returned table spatial sf object? Default TRUE.","code":""},{"path":"https://www.slendr.net/reference/ts_ibd.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Collect Identity-by-Descent (IBD) segments (EXPERIMENTAL) — ts_ibd","text":"data frame IBD results (either coordinates IBD segment shared pair nodes, summary statistics total IBD sharing pair)","code":""},{"path":"https://www.slendr.net/reference/ts_ibd.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Collect Identity-by-Descent (IBD) segments (EXPERIMENTAL) — ts_ibd","text":"function considered experimental. full control IBD segment detection tree-sequence data, users can (perhaps, time , ) rely tskit method ibd_segments (see https://tskit.dev/tskit/docs/stable/python-api.html#tskit.TreeSequence.ibd_segments). Iternally, function leverages tskit TreeSequence method ibd_segments. However, note ts_ibd function always returns data frame IBD tracts, provide option iterate individual IBD segments shown official tskit documentation https://tskit.dev/tskit/docs/stable/ibd.html. general, R handles heavy iteration poorly, function attempt serve full wrapper ibd_segments. Unfortunately, distinction \"squashed IBD\" (many consider expected definition IBD) tskit’s IBD defined via distinct genealogical paths (see https://github.com/tskit-dev/tskit/issues/2459 discussion topic), makes meaning filtering parameter ibd_segments() method tskit minimum_length somewhat unintuitive. moment, function argument filters IBD segments tskit level, level squashed IBD segments!","code":""},{"path":"https://www.slendr.net/reference/ts_ibd.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Collect Identity-by-Descent (IBD) segments (EXPERIMENTAL) — ts_ibd","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # find IBD segments between specified Neanderthals and Europeans ts_ibd( ts, coordinates = TRUE, between = list(c(\"NEA_1\", \"NEA_2\"), c(\"EUR_1\", \"EUR_2\")), minimum_length = 40000 ) #> # A tibble: 34 × 13 #> node1 node2 length mrca node1_time node2_time tmrca left right name1 #> #> 1 0 16 52762 83 70000 0 20001 228046 280808 NEA_1 #> 2 0 16 45006 83 70000 0 20001 449167 494173 NEA_1 #> 3 0 17 52762 83 70000 0 20001 228046 280808 NEA_1 #> 4 0 18 52762 83 70000 0 20001 228046 280808 NEA_1 #> 5 0 18 45006 83 70000 0 20001 449167 494173 NEA_1 #> 6 0 19 57765 83 70000 0 20001 47447 105212 NEA_1 #> 7 0 19 47935 83 70000 0 20001 105212 153147 NEA_1 #> 8 0 19 46028 83 70000 0 20001 178539 224567 NEA_1 #> 9 0 19 58054 79 70000 0 2340 227185 285239 NEA_1 #> 10 1 16 52762 83 70000 0 20001 228046 280808 NEA_1 #> # ℹ 24 more rows #> # ℹ 3 more variables: name2 , pop1 , pop2 "},{"path":"https://www.slendr.net/reference/ts_load.html","id":null,"dir":"Reference","previous_headings":"","what":"Load a tree sequence file produced by a given model — ts_load","title":"Load a tree sequence file produced by a given model — ts_load","text":"function loads tree sequence file simulated given slendr model. Optionally, tree sequence can recapitated simplified.","code":""},{"path":"https://www.slendr.net/reference/ts_load.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Load a tree sequence file produced by a given model — ts_load","text":"","code":"ts_load(file, model = NULL)"},{"path":"https://www.slendr.net/reference/ts_load.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Load a tree sequence file produced by a given model — ts_load","text":"file path tree-sequence file (either originating slendr model standard non-slendr tree sequence). model Optional slendr_model object produced tree-sequence file. Used adding various annotation data metadata standard tskit tree-sequence object.","code":""},{"path":"https://www.slendr.net/reference/ts_load.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Load a tree sequence file produced by a given model — ts_load","text":"Tree-sequence object class slendr_ts, serves interface point Python module tskit using slendr functions ts_ prefix.","code":""},{"path":"https://www.slendr.net/reference/ts_load.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Load a tree sequence file produced by a given model — ts_load","text":"loading, recapitation simplification performed using Python module pyslim serves link tree sequences generated SLiM tskit module manipulation tree sequence data. steps modelled official pyslim tutorial documentation available : https://tskit.dev/pyslim/docs/latest/tutorial.html. recapitation simplification steps can also performed individually using functions ts_recapitate ts_simplify.","code":""},{"path":[]},{"path":"https://www.slendr.net/reference/ts_load.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Load a tree sequence file produced by a given model — ts_load","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load tree sequence generated by a given model ts <- ts_load(slendr_ts, model) # even tree sequences generated by non-slendr models can be msprime_ts <- system.file(\"extdata/models/msprime.trees\", package = \"slendr\") ts <- ts_load(msprime_ts) # load tree sequence and immediately simplify it only to sampled individuals # (note that the example tree sequence is already simplified so this operation # does not do anything in this case) ts <- ts_load(slendr_ts, model = model) %>% ts_simplify(keep_input_roots = TRUE) # load tree sequence and simplify it to a subset of sampled individuals ts_small <- ts_simplify(ts, simplify_to = c(\"CH_1\", \"NEA_1\", \"NEA_2\", \"AFR_1\", \"AFR_2\", \"EUR_1\", \"EUR_2\")) # load tree sequence, recapitate it and simplify it ts <- ts_load(slendr_ts, model) %>% ts_recapitate(recombination_rate = 1e-8, Ne = 10000, random_seed = 42) %>% ts_simplify() # load tree sequence, recapitate it, simplify it and overlay neutral mutations ts <- ts_load(slendr_ts, model) %>% ts_recapitate(recombination_rate = 1e-8, Ne = 10000, random_seed = 42) %>% ts_simplify() %>% ts_mutate(mutation_rate = 1e-8) ts #> ╔═════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═════════╣ #> ║Trees │ 70║ #> ╟───────────────┼─────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼─────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼─────────╢ #> ║Sample Nodes │ 26║ #> ╟───────────────┼─────────╢ #> ║Total Size │205.3 KiB║ #> ╚═══════════════╧═════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 297│ 9.3 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 72│ 8.8 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │2206│80.9 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 85│ 3.8 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 6│ 2.7 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 6│41.0 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Sites │2201│53.8 KiB│ No║ #> ╚═══════════╧════╧════════╧════════════╝ #>"},{"path":"https://www.slendr.net/reference/ts_metadata.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract list with tree sequence metadata saved by SLiM — ts_metadata","title":"Extract list with tree sequence metadata saved by SLiM — ts_metadata","text":"Extract list tree sequence metadata saved SLiM","code":""},{"path":"https://www.slendr.net/reference/ts_metadata.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract list with tree sequence metadata saved by SLiM — ts_metadata","text":"","code":"ts_metadata(ts)"},{"path":"https://www.slendr.net/reference/ts_metadata.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract list with tree sequence metadata saved by SLiM — ts_metadata","text":"ts Tree sequence object class slendr_ts","code":""},{"path":"https://www.slendr.net/reference/ts_metadata.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract list with tree sequence metadata saved by SLiM — ts_metadata","text":"List metadata fields extracted tree-sequence object","code":""},{"path":"https://www.slendr.net/reference/ts_metadata.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract list with tree sequence metadata saved by SLiM — ts_metadata","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # extract the list of metadata information from the tree sequence ts_metadata(ts) #> $version #> [1] \"slendr_0.8.1.9000\" #> #> $description #> [1] \"\" #> #> $sampling #> # A tibble: 13 × 3 #> name time pop #> #> 1 NEA_1 70000 NEA #> 2 NEA_2 40000 NEA #> 3 AFR_1 0 AFR #> 4 AFR_2 0 AFR #> 5 AFR_3 0 AFR #> 6 AFR_4 0 AFR #> 7 AFR_5 0 AFR #> 8 CH_1 0 CH #> 9 EUR_1 0 EUR #> 10 EUR_2 0 EUR #> 11 EUR_3 0 EUR #> 12 EUR_4 0 EUR #> 13 EUR_5 0 EUR #> #> $sample_names #> [1] \"NEA_1\" \"NEA_2\" \"AFR_1\" \"AFR_2\" \"AFR_3\" \"AFR_4\" \"AFR_5\" \"CH_1\" \"EUR_1\" #> [10] \"EUR_2\" \"EUR_3\" \"EUR_4\" \"EUR_5\" #> #> $sample_ids #> NULL #> #> $map #> NULL #> #> $arguments #> $arguments$BURNIN_LENGTH #> [1] 0 #> #> $arguments$MAX_ATTEMPTS #> [1] 1 #> #> $arguments$RECOMB_RATE #> [1] 1e-08 #> #> $arguments$SEED #> [1] 314159 #> #> $arguments$SEQUENCE_LENGTH #> [1] 500000 #> #> $arguments$SIMULATION_LENGTH #> [1] 216667 #> #>"},{"path":"https://www.slendr.net/reference/ts_mutate.html","id":null,"dir":"Reference","previous_headings":"","what":"Add mutations to the given tree sequence — ts_mutate","title":"Add mutations to the given tree sequence — ts_mutate","text":"Add mutations given tree sequence","code":""},{"path":"https://www.slendr.net/reference/ts_mutate.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Add mutations to the given tree sequence — ts_mutate","text":"","code":"ts_mutate( ts, mutation_rate, random_seed = NULL, keep_existing = TRUE, mut_type = NULL )"},{"path":"https://www.slendr.net/reference/ts_mutate.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Add mutations to the given tree sequence — ts_mutate","text":"ts Tree sequence object class slendr_ts mutation_rate Mutation rate used msprime simulate mutations random_seed Random seed passed msprime's mutate method (NULL, seed generated 0 maximum integer number available) keep_existing Keep existing mutations? mut_type Assign SLiM mutation type neutral mutations? NULL (default), special mutation type used. integer number given, mutations SLiM mutation type integer identifier created.","code":""},{"path":"https://www.slendr.net/reference/ts_mutate.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Add mutations to the given tree sequence — ts_mutate","text":"Tree-sequence object class slendr_ts, serves interface point Python module tskit using slendr functions ts_ prefix.","code":""},{"path":[]},{"path":"https://www.slendr.net/reference/ts_mutate.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Add mutations to the given tree sequence — ts_mutate","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) ts <- ts_load(slendr_ts, model) ts_mutate <- ts_mutate(ts, mutation_rate = 1e-8, random_seed = 42) ts_mutate #> ╔═════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═════════╣ #> ║Trees │ 70║ #> ╟───────────────┼─────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼─────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼─────────╢ #> ║Sample Nodes │ 26║ #> ╟───────────────┼─────────╢ #> ║Total Size │204.8 KiB║ #> ╚═══════════════╧═════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 298│ 9.3 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 73│ 8.9 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │2246│82.3 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 86│ 3.9 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 5│ 2.6 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 4│38.0 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Sites │2240│54.7 KiB│ No║ #> ╚═══════════╧════╧════════╧════════════╝ #>"},{"path":"https://www.slendr.net/reference/ts_names.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract names of individuals in a tree sequence — ts_names","title":"Extract names of individuals in a tree sequence — ts_names","text":"Extract names individuals tree sequence","code":""},{"path":"https://www.slendr.net/reference/ts_names.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract names of individuals in a tree sequence — ts_names","text":"","code":"ts_names(ts, split = NULL)"},{"path":"https://www.slendr.net/reference/ts_names.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract names of individuals in a tree sequence — ts_names","text":"ts Tree sequence object class slendr_ts split sample names tree sequence split column (population time column)? Default NULL names samples returned single character vector. set \"pop\" \"time\", list character vectors returned, one vector unique \"pop\" \"time\" grouping.","code":""},{"path":"https://www.slendr.net/reference/ts_names.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract names of individuals in a tree sequence — ts_names","text":"vector character sample names. split specified, list vectors returned, one element list per population sampling time.","code":""},{"path":"https://www.slendr.net/reference/ts_nodes.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract combined annotated table of individuals and nodes — ts_nodes","title":"Extract combined annotated table of individuals and nodes — ts_nodes","text":"function combines information table individuals table nodes single data frame can used downstream analyses.","code":""},{"path":"https://www.slendr.net/reference/ts_nodes.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract combined annotated table of individuals and nodes — ts_nodes","text":"","code":"ts_nodes(x, sf = TRUE)"},{"path":"https://www.slendr.net/reference/ts_nodes.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract combined annotated table of individuals and nodes — ts_nodes","text":"x Tree sequence object class slendr_ts phylo object extracted ts_phylo sf spatial data returned sf format? FALSE, spatial geometries returned simply x y columns, instead standard POINT data type.","code":""},{"path":"https://www.slendr.net/reference/ts_nodes.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract combined annotated table of individuals and nodes — ts_nodes","text":"Data frame processed information tree sequence object. model generated data spatial, result returned spatial object class sf.","code":""},{"path":"https://www.slendr.net/reference/ts_nodes.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Extract combined annotated table of individuals and nodes — ts_nodes","text":"source data (tables individuals nodes recorded tree sequence generated SLiM) combined single data frame. model generated data spatial, coordinates nodes (pixel-based default SLiM spatial simulations occur raster), coordinates automatically converted explicit spatial object sf class unless spatial = FALSE. See https://r-spatial.github.io/sf/ extensive introduction sf package ways spatial data can processed, analysed, visualised.","code":""},{"path":[]},{"path":"https://www.slendr.net/reference/ts_nodes.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract combined annotated table of individuals and nodes — ts_nodes","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # extract an annotated table with (spatio-)temporal node information ts_nodes(ts) #> # A tibble: 86 × 12 #> name pop node_id time time_tskit sampled remembered retained alive #> #> 1 NEA_1 NEA 0 70000 2334 TRUE TRUE TRUE FALSE #> 2 NEA_1 NEA 1 70000 2334 TRUE TRUE TRUE FALSE #> 3 NEA_2 NEA 2 40000 1334 TRUE TRUE TRUE FALSE #> 4 NEA_2 NEA 3 40000 1334 TRUE TRUE TRUE FALSE #> 5 AFR_1 AFR 4 0 0 TRUE TRUE TRUE TRUE #> 6 AFR_1 AFR 5 0 0 TRUE TRUE TRUE TRUE #> 7 AFR_2 AFR 6 0 0 TRUE TRUE TRUE TRUE #> 8 AFR_2 AFR 7 0 0 TRUE TRUE TRUE TRUE #> 9 AFR_3 AFR 8 0 0 TRUE TRUE TRUE TRUE #> 10 AFR_3 AFR 9 0 0 TRUE TRUE TRUE TRUE #> # ℹ 76 more rows #> # ℹ 3 more variables: pedigree_id , pop_id , ind_id "},{"path":"https://www.slendr.net/reference/ts_phylo.html","id":null,"dir":"Reference","previous_headings":"","what":"Convert a tree in the tree sequence to an object of the class phylo — ts_phylo","title":"Convert a tree in the tree sequence to an object of the class phylo — ts_phylo","text":"Convert tree tree sequence object class phylo","code":""},{"path":"https://www.slendr.net/reference/ts_phylo.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Convert a tree in the tree sequence to an object of the class phylo — ts_phylo","text":"","code":"ts_phylo( ts, i, mode = c(\"index\", \"position\"), labels = c(\"tskit\", \"pop\"), quiet = FALSE )"},{"path":"https://www.slendr.net/reference/ts_phylo.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Convert a tree in the tree sequence to an object of the class phylo — ts_phylo","text":"ts Tree sequence object class slendr_ts Position tree tree sequence. mode = \"index\", -th tree returned (zero-based indexing tskit), mode = \"position\", tree covering -th base simulated genome returned (, tskit's indexing). mode argument interpreted? Either \"index\" -th tree sequence genealogies, \"position\" along simulated genome. labels stored node labels final phylo object? Options either population name tskit integer node ID (different thing phylo class node integer index). quiet ape's internal phylo validity test printed ?","code":""},{"path":"https://www.slendr.net/reference/ts_phylo.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Convert a tree in the tree sequence to an object of the class phylo — ts_phylo","text":"Standard phylogenetic tree object implemented R package ape","code":""},{"path":"https://www.slendr.net/reference/ts_phylo.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Convert a tree in the tree sequence to an object of the class phylo — ts_phylo","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) %>% ts_recapitate(Ne = 10000, recombination_rate = 1e-8) %>% ts_simplify() # extract the 1st tree from a given tree sequence, return ape object tree <- ts_phylo(ts, i = 1, mode = \"index\", quiet = TRUE) tree #> #> Phylogenetic tree with 26 tips and 24 internal nodes. #> #> Tip labels: #> 25 (EUR_5), 24 (EUR_5), 23 (EUR_4), 22 (EUR_4), 21 (EUR_3), 20 (EUR_3), ... #> Node labels: #> 84, 28, 27, 30, 31, 32, ... #> #> Rooted; includes branch lengths. # extract the tree at a 42th basepair in the given tree sequence tree <- ts_phylo(ts, i = 42, mode = \"position\", quiet = TRUE) # because the tree is a standard ape phylo object, we can plot it easily plot(tree, use.edge.length = FALSE) ape::nodelabels()"},{"path":"https://www.slendr.net/reference/ts_recapitate.html","id":null,"dir":"Reference","previous_headings":"","what":"Recapitate the tree sequence — ts_recapitate","title":"Recapitate the tree sequence — ts_recapitate","text":"Recapitate tree sequence","code":""},{"path":"https://www.slendr.net/reference/ts_recapitate.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Recapitate the tree sequence — ts_recapitate","text":"","code":"ts_recapitate( ts, recombination_rate, Ne = NULL, demography = NULL, random_seed = NULL )"},{"path":"https://www.slendr.net/reference/ts_recapitate.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Recapitate the tree sequence — ts_recapitate","text":"ts Tree sequence object loaded ts_load recombination_rate constant value recombination rate Ne Effective population size recapitation process demography Ancestral demography passed internally msprime.sim_ancestry() (see msprime's documentation mode detail) random_seed Random seed passed pyslim's recapitate method (NULL, seed generated 0 maximum integer number available)","code":""},{"path":"https://www.slendr.net/reference/ts_recapitate.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Recapitate the tree sequence — ts_recapitate","text":"Tree-sequence object class slendr_ts, serves interface point Python module tskit using slendr functions ts_ prefix.","code":""},{"path":[]},{"path":"https://www.slendr.net/reference/ts_recapitate.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Recapitate the tree sequence — ts_recapitate","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) ts <- ts_load(slendr_ts, model) %>% ts_recapitate(recombination_rate = 1e-8, Ne = 10000, random_seed = 42) ts #> ╔════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤════════╣ #> ║Trees │ 70║ #> ╟───────────────┼────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼────────╢ #> ║Sample Nodes │ 26║ #> ╟───────────────┼────────╢ #> ║Total Size │70.8 KiB║ #> ╚═══════════════╧════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 298│ 9.3 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 73│ 8.9 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 86│ 3.9 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 6│ 2.7 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 4│39.8 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Sites │ 0│16 Bytes│ No║ #> ╚═══════════╧════╧════════╧════════════╝ #>"},{"path":"https://www.slendr.net/reference/ts_samples.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract names and times of individuals of interest in the current tree sequence\n(either all sampled individuals or those that the user simplified to) — ts_samples","title":"Extract names and times of individuals of interest in the current tree sequence\n(either all sampled individuals or those that the user simplified to) — ts_samples","text":"Extract names times individuals interest current tree sequence (either sampled individuals user simplified )","code":""},{"path":"https://www.slendr.net/reference/ts_samples.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract names and times of individuals of interest in the current tree sequence\n(either all sampled individuals or those that the user simplified to) — ts_samples","text":"","code":"ts_samples(ts)"},{"path":"https://www.slendr.net/reference/ts_samples.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract names and times of individuals of interest in the current tree sequence\n(either all sampled individuals or those that the user simplified to) — ts_samples","text":"ts Tree sequence object class slendr_ts","code":""},{"path":"https://www.slendr.net/reference/ts_samples.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract names and times of individuals of interest in the current tree sequence\n(either all sampled individuals or those that the user simplified to) — ts_samples","text":"Table individuals scheduled sampling across space time","code":""},{"path":"https://www.slendr.net/reference/ts_samples.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract names and times of individuals of interest in the current tree sequence\n(either all sampled individuals or those that the user simplified to) — ts_samples","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # extract the table of individuals scheduled for simulation and sampling ts_samples(ts) #> # A tibble: 13 × 3 #> name time pop #> #> 1 NEA_1 70000 NEA #> 2 NEA_2 40000 NEA #> 3 AFR_1 0 AFR #> 4 AFR_2 0 AFR #> 5 AFR_3 0 AFR #> 6 AFR_4 0 AFR #> 7 AFR_5 0 AFR #> 8 CH_1 0 CH #> 9 EUR_1 0 EUR #> 10 EUR_2 0 EUR #> 11 EUR_3 0 EUR #> 12 EUR_4 0 EUR #> 13 EUR_5 0 EUR"},{"path":"https://www.slendr.net/reference/ts_save.html","id":null,"dir":"Reference","previous_headings":"","what":"Save a tree sequence to a file — ts_save","title":"Save a tree sequence to a file — ts_save","text":"Save tree sequence file","code":""},{"path":"https://www.slendr.net/reference/ts_save.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Save a tree sequence to a file — ts_save","text":"","code":"ts_save(ts, file)"},{"path":"https://www.slendr.net/reference/ts_save.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Save a tree sequence to a file — ts_save","text":"ts Tree sequence object loaded ts_load file File tree sequence saved","code":""},{"path":"https://www.slendr.net/reference/ts_save.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Save a tree sequence to a file — ts_save","text":"return value, called side effects","code":""},{"path":"https://www.slendr.net/reference/ts_save.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Save a tree sequence to a file — ts_save","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree sequence ts <- ts_load(slendr_ts, model) # save the tree-sequence object to a different location another_file <- paste(tempfile(), \".trees\") ts_save(ts, another_file)"},{"path":"https://www.slendr.net/reference/ts_segregating.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate the density of segregating sites for the given sets of individuals — ts_segregating","title":"Calculate the density of segregating sites for the given sets of individuals — ts_segregating","text":"Calculate density segregating sites given sets individuals","code":""},{"path":"https://www.slendr.net/reference/ts_segregating.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate the density of segregating sites for the given sets of individuals — ts_segregating","text":"","code":"ts_segregating( ts, sample_sets, mode = c(\"site\", \"branch\", \"node\"), windows = NULL, span_normalise = FALSE )"},{"path":"https://www.slendr.net/reference/ts_segregating.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate the density of segregating sites for the given sets of individuals — ts_segregating","text":"ts Tree sequence object class slendr_ts sample_sets list (optionally named list) character vectors individual names (one vector per set). simple vector provided, interpreted .list(sample_sets), meaning given statistic calculated individual separately. mode mode calculation (\"sites\" \"branch\") windows Coordinates breakpoints windows. first coordinate (0) last coordinate (equal ts$sequence_length) added automatically) span_normalise Divide result span window? Default TRUE, see tskit documentation detail.","code":""},{"path":"https://www.slendr.net/reference/ts_segregating.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate the density of segregating sites for the given sets of individuals — ts_segregating","text":"set individuals either single diversity value vector diversity values (one window)","code":""},{"path":"https://www.slendr.net/reference/ts_segregating.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate the density of segregating sites for the given sets of individuals — ts_segregating","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) %>% ts_mutate(mutation_rate = 1e-8, random_seed = 42) # collect sampled individuals from all populations in a list sample_sets <- ts_samples(ts) %>% split(., .$pop) %>% lapply(function(pop) pop$name) ts_segregating(ts, sample_sets) #> # A tibble: 4 × 2 #> set segsites #> #> 1 AFR 1 #> 2 CH 0 #> 3 EUR 122 #> 4 NEA 7"},{"path":"https://www.slendr.net/reference/ts_simplify.html","id":null,"dir":"Reference","previous_headings":"","what":"Simplify the tree sequence down to a given set of individuals — ts_simplify","title":"Simplify the tree sequence down to a given set of individuals — ts_simplify","text":"function convenience wrapper around simplify method implemented tskit, designed work tree sequence data simulated SLiM using slendr R package.","code":""},{"path":"https://www.slendr.net/reference/ts_simplify.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Simplify the tree sequence down to a given set of individuals — ts_simplify","text":"","code":"ts_simplify( ts, simplify_to = NULL, keep_input_roots = FALSE, keep_unary = FALSE, keep_unary_in_individuals = FALSE, filter_nodes = TRUE )"},{"path":"https://www.slendr.net/reference/ts_simplify.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Simplify the tree sequence down to a given set of individuals — ts_simplify","text":"ts Tree sequence object class slendr_ts simplify_to character vector individual names. NULL, explicitly remembered individuals (.e. specified via schedule_sampling function left tree sequence simplification. keep_input_roots history ancestral MRCA samples retained tree sequence? Default FALSE. keep_unary unary nodes preserved simplification? Default FALSE. keep_unary_in_individuals unary nodes preserved simplification associated individual recorded table individuals? Default FALSE. set TRUE keep_unary also TRUE filter_nodes nodes reindexed simplification? Default TRUE. See tskit's documentation Python method simplify()","code":""},{"path":"https://www.slendr.net/reference/ts_simplify.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Simplify the tree sequence down to a given set of individuals — ts_simplify","text":"Tree-sequence object class slendr_ts, serves interface point Python module tskit using slendr functions ts_ prefix.","code":""},{"path":"https://www.slendr.net/reference/ts_simplify.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Simplify the tree sequence down to a given set of individuals — ts_simplify","text":"simplification process used remove redundant information tree sequence retains information necessary describe genealogical history set samples. information simplification works pyslim tskit, see official documentation https://tskit.dev/tskit/docs/stable/python-api.html#tskit.TreeSequence.simplify https://tskit.dev/pyslim/docs/latest/tutorial.html#simplification. clear description difference remembering retaining use techniques implement historical individuals (.e. ancient DNA samples) pyslim documentation https://tskit.dev/pyslim/docs/latest/tutorial.html#historical-individuals.","code":""},{"path":[]},{"path":"https://www.slendr.net/reference/ts_simplify.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Simplify the tree sequence down to a given set of individuals — ts_simplify","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) ts <- ts_load(slendr_ts, model) ts #> ╔════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤════════╣ #> ║Trees │ 70║ #> ╟───────────────┼────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼────────╢ #> ║Sample Nodes │ 26║ #> ╟───────────────┼────────╢ #> ║Total Size │68.2 KiB║ #> ╚═══════════════╧════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 298│ 9.3 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 73│ 8.9 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 86│ 3.9 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 5│ 2.6 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 3│37.3 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Sites │ 0│16 Bytes│ No║ #> ╚═══════════╧════╧════════╧════════════╝ #> # simplify tree sequence to sampled individuals ts_simplified <- ts_simplify(ts) # simplify to a subset of sampled individuals ts_small <- ts_simplify(ts, simplify_to = c(\"CH_1\", \"NEA_1\", \"NEA_2\", \"AFR_1\", \"AFR_2\", \"EUR_1\", \"EUR_2\")) ts_small #> ╔════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤════════╣ #> ║Trees │ 28║ #> ╟───────────────┼────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼────────╢ #> ║Sample Nodes │ 14║ #> ╟───────────────┼────────╢ #> ║Total Size │56.0 KiB║ #> ╚═══════════════╧════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 118│ 3.7 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 32│ 4.9 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 39│ 2.1 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 5│ 2.6 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 4│37.8 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Sites │ 0│16 Bytes│ No║ #> ╚═══════════╧════╧════════╧════════════╝ #>"},{"path":"https://www.slendr.net/reference/ts_table.html","id":null,"dir":"Reference","previous_headings":"","what":"Get the table of individuals/nodes/edges/mutations from the tree sequence — ts_table","title":"Get the table of individuals/nodes/edges/mutations from the tree sequence — ts_table","text":"function extracts data given tree sequence table. times converted model-specific time units tskit's \"generations backwards\" time direction.","code":""},{"path":"https://www.slendr.net/reference/ts_table.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Get the table of individuals/nodes/edges/mutations from the tree sequence — ts_table","text":"","code":"ts_table(ts, table = c(\"individuals\", \"edges\", \"nodes\", \"mutations\"))"},{"path":"https://www.slendr.net/reference/ts_table.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Get the table of individuals/nodes/edges/mutations from the tree sequence — ts_table","text":"ts Tree sequence object class slendr_ts table tree sequence table return","code":""},{"path":"https://www.slendr.net/reference/ts_table.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Get the table of individuals/nodes/edges/mutations from the tree sequence — ts_table","text":"Data frame information give tree-sequence table (can either table individuals, edges, nodes, mutations).","code":""},{"path":"https://www.slendr.net/reference/ts_table.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Get the table of individuals/nodes/edges/mutations from the tree sequence — ts_table","text":"processing analyses, output function ts_nodes might useful, merges information node individual tables one table annotates useful information model configuration data.","code":""},{"path":[]},{"path":"https://www.slendr.net/reference/ts_table.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Get the table of individuals/nodes/edges/mutations from the tree sequence — ts_table","text":"","code":"# load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk and add mutations to it ts <- ts_load(slendr_ts, model) %>% ts_mutate(mutation_rate = 1e-8, random_seed = 42) # get the 'raw' tskit table of individuals ts_table(ts, \"individuals\") #> # A tibble: 73 × 9 #> ind_id time pedigree_id pop_id alive remembered retained sampled time_tskit #> #> 1 0 -10 16023346 0 TRUE TRUE TRUE TRUE 0 #> 2 1 -10 16023350 1 TRUE TRUE TRUE TRUE 0 #> 3 2 -10 16023352 1 TRUE TRUE TRUE TRUE 0 #> 4 3 -10 16023353 1 TRUE TRUE TRUE TRUE 0 #> 5 4 -10 16023355 1 TRUE TRUE TRUE TRUE 0 #> 6 5 -10 16023359 1 TRUE TRUE TRUE TRUE 0 #> 7 6 -10 16024625 3 TRUE TRUE TRUE TRUE 0 #> 8 7 -10 16025081 3 TRUE TRUE TRUE TRUE 0 #> 9 8 -10 16025520 3 TRUE TRUE TRUE TRUE 0 #> 10 9 -10 16026684 3 TRUE TRUE TRUE TRUE 0 #> # ℹ 63 more rows # get the 'raw' tskit table of edges ts_table(ts, \"edges\") #> # A tibble: 298 × 5 #> id child parent left right #> #> 1 0 6 26 0 500000 #> 2 1 13 26 0 500000 #> 3 2 7 27 0 500000 #> 4 3 8 27 0 500000 #> 5 4 12 27 0 500000 #> 6 5 5 28 0 500000 #> 7 6 10 28 0 500000 #> 8 7 11 29 306056 500000 #> 9 8 26 29 306056 500000 #> 10 9 27 30 0 500000 #> # ℹ 288 more rows # get the 'raw' tskit table of nodes ts_table(ts, \"nodes\") #> # A tibble: 86 × 5 #> node_id ind_id pop_id time time_tskit #> #> 1 0 25 2 70010 2334 #> 2 1 25 2 70010 2334 #> 3 2 43 2 40010 1334 #> 4 3 43 2 40010 1334 #> 5 4 1 1 -10 0 #> 6 5 1 1 -10 0 #> 7 6 2 1 -10 0 #> 8 7 2 1 -10 0 #> 9 8 3 1 -10 0 #> 10 9 3 1 -10 0 #> # ℹ 76 more rows # get the 'raw' tskit table of mutations ts_table(ts, \"mutations\") #> # A tibble: 2,246 × 5 #> id site node time time_tskit #> #> 1 0 0 83 3626483. 120883. #> 2 1 1 83 1766659. 58889. #> 3 2 2 83 2476958. 82566. #> 4 3 3 83 4356462. 145216. #> 5 4 4 83 876159. 29206. #> 6 5 5 83 3848814. 128294. #> 7 6 6 83 2554081. 85136. #> 8 7 7 83 976093. 32537. #> 9 8 8 32 3622571. 120753. #> 10 9 9 32 104626. 3488. #> # ℹ 2,236 more rows"},{"path":"https://www.slendr.net/reference/ts_tajima.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate Tajima's D for given sets of individuals — ts_tajima","title":"Calculate Tajima's D for given sets of individuals — ts_tajima","text":"discussion difference \"site\" \"branch\" options mode argument, please see tskit documentation https://tskit.dev/tskit/docs/stable/stats.html#sec-stats-mode","code":""},{"path":"https://www.slendr.net/reference/ts_tajima.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate Tajima's D for given sets of individuals — ts_tajima","text":"","code":"ts_tajima(ts, sample_sets, mode = c(\"site\", \"branch\", \"node\"), windows = NULL)"},{"path":"https://www.slendr.net/reference/ts_tajima.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate Tajima's D for given sets of individuals — ts_tajima","text":"ts Tree sequence object class slendr_ts sample_sets list (optionally named list) character vectors individual names (one vector per set). simple vector provided, interpreted .list(sample_sets), meaning given statistic calculated individual separately. mode mode calculation (\"sites\" \"branch\") windows Coordinates breakpoints windows. first coordinate (0) last coordinate (equal ts$sequence_length) added automatically)","code":""},{"path":"https://www.slendr.net/reference/ts_tajima.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate Tajima's D for given sets of individuals — ts_tajima","text":"set individuals either single Tajima's D value vector Tajima's D values (one window)","code":""},{"path":"https://www.slendr.net/reference/ts_tajima.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate Tajima's D for given sets of individuals — ts_tajima","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) %>% ts_mutate(mutation_rate = 1e-8, random_seed = 42) # calculate Tajima's D for given sets of individuals in a tree sequence ts ts_tajima(ts, list(eur = c(\"EUR_1\", \"EUR_2\", \"EUR_3\", \"EUR_4\", \"EUR_5\"), nea = c(\"NEA_1\", \"NEA_2\"))) #> # A tibble: 2 × 2 #> set D #> #> 1 eur -1.16 #> 2 nea 2.18"},{"path":"https://www.slendr.net/reference/ts_tracts.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract ancestry tracts from a tree sequence (EXPERIMENTAL) — ts_tracts","title":"Extract ancestry tracts from a tree sequence (EXPERIMENTAL) — ts_tracts","text":"Extract data frame coordinates ancestry tracts given tree sequence.","code":""},{"path":"https://www.slendr.net/reference/ts_tracts.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract ancestry tracts from a tree sequence (EXPERIMENTAL) — ts_tracts","text":"","code":"ts_tracts(ts, census, squashed = TRUE, source = NULL, target = NULL)"},{"path":"https://www.slendr.net/reference/ts_tracts.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract ancestry tracts from a tree sequence (EXPERIMENTAL) — ts_tracts","text":"ts Tree sequence object class slendr_ts census Census time. See documentation linked Details information. slendr-specific tree sequence provided ts, census time expected given slendr model-specific time units, must correspond gene-flow event encoded model. squashed ancestry tracts squashed (.e., continuous tracts can traced different ancestral nodes merged)? Default TRUE. FALSE, effectively continuous ancestry tracts split individual segments, assigned specific ancestral node ID (recorded column ancestor_id). source source population extract tracts ? NULL (default), ancestry tracts populations contributing gene flow census time reported. Otherwise, ancestry tracts specified source populations extracted. Note option ignored non-slendr tree sequences! target Similar purpose source , except filters tracts discovered target population(s)","code":""},{"path":"https://www.slendr.net/reference/ts_tracts.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract ancestry tracts from a tree sequence (EXPERIMENTAL) — ts_tracts","text":"data frame containing coordinates ancestry tracts","code":""},{"path":"https://www.slendr.net/reference/ts_tracts.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Extract ancestry tracts from a tree sequence (EXPERIMENTAL) — ts_tracts","text":"function implements R-friendly interface algorithm extracting ancestry tracts provided Python module tspop https://tspop.readthedocs.io/en/latest/ developed Georgia Tsambos. Please make sure cite paper describes algorithm detail: https://academic.oup.com/bioinformaticsadvances/article/3/1/vbad163/7429395. technical details, see also tutorial : https://tspop.readthedocs.io/en/latest/basicusage.html. general, using function slendr-generated tree sequence, please aware output changes slightly get running pure tspop.get_pop_ancestry() Python. First, ts_tracts() populates output data frame additional metadata (names individuals populations). Additionally, slendr models, specifically designed return ancestry tracts originating ancestral population contributed ancestry gene-flow event started specific time (.e., scheduled model via gene_flow()) function. return every single ancestry tracts present tree sequence every single sample node (every single potential ancestry population) tspop.get_pop_ancestry() Python method. said, run tree sequence originate slendr simulation, behavior ts_tracts() identical underlying tspop.get_pop_ancestry(). current version slendr, ts_tracts() works slendr/msprime sequences slendr/SLiM tree sequences. Support slendr-generated SLiM tree sequences development. Tracts tree sequences originating non-slendr msprime SLiM simulations restricted way , mentioned previous paragraph, ts_tracts() situation effectively reduces standard tspop.get_pop_ancestry() call.","code":""},{"path":"https://www.slendr.net/reference/ts_tracts.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract ancestry tracts from a tree sequence (EXPERIMENTAL) — ts_tracts","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env(quiet = TRUE) # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_msprime.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(file = slendr_ts, model = model) # extract Neanderthal ancestry tracts (i.e. those corresponding to the # census event at the gene-flow time at 55000 kya as scheduled by # the simulation which produced the tree sequence) nea_tracts <- ts_tracts(ts, census = 55000, source = \"NEA\") #> #> PopAncestry summary #> Number of ancestral populations: \t4 #> Number of sample chromosomes: \t\t26 #> Number of ancestors: \t\t\t763 #> Total length of genomes: \t\t130000000.000000 #> Ancestral coverage: \t\t\t120000000.000000 #> nea_tracts #> # A tibble: 42 × 8 #> name node_id pop source_pop left right length source_pop_id #> #> 1 EUR_1 16 EUR NEA 44049 101210 57161 2 #> 2 EUR_1 16 EUR NEA 244041 280650 36609 2 #> 3 EUR_1 16 EUR NEA 4636048 4736790 100742 2 #> 4 EUR_1 16 EUR NEA 4756344 4850072 93728 2 #> 5 EUR_1 17 EUR NEA 106906 268610 161704 2 #> 6 EUR_1 17 EUR NEA 1420672 1432252 11580 2 #> 7 EUR_1 17 EUR NEA 3438894 3511366 72472 2 #> 8 EUR_1 17 EUR NEA 3624298 3682434 58136 2 #> 9 EUR_1 17 EUR NEA 4139989 4239794 99805 2 #> 10 EUR_1 17 EUR NEA 4318138 4351616 33478 2 #> # ℹ 32 more rows"},{"path":"https://www.slendr.net/reference/ts_tree.html","id":null,"dir":"Reference","previous_headings":"","what":"Get a tree from a given tree sequence — ts_tree","title":"Get a tree from a given tree sequence — ts_tree","text":"information optional keyword arguments see tskit documentation: https://tskit.dev/tskit/docs/stable/python-api.html#-treesequence-class","code":""},{"path":"https://www.slendr.net/reference/ts_tree.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Get a tree from a given tree sequence — ts_tree","text":"","code":"ts_tree(ts, i, mode = c(\"index\", \"position\"), ...)"},{"path":"https://www.slendr.net/reference/ts_tree.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Get a tree from a given tree sequence — ts_tree","text":"ts Tree sequence object class slendr_ts Position tree tree sequence. mode = \"index\", -th tree returned (zero-based indexing tskit), mode = \"position\", tree covering -th base simulated genome returned (, tskit's indexing). mode argument interpreted? Either \"index\" -th tree sequence genealogies, \"position\" along simulated genome. ... Additional keyword arguments accepted tskit.TreeSequence.tskit.TreeSequence.at_index methods","code":""},{"path":"https://www.slendr.net/reference/ts_tree.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Get a tree from a given tree sequence — ts_tree","text":"Python-reticulate-based object class tskit.trees.Tree","code":""},{"path":"https://www.slendr.net/reference/ts_tree.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Get a tree from a given tree sequence — ts_tree","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # extract the zero-th tree in the tree sequence tree <- ts_tree(ts, i = 0) # extract the tree at a position in the tree sequence tree <- ts_tree(ts, i = 100000, mode = \"position\")"},{"path":"https://www.slendr.net/reference/ts_vcf.html","id":null,"dir":"Reference","previous_headings":"","what":"Save genotypes from the tree sequence as a VCF file — ts_vcf","title":"Save genotypes from the tree sequence as a VCF file — ts_vcf","text":"Save genotypes tree sequence VCF file","code":""},{"path":"https://www.slendr.net/reference/ts_vcf.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Save genotypes from the tree sequence as a VCF file — ts_vcf","text":"","code":"ts_vcf(ts, path, chrom = NULL, individuals = NULL)"},{"path":"https://www.slendr.net/reference/ts_vcf.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Save genotypes from the tree sequence as a VCF file — ts_vcf","text":"ts Tree sequence object class slendr_ts path Path VCF file chrom Chromosome name written CHROM column VCF individuals character vector individuals tree sequence. missing, individuals present tree sequence saved.","code":""},{"path":"https://www.slendr.net/reference/ts_vcf.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Save genotypes from the tree sequence as a VCF file — ts_vcf","text":"return value, called side effects","code":""},{"path":"https://www.slendr.net/reference/world.html","id":null,"dir":"Reference","previous_headings":"","what":"Define a world map for all spatial operations — world","title":"Define a world map for all spatial operations — world","text":"Defines either abstract geographic landscape (blank containing user-defined landscape) using real Earth cartographic data Natural Earth project (https://www.naturalearthdata.com).","code":""},{"path":"https://www.slendr.net/reference/world.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Define a world map for all spatial operations — world","text":"","code":"world( xrange, yrange, landscape = \"naturalearth\", crs = NULL, scale = c(\"small\", \"medium\", \"large\") )"},{"path":"https://www.slendr.net/reference/world.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Define a world map for all spatial operations — world","text":"xrange Two-dimensional vector specifying minimum maximum horizontal range (\"longitude\" using real Earth cartographic data) yrange Two-dimensional vector specifying minimum maximum vertical range (\"latitude\" using real Earth cartographic data) landscape Either \"blank\" (blank abstract geography), \"naturalearth\" (real Earth geography) object class sf defining abstract geographic features world crs EPSG code coordinate reference system use spatial operations. CRS assumed default (NULL), implying abstract landscape tied real-world geographic region (landscape = \"blank\" landscape custom-defined geographic landscape), implying WGS-84 (EPSG 4326) coordinate system real Earth landscape defined (landscape = \"naturalearth\"). scale Natural Earth geographic data used (.e. landscape = \"naturalearth\"), parameter determines resolution data used. value \"small\" corresponds 1:110m data provided package, values \"medium\" \"large\" correspond 1:50m 1:10m respectively downloaded internet. Default value \"small\".","code":""},{"path":"https://www.slendr.net/reference/world.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Define a world map for all spatial operations — world","text":"Object class slendr_map, encodes standard spatial object class sf additional slendr-specific attributes requested x-range y-range.","code":""},{"path":"https://www.slendr.net/reference/world.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Define a world map for all spatial operations — world","text":"","code":"# create a blank abstract world 1000x1000 distance units in size blank_map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # it is possible to construct custom landscapes (islands, corridors, etc.) island1 <- region(\"island1\", polygon = list(c(10, 30), c(50, 30), c(40, 50), c(0, 40))) island2 <- region(\"island2\", polygon = list(c(60, 60), c(80, 40), c(100, 60), c(80, 80))) island3 <- region(\"island3\", center = c(20, 80), radius = 10) archipelago <- island1 %>% join(island2) %>% join(island3) custom_map <- world(xrange = c(1, 100), c(1, 100), landscape = archipelago) # real Earth landscapes can be defined using freely-available Natural Earth # project data and with the possibility to specify an appropriate Coordinate # Reference System, such as this example of a map of Europe real_map <- world(xrange = c(-15, 40), yrange = c(30, 60), crs = \"EPSG:3035\") #> Reading layer `ne_110m_land' from data source #> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmphADFZn/naturalearth/ne_110m_land.shp' #> using driver `ESRI Shapefile' #> Simple feature collection with 127 features and 3 fields #> Geometry type: POLYGON #> Dimension: XY #> Bounding box: xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513 #> Geodetic CRS: WGS 84"},{"path":"https://www.slendr.net/news/index.html","id":"slendr-090","dir":"Changelog","previous_headings":"","what":"slendr 0.9.0","title":"slendr 0.9.0","text":"full support running SLiM msprime simulations slendr analyzing tree sequences using tskit interface implemented. Please note Windows support still rather experimental – internal slendr test suite currently assumes SLiM installed using msys2 system described section 2.3.1 SLiM manual means installing SLiM (via conda) might require additional adjustments. fallback option form slim_path= argument slim() function can used non-standard SLiM installation circumstances. convenience, please add path directory containing slim.exe binary PATH variable editing C:/Users//Documents/.Renviron file accordingly. See relevant section Windows installation slendr documentation additional information. Feedback Windows functionality bug reports highly appreciated via GitHub issues! Many thanks @GKresearch @rdinnager huge help making Windows port happen! [PR #149] trivial change made slendr’s SLiM back-end script fixing issue introduced SLiM 4.1 upgrade (see changelog version 0.8.1 ). expected lead different simulation outputs two versions slendr (0.8.2 vs 0.8.1) SLiM (4.1 vs 4.0.1) used. (PR #148) msprime internal dependency slendr updated 1.3.0, Python 3.12. result, loading slendr, users prompted re-run setup_env() make sure dedicated slendr Python environment fully updated. time, prevents failing installation (least) M1 macOS using pip. (#5ce212, #a210d4)","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-081","dir":"Changelog","previous_headings":"","what":"slendr 0.8.1","title":"slendr 0.8.1","text":"CRAN release: 2024-01-15 Fixed issue apparent contradiction time direction models range expansion scheduled within time interval together associated “locked-” changes population size time interval. (#d2a29e) introduction tspop installable via pip (see changelog previous version) caused GLIBCXX-related errors conda pip dependencies related pandas Python package. work around issue, setup_env() longer installs pandas conda regardless setting pip = TRUE|FALSE parameter. Instead, pandas installed via pip single step tspop installed. (#cbe960) WARNING: SLiM 4.1 just released includes couple backwards incompatible changes related implementation spatial maps prevent current version slendr’s slim() function working correctly. rely functionality provided slim() function, use SLiM 4.0. (Note want multiple versions SLiM system, can either use slim_path = argument slim() specify $PATH required version SLiM ~/.Renviron file just like normal circumstances). Porting slendr SLiM 4.1 worked .","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-080","dir":"Changelog","previous_headings":"","what":"slendr 0.8.0","title":"slendr 0.8.0","text":"CRAN release: 2023-12-07 order support new ts_tracts() function backed tspop module (see item ), new slendr Python environment required. , users run setup_env() get required Python dependencies now installed internal virtual environment named Python-3.11_msprime-1.2.0_tskit-0.5.6_pyslim-1.0.4_tspop-0.0.2. (#b5330c) Experimental support tspop link-ancestors algorithm detection ancestry tracts form new slendr function ts_tracts(). works slendr-generated msprime tree sequences “pure” msprime SLiM tree sequences (slendr-generated SLiM tree sequences), tested toy models. Note: tspop Python module published conda. order set new slendr Python environment, run setup_env(pip = TRUE) make sure Python dependencies installed pip instead conda. (PR #145) Updated Python dependencies (bugfix pyslim release v1.0.4 tskit v0.5.6, latter due broken jsonschema dependency tskit). (#001ee5) Experimental support manually created spatial tree sequences. (PR #144)","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-072","dir":"Changelog","previous_headings":"","what":"slendr 0.7.2","title":"slendr 0.7.2","text":"CRAN release: 2023-08-08 new function ts_names() added, avoiding need extremely frequent (, unfortunately, cumbersome) trick getting named lists individual symbolic names ts_samples(ts) %>% split(., .[[split]]) %>% lapply([[, \"name\") confusing experienced R users. (#7db6ea) Fixed broken concatenation symbolic sample names tree-sequence statistic functions, provided unnamed single-element lists character vectors. (#b3c650) plot_model() now argument file =, making possible save visualization model without actually opening plotting device. can useful particularly working remote server, order avoid often slow X11 rendering. (#e60078) plot_model() now argument order = allowing override default -order ordering populations along x-axis. (#7a10ea)","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-071","dir":"Changelog","previous_headings":"","what":"slendr 0.7.1","title":"slendr 0.7.1","text":"CRAN release: 2023-07-14 Starting release, *spatial* simulation data analysis functionality slendr conditional presence R geospatial packages sf, stars, rnaturalearth system. means users able install slendr (use non-spatial functionality) even without R packages installed. said, nothing really changes practice: spatial features slendr just one install.packages(c(\"sf\", \"stars\", \"rnaturalearth\")) away! difference slendr doesn’t try installation, users instructed (needed) package loaded. (#7a10ea) spatial dependencies present spatial slendr function called regardless (world(), move(), etc.), error message printed information install spatial dependencies via install.packages() . ? ’s true main reason slendr’s existence ability simulate spatio-temporal data realistic landscapes via SLiM. However, practice, “average” uses slendr wild (classrooms!) rely traditional, non-spatial interface, spatial features used comparatively rarely moment (except cutting-edge exploratory research). Given setting spatial dependencies can bit hurdle, decided make dependencies optional, rather force every user go process installation whether need spatial features . function check_dependencies() now exported can used check whether slendr Python environment () SLiM () present. useful software building upon slendr, normal users can freely ignore . (#6ae6ce) path file tree sequence loaded now tracked internally via attr(, \"path\") attribute. Note implemented purposes clean large-scale simulation studies (facilitated demografr) mostly internal feature, considered experimental. (#f181a2) Attempts resize population right time split (led issues simulations) now prevented. (#f181a2) Fix minor issue preventing sampling msprime population right time creation. (#aea231)","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-070","dir":"Changelog","previous_headings":"","what":"slendr 0.7.0","title":"slendr 0.7.0","text":"CRAN release: 2023-06-26 emergency upgrade match latest pyslim 1.0.3 due serious bug recapitation. See extensive discussion process identification bug eventual fix. brief summary practical consequences bug, see thread pyslim’s developer formal announcement . change require re-run setup_env() order update slendr’s Python internals creating new internal Python virtual environment. (#45539a) potential issue parent population scheduled removal daughter population splits now caught moment daughter population() call rather simulation slim() run. (#0791b5) function plot_model() new argument gene_flow= determines whether gene-flow arrows visualized . (#104aa6) possibility perform recapitation, simplification, mutation tree sequence right inside call ts_load() (providing recapitate = TRUE, simplify = TRUE, mutate = TRUE, together arguments) now removed. motivation change realization benefit things like ts_load(\"\", recapitate = TRUE, Ne = ..., recombination_rate = ...) ts_load(\"\") %>% ts_recapitate(Ne = ..., recombination_rate = ...), frequent confusion recapitate = TRUE switches forgotten user. slendr teaching material actively used research codebases know use latter, explicit, pipeline approach anyway, one example reduncancy harm good. (#ad82ee) Note: Loading library(slendr) prompt message “legacy packages maptools, rgdal, rgeos, underpinning sp package, just loaded, retire October 2023. […].” internal business packages used slendr unfortunately silenced slendr’s side. ’s reason panic, can safely ignore . Apologies unnecessary noise.","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-060","dir":"Changelog","previous_headings":"","what":"slendr 0.6.0","title":"slendr 0.6.0","text":"CRAN release: 2023-06-07 relatively large update, unfortunately released haste due retirement rgdal package – significant dependency entire spatial R ecosystem phased effort move towards modern low-level geospatial architecture. Although slendr depend rgdal, many dependencies used (won’t short term, hence push remove rgdal dependency). significant update addition IBD functionality tskit, described . However, large part functionality extensively tested considered extremely experimental stage. like use , might safer either wait later release IBD functionality stable, use underlying, battle-tested Python implementation tskit. ts_ibd() now returns ID number MRCA node pair nodes sharing given IBD segment, well TMRCA node. (#7e2825) Trivial parameter errors caught population() calls rather simulation (solving minor issues discovered via big simulation runs development demografr). (#e33373) Fix error plotting exponential resizes last “present”. (#4c49a4) ts_ibd() longer gives obscure error = provided named list individuals’ names (instead expected unnamed list). names list elements used way, error happens somewhere deeply R->Python translation layer inside reticulate ’s need users concern . (#7965e4) Population size parameters times now explicitly converted integer numbers. internal, formal change (conversion happening implicitly inside SLiM engine anyway) now explicitly stated, also documentation relevant function. (#b7e89e) Population names now restricted strings also valid Python identifiers. Although restriction needed msprime back end slendr (SLiM), makes sense keep things tidy unified. fixes msprime crashing ValueError: population name must valid Python identifier. (#4ef518) layout algorithm plot_model() improved significantly. (PR #135). new optional argument run = added slim() msprime(). set TRUE (default), engines operate usual way. set FALSE, simulation run functions simply print command-line command execute engine question (returning CLI command invisibly). (#2e5b85) following start-note longer shown upon calling library(slendr): Users call init_env() manually activate Python environment slendr (see note version 0.5.0 extended explanation). ts_simplify() now accepts optional arguments keep_unary keep_unary_in_individuals (see official tskit docs detail) (#1b2112) Fix ts_load() failing load slendr-produced tree sequences simplified smaller set sampled individuals (reported ). issue caused incompatible sizes sampling table (always form used simulation) table individuals stored tree sequence simplification (potentially containing smaller set individuals original sampling table). fix , slendr tree sequence objects now track information individuals regarded “samples” (.e. symbolic names) maintained simplification, serialization loading, used slendr’s internal machinery join operations. (PR #137) Metadata summary ts_nodes() results longer printed whenever typed R console. Instead, summary can obtained explicit call summary() ts_nodes() tables. (#01af51 ts_tree() ts_phylo() now extract trees based tskit’s zero-based indexing #554e13. ts_simplify() now accepts filter_nodes = TRUE|FALSE, behavior tskit’s method #f07ffed.","code":"NOTE: Due to Python setup issues on some systems which have been causing trouble particularly for novice users, calling library(slendr) no longer activates slendr's Python environment automatically. In order to use slendr's msprime back end or its tree-sequence functionality, users must now activate slendr's Python environment manually by executing init_env() after calling library(slendr). (This note will be removed in the next major version of slendr.)"},{"path":"https://www.slendr.net/news/index.html","id":"slendr-051","dir":"Changelog","previous_headings":"","what":"slendr 0.5.1","title":"slendr 0.5.1","text":"CRAN release: 2023-03-09 minor release implements emergency fix CRAN warning suddenly popped latest CRAN checks. (#5600a4) new function ts_ibd() added, representing R interface tskit method TreeSequence.ibd_segments(). However, note ts_ibd() returns IBD results data frame (optionally, spatially annotated sf data frame). function operate around iteration, Python counterpart tskit. next major version slendr, function considered experimental. (PR #123)","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-050","dir":"Changelog","previous_headings":"","what":"slendr 0.5.0","title":"slendr 0.5.0","text":"CRAN release: 2023-02-02 Minor breaking change! Python environments slendr longer automatically activated upon calling library(slendr)! Using coalescent msprime back end slendr’s tree-sequence functions now requires making explicit call new function init_env() library(slendr) executed. (PR #102) Motivation change: small proportion users experiencing issues broken conda environments various issues Python virtual environments general. ’s hard guess frequent , experience workshops courses suggests perhaps 1 20 users experiencing Python issues hindered ability use slendr .(Fun fact: first user-submitted GitHub issue upon releasing first version slendr R package … Python virtual environment issue). Explanation: Activating Python environments automatically upon calling library(slendr) popular feature hid away complexities R-Python interface powers slendr’s tree-sequence functionality. particularly convenient many slendr users, particularly experience Python . Unfortunately, cases Python virtual environments tskit/msprime/pyslim user’s system ended corrupted (anything else Python level got broken), automatic Python environment activation performed library(slendr) call failed slendr even loaded. Sadly, completely pulled rug slendr nothing done perspective (issue happened low-level layer embedded-Python slendr ’ve loaded R). Solving issues difficult experienced users, many slendr users experience Python , never used conda, don’t understand concept “Python virtual environments” R-Python interface works. ! , slendr R package. Splitting Python virtual environment activation step init_env() function means library(slendr) now always succeeds (regardless potential underlying Python issues user’s sytem), making much easier diagnose fix Python problems R package loaded. , recap: library(slendr) longer activates slendr’s isolated Python virtual environment. order simulate tree sequences analyse using interface tskit, necessary call init_env(). function performs Python-activation steps library(slendr) used call automagically earlier slendr versions. change scripts necessary. Related previous point: slendr now requires Python 3.11, msprime 1.2.0, tskit 0.5.4, pyslim 1.0.1, keep recent releases Python dependencies. , presents hassle user, thing required re-running setup_env(). (PR #112). named list provided sample_sets = argument oneway statistic function, names used set column resulting data frame even single samples used. (#2a6781) now possible non-spatial populations otherwise spatial model. course, plotting models map, spatial components model plotted slendr give warning. absolutely sure users intends , slendr also give warning running compile_model() models like . Please consider option experimental time-hard predict edge cases might break (unit tests documentation tests passing though). Feedback welcome. (PR #112). now possible label groups samples slendr’s tskit interface functions make data frames statistics results readable. example, running ts_f3(ts, = c(\"p1_1\", \"p1_2\", \"p1_3\"), B = c(\"p2_1\", \"p2_3\"), C = c(\"p3_1\", \"p3_2\", \"p3_\")) resulted following data-frame output: gets unwieldy rather quickly, especially dozens hundreds samples grouped together populations. new syntax allows following shortcut via customised group names leveraging standard named list functionality R: readable line tskit-interface functions slendr used functionality via sample_sets = argument (ts_divergence(), ts_diversity(), etc.). (#ac5e484) default state parent = argument population() now NULL instead \"ancestor\". prevents silly surprising clashes situation population’s name really “ancestor”. change internally populations ancestral, splits data frame element slendr model object includes population carries formal “ancestral parent population” \"__pop_is_ancestor\" instead just \"ancestor\". Note internal implementation detail something particularly involve user. Still, somehow using slendr’s internal data structures, keep mind. (#f8a39a2)","code":"> ts_f3(ts, A = c(\"p1_1\", \"p1_2\", \"p1_3\", \"p1_4\", \"p1_5\"), B = c(\"p2_1\", \"p2_2\", \"p2_3\"), C = c(\"p3_1\", \"p3_2\", \"p3_3\", \"p3_4\")) # A tibble: 1 × 4 A B C f3 1 p1_1+p1_2+p1_3+p1_4+p1_5 p2_1+p2_2+p2_3 p3_1+p3_2+p3_3+p3_4 0.000130 > ts_f3(ts, A = list(group_one = c(\"p1_1\", \"p1_2\", \"p1_3\", \"p1_4\", \"p1_5\")), B = list(group_two = c(\"p2_1\", \"p2_2\", \"p2_3\")), C = list(group_three = c(\"p3_1\", \"p3_2\", \"p3_3\", \"p3_4\"))) # A tibble: 1 × 4 A B C f3 1 group_one group_two group_three 0.000130"},{"path":"https://www.slendr.net/news/index.html","id":"slendr-040","dir":"Changelog","previous_headings":"","what":"slendr 0.4.0","title":"slendr 0.4.0","text":"CRAN release: 2022-09-30 msprime() function now makes sure given slendr model can fully coalesce single common ancestor population. Previously, multiple ancestral populations created parent = \"ancestor\" cause infinite simulation plugged msprime() backend. (#095b124) initial size population emerges split another population now printed population history summary R console. (#6525bf3) couple fixes support loading, processing, plotting “manually” created tree sequences implemented (see ). sure practically useful, ’s important able load even “pure” tree sequences simulators SLiM msprime. set unit tests added, making sure minimalist nodes & edges table can loaded, well nodes & edges & individuals, plus tables populations sites & mutations. PRs extensive unit tests bug reports tree sequences failing load appreciated! code handling cases “manually-created” tree sequences missing individual table, missing populations table, etc. seems especially brittle moment (#79adf14). -1 value missing value indicator used tskit now replaced R-like NA various tree-sequence tables (annotated slendr original tskit ) (#79adf14). Relative paths now expanded ts_save() (#382e0b7). slendr models can now optionally compiled without serialization disk. works msprime() coalescent back end much faster cases huge number simulations needs run non-serialized models, msprime() now calls back end engine directly R-Python interface (rather command line) output tree sequences saved disk, rather passed Python-R interface directly memory (PR #112). Deprecated argument sampling = functions slim() msprime() now permanently removed favour samples = argument (#0757b6e). Avoid unnecessary array type tskit results returned via reticulate. Numeric vectors (columns data frames numerical results) obtained way simple R numeric vector (#5101b39). One-way multi-way statistics results now returned simple numerical vectors. Previously, results returned type array despite “looking” vectors (values returned R reticulate-Python layer), caused unnecessary annoyances type-conversions R side things even intended (#403df3b). Computing population genetic statistics named samples present tree sequence (likely typos) now correctly caught reported error (#da7e0bb).","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-030","dir":"Changelog","previous_headings":"","what":"slendr 0.3.0","title":"slendr 0.3.0","text":"CRAN release: 2022-08-19 SLiM 4.0 now required running simulations slim() engine. want run slendr simulations SLiM (spatial non-spatial), need upgrade SLiM installation. SLiM 3.7.1 version longer supported upcoming new slendr spatial features depend SLiM 4.x maintaining two functionally identical yet syntactically different back ends feasible (PR #104). time SLiM 4.0 release, new versions Python modules msprime, tskit pyslim also released. fact, able work SLiM 4.0 tree sequences properly, Python modules must upgraded well. Next time load library(slendr), prompted setup new updated Python environment can easily running setup_env(). Experimental support running coalescent msprime simulations analysing tree-sequence data using tskit Windows platform now implemented (PR #102).","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-020","dir":"Changelog","previous_headings":"","what":"slendr 0.2.0","title":"slendr 0.2.0","text":"CRAN release: 2022-08-09 slendr now CRAN! Big changes way tree-sequence outputs handled slendr default. See comment extended description examples change. (PR #100). Briefly, simulation functions slim() msprime() now return tree-sequence object default (can switched setting load = FALSE), avoiding need always run ts <- ts_load(model) previously. time, parameter output = can now used slim() msprime() specify location tree-sequence file saved (temporary file default). slendr’s tree-sequence R interface tskit Python module generalized load, process, analyze tree sequences non-slendr models! means users can use slendr R package even analyzing tree sequences coming standard msprime SLiM scripts, including spatial capabilities available slendr tree sequences far. Please note generalization still rather experimental might corner cases tree sequence msprime SLiM script load properly leads errors. happens, please open GitHub issue script question attached. (PR #91) Removed functions function arguments originally deprecated renaming phase pre-preprint refactoring. affects compile, boundary, dispersal, expand, geneflow, plot.slendr, plot_graph, read, sampling, shrink. Similarly, deprecated dir argument compile_model now path, geneflow argument compile_model now gene_flow, _dist suffix removed competition_dist, mate_dist, dispersal_dist. get error missing function function argument code used work ancient version slendr, . (#985b451) setting isolated Python environment using setup_env(), slendr now makes decision whether install Python dependencies using pip (critical osx-arm64 conda msprime/tskit unfortunately currently broken) conda (every platform). can still influenced user using pip = argument, now change default behavior ARM64 Mac. (#54a413d) name default slendr Python environment now shortened even , redundant _pandas prefix now dropped. Users notified upon calling library(slendr) new environment created. OK, ’s bug. (#54a413d) format default slendr Python environment now msprime-_tskit-_pyslim-_pandas, dropping slendr_ prefix. paves way towards future non-slendr tskit R package, share Python environment slendr (R packages go hand hand). isn’t really user-facing change, except calling setup_env() suggests creating new Python environment library(slendr) appear slendr environment yet present. Calling setup_env() creating new Python environment scratch solve problem. (#eb05180) xrange yrange parameters world() now enforced two-dimensional numeric vectors, avoiding unnecessary issues misspecified longitude/latitude (#df95369) argument sampling = slim() msprime() now renamed samples = (#adf4e0d). automated setup_env() function creating dedicated mini Python environments slendr now installs packages using pip default. Reason: rate conda failures dependency conflicts (even trivial case installing nothing msprime + tskit + pyslim + pandas) high rely . option use conda package installations setup_env() still , users must explicitly call setup_env(pip = FALSE) get behavior. Note conda still used means install Python ! change affects way Python modules installed dedicated slendr Python environment, installation Python . (#81be1a7) name automatically created slendr-specific Python environment now composed names versions Python modules installed. makes possible naturally upgrade slendr Python dependencies case tskit / msprime / pyslim folks upgrade packages. case, slendr user upgrades slendr package (new version requires newer versions Python modules), slendr simply recommend create new Python environment without additional effort part. (#81be1a7) code setup_env() simplified bare essentials. Now serves way auto-setup dedicated, isolated Python installation slendr environment. interface install Python modules custom-defined Python environment created outside R removed functionality necessary – custom environments can easily activated calling reticulate::use_virtualenv reticulate::use_condaenv. (#30f24b9) Python users want use custom Python environments msprime, tskit, pyslim, can silence suggestion use setup_env() printed library(slendr) call setting options(slendr.custom_env = TRUE). (#30f24b9) argument sim_length = now renamed simulation_length =. accepted moment using old name simply inform user future deprecation. (#56491fb) Extensive set runnable examples including figures built-pre-compiled example model added documentation. (#395df62c)","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-010","dir":"Changelog","previous_headings":"","what":"slendr 0.1.0","title":"slendr 0.1.0","text":"First numbered version slendr celebrate bioRxiv preprint. 🥳 🎉","code":""}] +[{"path":"https://www.slendr.net/LICENSE.html","id":null,"dir":"","previous_headings":"","what":"MIT License","title":"MIT License","text":"Copyright (c) 2022 Martin Petr Permission hereby granted, free charge, person obtaining copy software associated documentation files (“Software”), deal Software without restriction, including without limitation rights use, copy, modify, merge, publish, distribute, sublicense, /sell copies Software, permit persons Software furnished , subject following conditions: copyright notice permission notice shall included copies substantial portions Software. SOFTWARE PROVIDED “”, WITHOUT WARRANTY KIND, EXPRESS IMPLIED, INCLUDING LIMITED WARRANTIES MERCHANTABILITY, FITNESS PARTICULAR PURPOSE NONINFRINGEMENT. EVENT SHALL AUTHORS COPYRIGHT HOLDERS LIABLE CLAIM, DAMAGES LIABILITY, WHETHER ACTION CONTRACT, TORT OTHERWISE, ARISING , CONNECTION SOFTWARE USE DEALINGS SOFTWARE.","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"quick-installation","dir":"Articles","previous_headings":"","what":"Quick installation","title":"Installation instructions","text":"slendr available CRAN R package repository. , can install simply executing install.packages(\"slendr\") R console. want (need) get development version, can install directly GitHub executing devtools::install_github(\"bodkan/slendr\") via R package devtools (can gen devtools running install.packages(\"devtools\")). fact, decide try slendr, please make sure update regularly keep eye changelog regular basis! can find information latest bugfixes potential breaking changes. install slendr, calling library(slendr) check software dependencies available. , R package provide brief helpful guide resolve potential issues. rest vignette talks necessary software dependencies bit detail. Please note slendr extensively tested macOS Linux moment. However, experimental support runnig SLiM msprime simulations Windows analyzing tree-sequence outputs using tskit interface platform well. Feedback issues using slendr Windows highly appreciated.","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"software-dependencies","dir":"Articles","previous_headings":"","what":"Software dependencies","title":"Installation instructions","text":"slendr relies three main software dependencies: geospatial data analysis R package sf (encoding spatial slendr models analysing spatial tree-sequence data), forward population genetic simulator SLiM (forward simulations), Python modules tskit, msprime, pyslim (coalescent simulations tree-sequence analysis), also pandas used internally simulation back ends. three widely used respective fields , , easily obtainable major operating systems (see information troubleshoot potential problems). Note depending use case, three sets dependencies necessarily needed. ’re going running forward spatial simulations, don’t need SLiM geospatial R packages sf, stars, rnaturalearth. applies also animation spatial models using gganimate R package. slendr install dependencies. need functionality, install respective R packages manually. vignette, briefly explain get slendr’s software dependencies installed. said, note normal circumstances (exception SLiM), manual installation individual dependencies required.","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"sf-stars-rnaturalearth","dir":"Articles","previous_headings":"Software dependencies","what":"sf, stars, rnaturalearth","title":"Installation instructions","text":"R package sf heart geospatial data analysis R. available CRAN can installed major platforms executing install.packages(\"sf\") R session. applies stars rnaturalearth. first load slendr via library(slendr), ’re missing three geospatial R packages, notified instructed can easily obtain CRAN using single call install.packages(). said, sf depends number geospatial libraries depending exact setup Linux macOS machine, libraries missing. Luckily, easy install via Homebrew (macOS) via appropriate package manager Linux distribution (Ubuntu, Fedora, etc.). Detailed instructions operating system can found . ’re problems installation three packages, look help .","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"macos","dir":"Articles","previous_headings":"Software dependencies > sf, stars, rnaturalearth","what":"macOS","title":"Installation instructions","text":"One user recently installed slendr fresh macOS system reported needed install libgit2 order able install package devtools devtools::install_github(\"bodkan/slendr\") step described top page. Additionally, install couple C/C++ libraries well (dependencies sf package). end, able successfully install slendr running: Note assumes Homebrew package manager already setup Mac. ’re beginning computational scientist using Mac, strongly encourage install Homebrew. Sooner later need specific Linux/unix program anyway, Homebrew way get (Mac unix machine, without Homebrew poor one default).","code":"brew install libgit2 udunits gdal proj"},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"linux","dir":"Articles","previous_headings":"Software dependencies > sf, stars, rnaturalearth","what":"Linux","title":"Installation instructions","text":"Testing slendr installation fresh, pristine Debian installation dependencies previously installed, run following: ’s unlikely need (might need packages non-Debian distributions), got slendr dependencies running completely clean system. Might good start case trouble Linux machine. Windows special treatment necessary get slendr running. install slendr via install.packages(\"slendr\"), get binary version package dependencies without need compiling sources.","code":"sudo apt-get install libudunits2-dev libssl-dev libgdal-dev libgsl-dev libgit2-dev libfontconfig1-dev libharfbuzz-dev libfribidi-dev"},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"slim","dir":"Articles","previous_headings":"Software dependencies","what":"SLiM","title":"Installation instructions","text":"forward population genetic software SLiM available major software platforms. complete installation instructions can found . Mac, recommend installing SLiM via pkg installer available direct download website. Linux, can either install SLiM via appropriate package manager Linux distribution (see SLiM manual information), can easily compile . install SLiM Windows, please follow instructions section 2.3.1 SLiM manual. Note although SLiM also available conda, comes without SLiMgui! Note slendr requires SLiM 4.0 work earlier version. , running library(slendr) inform potential issues SLiM installation.","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"adding-slim-to-the-path","dir":"Articles","previous_headings":"Software dependencies > SLiM","what":"Adding SLiM to the $PATH","title":"Installation instructions","text":"order slendr able find SLiM installation, R must able find slim binary (slim.exe case Windows) called $PATH variable. easiest way verify true call Sys.(\"slim\") (Sys.(\"slim.exe\") Windows) R session. instance, Mac, get : Windows, get (followed section 2.3.1 SLiM manual describing “official” way install SLiM recommend follow well): , hand, might get something like — empty string: means $PATH R configured properly R (slendr) won’t able find SLiM $PATH. add SLiM $PATH ? Probably convenient way editing .Renviron file. precise location file depends operation system can automatically get open text editor using command (might install.packages(\"usethis\") first): , can either add following (note ’s $ line!): Alternatively, already $PATH contents specified R session, can get calling Sys.getenv(\"PATH\") R console, grab entire string get way, append path installed SLiM using appropriate delimiter (: Linux/macOS, ; Windows) string. case, edit might look something like : instance, Mac, .Renviron file contains line (note last item /usr/local/bin matches path slim showed ): testing Windows machine, .Renviron file (, look path C:/msys64/mingw64/bin;$PATH\" matches slim.exe binary shown ): important check R can find SLiM using Sys.() command described . gives positive result, won’t able use slendr’s spatial SLiM simulations. ’re struggling , search advice related .Renviron $PATH online.","code":"> Sys.which(\"slim\") slim \"/usr/local/bin/slim\" > Sys.which(\"slim.exe\") slim.exe \"C:\\\\msys64\\\\mingw64\\\\bin\\\\slim.exe\" > Sys.which(\"slim\") slim \"\" usethis::edit_r_environ() PATH=\"\" PATH=\"\" PATH=\"/opt/homebrew/bin:/opt/homebrew/sbin:/Users/mp/.my_local/bin:/Users/mp/.my_local/AdmixTools/bin:/Library/TeX/texbin:/opt/homebrew/opt/gnu-sed/libexec/gnubin:/opt/homebrew/opt/coreutils/libexec/gnubin:/usr/local/bin\" PATH=\"C:\\\\msys64\\\\usr\\\\bin;C:\\\\rtools43\\\\x86_64-w64-mingw32.static.posix\\\\bin;C:\\\\rtools43\\\\usr\\\\bin;C:\\\\Program Files (x86)\\\\R\\\\R-4.3.2\\\\bin\\\\x64;C:/msys64/mingw64/bin\""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"fallback-options","dir":"Articles","previous_headings":"Software dependencies > SLiM > Adding SLiM to the $PATH","what":"Fallback options","title":"Installation instructions","text":"don’t want deal editing .Renviron file, able set path SLiM using command Sys.setenv(PATH = \"\"). beginning slendr R scripts though. Alternatively, slim() function argument slim_path= can specify full path slim slim.exe binaries directly (directory ’s case $PATH! full path slim/slim.exe binary ).","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"python","dir":"Articles","previous_headings":"Software dependencies","what":"Python","title":"Installation instructions","text":"order able run coalescent simulations process tree-sequence files, slendr needs Python modules tskit, msprime, pyslim (also needs pandas library). Setting isolated Python environment specific version Python packages (important avoid clashes among different Python programs needed system) can bit hassle users. especially true R users might use Python daily work. order make sure R package appropriate version Python available, correct versions Python module dependencies, slendr provides dedicated function setup_env() automatically downloads completely separate Python distribution installs required versions tskit, msprime, pyslim modules dedicated virtual environment. Moreover, Python installation virtual environment entirely isolated Python configurations already present user’s system, avoiding potential conflicts versions Python Python modules required slendr. Next time call library(slendr), need activate environment automatically calling init_env(). ’re comfortable Python don’t need worry beyond calling setup_env() init_env(), interaction Python necessary working slendr R.","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"failing-conda","dir":"Articles","previous_headings":"Software dependencies > Python","what":"Failing conda?","title":"Installation instructions","text":"order support Windows, slendr uses conda download Python interpreter explained . Given fact, run setup_env(), slendr tries leverage conda present install Python dependencies (msprime, tskit, pyslim, pandas) via conda . Unfortunately, conda can break frustratingly many random reasons completely trips setup_env(). run issue, fallback option install Python dependencies msprime, tskit, pyslim, pandas via pip , unlike conda, works practically every time. setup_env() fails conda-related reason, first clear broken environment calling clear_env(), restart R session, call setup_env(pip = TRUE) instead default setup_env(). Note might require install GSL numerical library, ’s trivial issue macOS (brew install gsl) Linux (Ubuntu, instance, sudo apt-get install libgsl-dev).","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"information-for-python-experts","dir":"Articles","previous_headings":"Software dependencies > Python","what":"Information for Python experts","title":"Installation instructions","text":"case wondering slendr accomplish : slendr’s Python interface implemented using R package reticulate. embeds Python interpreter inside R session, enabling high-performance interoperability languages without need user intervention.","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"docker","dir":"Articles","previous_headings":"","what":"Docker","title":"Installation instructions","text":"currently official Docker image slendr one soon. current plan use geospatial image published Rocker project (already contains pre-compiled R, RStudio, necessary R package dependencies sf ) extend slendr SLiM. Stay tuned!","code":""},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"motivation","dir":"Articles","previous_headings":"","what":"Motivation","title":"Introduction and basic tutorial","text":"motivation starting project create programmable simulation framework add explicit spatial dimension population genetics models. Specifically, original idea able take models one — representing simplified view history anatomically modern humans (AMH) West Eurasia last ~50 thousand years (comprehensive overview can found review Lazaridis)—design tool makes possible simulate models explicit geographical context capture processes similar following figure (taken study Haak et al. 2015): reason probably clear. lot studying history humans species focused reconstructing population movements, expansions gene flow events, happen geographic context. fact, geographic component often interested (.e., “ancestors population come ?”, “route fast migrate?”, etc.). However, goes beyond just simulating demographic history. instance, selection pressure driving adaptation can often spatially heterogeneous: members population occupying one part continent exposed different environmental pressure individuals elsewhere, allele frequency distributions shaped adaptation process reflect spatial heterogeneity accordingly. framework enables simulation explicitly spatial genomic data situations allow us build realistic models test specific hypotheses, goals simply possible using non-spatial simulation methods. R package slendr introduced vignette presents framework. Internally, package two independent tightly interconnected units: R interface provides set functional primitives (“mini-language” sorts) encoding various features spatio-temporal models: population migrations, expansions gene flow, happening real geographic landscape defined freely available cartographic data. Populations represented simple R objects easily visualized spatial boundaries, making possible build complex models interactively set small simple building blocks. SLiM simulation back end represented built-generic SLiM script designed read spatio-temporal model configuration parameters objects established step 1. , tailor simulation run user-defined model. Alternatively, slendr also supports executing standard population genetics models random-mating setting. means models need explicit geographic map can simulated either built-SLiM back end script, efficient msprime back end also provided package. important design objective make integration parts 1. 2. appear completely seamless. Even extremely complex models, model building execution (.e., simulation) can performed without leaving convenience R interface RStudio. simulation complexities happen automatically hood knowledge SLiM required. fact, motto slendr package “Write complex spatiotemporal population genetics models simple R script.”","code":""},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"geospatial-data","dir":"Articles","previous_headings":"","what":"Geospatial data","title":"Introduction and basic tutorial","text":"Geospatial analysis deep complex topic, dozens libraries programs designed deal fact Earth three-dimensional object forced plot geographical objects (, case, simulate data) two-dimensional plane. Luckily, technical issues Coordinate Reference Systems, transformations manipulation geometric objects (shifting population boundaries, expansions, etc.) pretty much solved now. Unfortunately, dealing issues practice quite challenging requires non-trivial degree domain expertise. Programming even simple task geospatial data analysis also often requires lot code. R package designed provide collection primitives (“mini-language” sorts) programming population dynamics (splits, movement, gene flow, expansion spatial boundaries) across space time without explicitly deal challenges inherent geospatial analyses.","code":""},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"installation-and-setup","dir":"Articles","previous_headings":"","what":"Installation and setup","title":"Introduction and basic tutorial","text":"slendr R package available CRAN can installed simply running install.packages(\"slendr\"). need run latest development version (instance, need latest bugfixes), can get via R package devtools executing devtools::install_github(\"bodkan/slendr\") R terminal. can find detailed installation instructions vignette. get slendr installed, just need load : dependencies (SLiM necessary Python modules) missing, get informative message proceed.","code":"library(slendr) # activate the internal Python environment needed for simulation and # tree-sequence processing init_env() #> The interface to all required Python modules has been activated."},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"defining-the-overall-world-map","dir":"Articles","previous_headings":"","what":"Defining the overall world map","title":"Introduction and basic tutorial","text":"anything else, need define section map world provide context downstream spatio-temporal manipulation population ranges. principle, source geospatial data can manipulated using simple features (sf) infrastructure used. now slendr package implicitly uses Natural Earth project data (vectorized form!), internally loads using rnaturalearth interface. first slendr function look map(). function load map entire world vectorized format zoom specified section world. Note call , specify coordinates zoom geographical Coordinate Reference System (CRS), longitude/latitude, also specified want perform downstream manipulation spatial population maps projected CRS (Lambert Azimuthal Equal-Area projection) appropriate representing wider European continent used tutorial. course, different CRS projections used based part world want simulate. Describing intricacies coordinate reference systems beyond scope tutorial, ’re interested learning encourage read freely available textbook dedicated topic. approach slendr: let user specify everything easy--understand longitude/latitude geographical CRS (can read map, making easy define spatial boundaries trajectories movement), internal data structures final exported spatial maps internally handled projected CRS, important make sure distances proportions distorted. Internally, map object currently normal sf class object without additional components. unlike slendr objects described , also sf objects carry additional internal components. Note summary object says “projected CRS: ETRS89-extended / LAEA Europe”. means world map indeed transformed projected CRS specified .","code":"map <- world( xrange = c(-13, 70), # min-max longitude yrange = c(18, 65), # min-max latitude crs = \"EPSG:3035\" # coordinate reference system (CRS) for West Eurasia ) map #> slendr 'map' object #> ------------------- #> map: internal coordinate reference system EPSG 3035 #> spatial limits (in degrees longitude and latitude): #> - vertical -13 ... 70 #> - horizontal 18 ... 65"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"plotting-geographic-features-and-population-ranges","dir":"Articles","previous_headings":"","what":"Plotting geographic features and population ranges","title":"Introduction and basic tutorial","text":"slendr package implements plotting function called plot_map(). order make easier convenient iteratively build complex models. function can intelligently decide (based given input arguments) right way present data user, helps define models quickly without relying lower-level mechanisms sf package. see examples plot_map() action .","code":""},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"defining-smaller-geographic-regions","dir":"Articles","previous_headings":"","what":"Defining smaller geographic regions","title":"Introduction and basic tutorial","text":"addition overall spatial map context, can also define smaller geographic boundaries. mostly useful whenever want restrict population’s movement (spatial population expansion) smaller region map intuitive geographic meaning (.e., Anatolia, West Eurasia, etc.). Note objects created population boundaries (yet anyway)! simply labels generic geographic boundaries can used later. attached population point. , object returned region() function actually sf object, carries additional annotation name region (“Anatolia”): However, object also carries additional class annotations purpose internal slendr machinery: Furthermore, note region() calls specified map object defined beginning. object added hidden attribute slendr object represents context geospatial transformations, expansions, plots. can use generic plot_map() function plot geographic regions context defined section world map: Note map object longer explicitly specified. needed, class objects provided plot_map() function must carry “map” attribute. fact, object must carry map context — slendr complains whenever case. can check component really , although hidden, using built-attr function verify map object created beginning:","code":"africa <- region( \"Africa\", map, polygon = list(c(-18, 20), c(38, 20), c(30, 33), c(20, 33), c(10, 38), c(-6, 35)) ) europe <- region( \"Europe\", map, polygon = list( c(-8, 35), c(-5, 36), c(10, 38), c(20, 35), c(25, 35), c(33, 45), c(20, 58), c(-5, 60), c(-15, 50) ) ) anatolia <- region( \"Anatolia\", map, polygon = list(c(28, 35), c(40, 35), c(42, 40), c(30, 43), c(27, 40), c(25, 38)) ) anatolia #> slendr 'region' object #> ---------------------- #> name: Anatolia #> #> map: internal coordinate reference system EPSG 3035 class(anatolia) #> [1] \"slendr\" \"slendr_region\" \"sf\" \"data.frame\" plot_map(africa, europe, anatolia, title = \"Geographic regions\") all(attr(europe, \"map\") == map) #> [1] TRUE all(attr(anatolia, \"map\") == map) #> [1] TRUE"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"defining-spatial-population-boundaries","dir":"Articles","previous_headings":"","what":"Defining spatial population boundaries","title":"Introduction and basic tutorial","text":"One aims slendr package formalize specification spatial population boundaries changes time. core function population(), takes population name, time want enforce population’s boundary, effective population size population time, map object described . also specify existing population specified population split (explicitly say ’s ancestral population). specifying actual spatial boundaries, several options.","code":""},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"polygon-population-ranges","dir":"Articles","previous_headings":"Defining spatial population boundaries","what":"Polygon population ranges","title":"Introduction and basic tutorial","text":"can define detailed population boundaries using polygon geometry object region object created region() function , using polygon = argument population(). , reminder, note coordinates described context geographic CRS. First, let’s create African ancestors modern humans. restrict spatial boundary African population africa region defined :","code":"afr <- population(\"AFR\", time = 52000, N = 3000, map = map, polygon = africa) plot_map(afr)"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"circular-population-ranges","dir":"Articles","previous_headings":"Defining spatial population boundaries","what":"Circular population ranges","title":"Introduction and basic tutorial","text":"want simulate abstract simple population boundary, can specify circular range center radius arguments instead polygon. distance units slendr package specified coordinate system given “world creation”. instance, EPSG 3035 (’re using ) specifies distances meters. define location population non-Africans right split African ancestors: call plot_map() function returned object, option either plot population range “raw” form “intersected” form, case raw boundary intersected “background” landscape (removing large bodies water, etc.). intersected form ultimately exported serialized format (see ) loaded spatial map SLiM. plot_map() function renders intersected population ranges default.","code":"ooa <- population( \"OOA\", parent = afr, time = 51000, N = 500, remove = 25000, center = c(33, 30), radius = 400e3 ) plot_map(ooa, intersect = TRUE, title = \"'Intersected' population range\")"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"population-movement-across-a-landscape","dir":"Articles","previous_headings":"","what":"Population movement across a landscape","title":"Introduction and basic tutorial","text":"describe directional population movement, can use function move(). accepts coordinates destination points along way (trajectory) duration migration, automatically generates number intermediate spatial maps along trajectory movement produce reasonable degree spatial continuity (number can also specified manually). can inspect object returned move() function see now contains just first YAM population range 7000 years ago, also ranges intermediate locations: Checking result visually , see: Let’s create population Eastern Hunter Gatherers (EHG), split first non-Africans 28000 years ago: ’re , let’s also create population Western Hunter Gatherers (WHG). people living region eventually became present day Europeans receiving gene flow groups time (see ), call “EUR” simplify modeling code little bit:","code":"ooa <- ooa %>% move( trajectory = list(c(40, 30), c(50, 30), c(60, 40)), start = 50000, end = 40000 ) ooa #> slendr 'population' object #> -------------------------- #> name: OOA #> habitat: terrestrial #> #> number of spatial maps: 28 #> map: internal coordinate reference system EPSG 3035 #> scheduled removal at time 25000 #> #> population history overview: #> - time 51000: split from AFR (N = 500) #> - time 50000-40000: movement across a landscape plot_map(ooa, title = \"Intermediate migration maps\") ehg <- population( \"EHG\", parent = ooa, time = 28000, N = 1000, remove = 6000, polygon = list( c(26, 55), c(38, 53), c(48, 53), c(60, 53), c(60, 60), c(48, 63), c(38, 63), c(26, 60)) ) eur <- population( # European population name = \"EUR\", parent = ehg, time = 25000, N = 2000, polygon = europe )"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"spatial-population-expansion","dir":"Articles","previous_headings":"","what":"Spatial population expansion","title":"Introduction and basic tutorial","text":"can simulate expanding range population using function expand_range(), accepts parameters specifying many kilometers boundary expand (argument), long expansion take (duration argument) many intermediate spatial map snapshots exported representing expansion (snapshots argument). instance, let’s represent expansion Anatolian farmers, also split OOA population 28000 years ago time split EHG population. Note use optional parameter, polygon, restricts expansion Europe, instead around Anatolia: Note , principle, specify entire spatio-temporal history population single pipeline using pipe operator %>%. , can inspect object returned expand_range() function see contains spatial maps (“snapshots”) expansion process across time: can () check results visually: visually see really going behind scenes, can also plot raw, non-intersected form expansion : can see population Anatolian farmers point invades spatial boundary EUR population. , doesn’t imply gene flow. section gene flow , see slendr implements gene flow overlapping (non-overlapping) populations. Let’s add couple populations migrations move implementing gene flow . Yamnaya steppe herders:","code":"ana <- population( # Anatolian farmers name = \"ANA\", time = 28000, N = 3000, parent = ooa, remove = 4000, center = c(34, 38), radius = 500e3, polygon = anatolia ) %>% expand_range( # expand the range by 2.500 km by = 2500e3, start = 10000, end = 7000, polygon = join(europe, anatolia) ) ana #> slendr 'population' object #> -------------------------- #> name: ANA #> habitat: terrestrial #> #> number of spatial maps: 16 #> map: internal coordinate reference system EPSG 3035 #> scheduled removal at time 4000 #> #> population history overview: #> - time 28000: split from OOA (N = 3000) #> - time 10000-7000: range expansion plot_map(ana, title = \"Anatolian expansion into Europe\") plot_map(ana, title = \"Anatolian expansion into Europe (not intersected)\", intersect = FALSE) yam <- population( # Yamnaya steppe population name = \"YAM\", time = 7000, N = 500, parent = ehg, remove = 2500, polygon = list(c(26, 50), c(38, 49), c(48, 50), c(48, 56), c(38, 59), c(26, 56)) ) %>% move( trajectory = c(15, 50), start = 5000, end = 3000, snapshots = 8 ) plot_map(yam)"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"plotting-multiple-slendr-objects","dir":"Articles","previous_headings":"","what":"Plotting multiple slendr objects","title":"Introduction and basic tutorial","text":"addition plotting individual population ranges, generic function plot_map() can handle combination population ranges, can also partition individual facets. useful visual inspection specified model, looking potential issues export individual spatio-temporal maps. Obviously, lot multi-dimensional information: see better way explore slendr model interactively.","code":"plot_map(afr, ooa, ehg, eur, ana, yam)"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"defining-gene-flow-events","dir":"Articles","previous_headings":"","what":"Defining gene flow events","title":"Introduction and basic tutorial","text":"way slendr implements gene flow events calling gene_flow() function. function straightforward interface, shown . One thing note default, populations gene flow events must overlapping spatial ranges order simulate gene flow. probably rather obvious, populations can’t mix space-time don’t overlap given point space-time. example, look spatial boundaries plotted , ’ll see European African populations don’t overlap population ranges. try instruct slendr simulate geneflow , get error: error message instructs us visually verify case, can done slendr’s plot_map() function optional parameter pop_facets = F (set TRUE default). Many models include multiple gene flow events, can collect simple R list: gene_flow() function simply returns data frame collecting geneflow parameters compile_model() step :","code":"gf <- gene_flow(from = eur, to = afr, rate = 0.1, start = 20000, end = 15000) Error: No overlap between population ranges of EUR and AFR at time 20000. Please check the spatial maps of both populations by running `plot_map(eur, afr)` and adjust them accordingly. Alternatively, in case this makes sense for your model, you can add `overlap = F` which will instruct slendr to simulate gene flow without spatial overlap between populations. gf <- list( gene_flow(from = ana, to = yam, rate = 0.5, start = 6500, end = 6400, overlap = FALSE), gene_flow(from = ana, to = eur, rate = 0.5, start = 8000, end = 6000), gene_flow(from = yam, to = eur, rate = 0.75, start = 4000, end = 3000) ) gf #> [[1]] #> from_name to_name tstart tend rate overlap #> 1 ANA YAM 6500 6400 0.5 FALSE #> #> [[2]] #> from_name to_name tstart tend rate overlap #> 1 ANA EUR 8000 6000 0.5 TRUE #> #> [[3]] #> from_name to_name tstart tend rate overlap #> 1 YAM EUR 4000 3000 0.75 TRUE"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"compile-the-whole-model-and-load-it-in-slim","dir":"Articles","previous_headings":"","what":"Compile the whole model and load it in SLiM","title":"Introduction and basic tutorial","text":"crucial function slendr compile_model(). takes population ranges defined across space time, together list gene flow events (optional, since models won’t include gene flow), proceeds converting vectorized spatial ranges raster bitmaps. Furthermore, compiles information split times, \\(N_e\\) values, gene flow directions, times, rates series tables. saved automatically dedicated directory format understood back end SLiM script provided slendr (). files model directory look like? Ideally, user never worry ; fact, whole purpose slendr let work much higher level abstraction without worrying low-level details. said, might find useful see things look like behind curtain… First , can inspect contents directory see , indeed, contain defined spatial maps (now PNG files, SLiM requires). also contains series tab-delimited configuration tables. tables contain summaries model parameters defined graphically , namely: table population splits: table geneflow events: finally, table populations whose spatial maps updated throughout simulation, well times updates (table rather large, ’re showing ). object returned compile_model() function (called model ) binds information together. fact, easier debugging sanity checking, carries locations tables (well important information) inside , elements list: model$splits, model$geneflows, etc. case ’d want separate model specification running different scripts, slendr includes function read_model() just purpose:","code":"model_dir <- paste0(tempfile(), \"_tutorial-model\") model <- compile_model( populations = list(afr, ooa, ehg, eur, ana, yam), # populations defined above gene_flow = gf, # gene-flow events defined above generation_time = 30, resolution = 10e3, # resolution in meters per pixel competition = 130e3, mating = 100e3, # spatial interaction in SLiM dispersal = 70e3, # how far will offspring end up from their parents path = model_dir ) list.files(model_dir, pattern = \"*.jpg\") #> character(0) read.table(file.path(model_dir, \"populations.tsv\"), header = TRUE) #> pop parent N tsplit_gen tsplit_orig tremove_gen tremove_orig #> 1 AFR __pop_is_ancestor 3000 1 52000 -1 -1 #> 2 OOA AFR 500 34 51000 901 25000 #> 3 EHG OOA 1000 801 28000 1534 6000 #> 4 ANA OOA 3000 801 28000 1601 4000 #> 5 EUR EHG 2000 901 25000 -1 -1 #> 6 YAM EHG 500 1501 7000 1651 2500 #> pop_id parent_id #> 1 0 -1 #> 2 1 0 #> 3 2 1 #> 4 3 1 #> 5 4 2 #> 6 5 2 read.table(file.path(model_dir, \"geneflow.tsv\"), header = TRUE) #> from to rate overlap tstart_gen tstart_orig tend_gen tend_orig from_id to_id #> 1 ANA YAM 0.50 0 1518 6500 1521 6400 3 5 #> 2 ANA EUR 0.50 1 1468 8000 1534 6000 3 4 #> 3 YAM EUR 0.75 1 1601 4000 1634 3000 5 4 loaded_model <- read_model(model_dir)"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"visualize-the-entire-history-of-splits-and-gene-flow","dir":"Articles","previous_headings":"","what":"Visualize the entire history of splits and gene flow","title":"Introduction and basic tutorial","text":"code snippets , defined simple history European populations last 50000 years. history includes population splits gene flow events, well demographic changes. slendr tries make formal specification spatio-temporal population dynamics concise possible, hard really visualize everything happen SLiM side simulation starts just code alone. purpose, package includes function named plot_model() takes information relationships populations (.e., population gene flow objects defined ) plots form -called admixture graph (see discussion admixture graph concept). One important thing note unlike traditional admixture graphs node/population present , full slendr graph single population can participate many gene flow events course history. visualized assigning color population, different nodes color represent snapshots time demographic event affecting population happens.","code":"plot_model(model, proportions = TRUE)"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"interactive-exploration-of-spatio-temporal-models","dir":"Articles","previous_headings":"","what":"Interactive exploration of spatio-temporal models","title":"Introduction and basic tutorial","text":"slightly fancier way visualize models implemented function explore_model(). function accepts compiled model parameter spawns R shiny-based browser app makes possible click time snapshots interactively visualize spatial maps time point.","code":"explore_model(model)"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"running-the-simulation","dir":"Articles","previous_headings":"","what":"Running the simulation","title":"Introduction and basic tutorial","text":"way feed entire serialized model SLiM slim() function, understands format model directory created compile_model() function generates SLiM script (using back end skeleton script part package can found calling system.file(\"scripts/script.slim\", package = \"slendr\"), case ’d like peek internals). output slendr simulation tree-sequence file (produced SLiM simulation behind scenes). tree sequence automatically loaded R returned user: lots slendr allows , terms simulation , also terms analyzing tree-sequence data. list provides list additional resources might want look .","code":"ts <- slim(model, sequence_length = 100000, recombination_rate = 1e-8) ts #> ╔═══════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════╣ #> ║Trees │ 133║ #> ╟───────────────┼───────╢ #> ║Sequence Length│ 100000║ #> ╟───────────────┼───────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼───────╢ #> ║Sample Nodes │ 10000║ #> ╟───────────────┼───────╢ #> ║Total Size │2.7 MiB║ #> ╚═══════════════╧═══════╝ #> ╔═══════════╤═════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪═════╪═════════╪════════════╣ #> ║Edges │18682│583.8 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Individuals│12838│ 1.2 MiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Nodes │18332│681.0 KiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Populations│ 6│ 2.6 KiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Provenances│ 1│ 34.7 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧═════╧═════════╧════════════╝"},{"path":"https://www.slendr.net/articles/vignette-01-tutorial.html","id":"more-information","dir":"Articles","previous_headings":"","what":"More information","title":"Introduction and basic tutorial","text":"vignette described basic features slendr package already quite long. much slendr demonstrated . instance: can tweak parameters influencing dispersal dynamics (“clumpy” populations , far offspring can migrate parents, etc.) change dynamics evolve time. See vignette information. can use slendr program non-spatial models, means standard, Wright-Fisher demographic model can simulated lines R code , instance, plugged Approximate Bayesian Computation pipeline analyses leveraging readily available R packages. can find vignette much detailed example vignette SLiM msprime back ends. can build complex spatial models still abstract (assuming real geographic location), including traditional simulations demes lattice structure. complete example shown vignette. SLiM saves data .trees tree-sequence file format, thanks R package reticulate interfacing Python code incredible power tskit pyslim process simulated data massive scale right fingertips, within convenient environment R. See much detailed example vignette vignette extensive tutorial feature.","code":""},{"path":"https://www.slendr.net/articles/vignette-02-grid-model.html","id":"simple-two-dimensional-grid-model","dir":"Articles","previous_headings":"","what":"Simple two-dimensional grid model","title":"Demes on a regular spatial grid","text":"First, let’s load slendr R package create two-dimensional abstract world map: Next, define helper function ) create single slendr population object, b) place population appropriate coordinate lattice world map based numeric identifier population (runs 1 \\(n \\times n\\) , n total number demes along one side regular grid): defined population construction function, let’s build model. Let’s say want create regular grid n × n populations, N individuals population: Let’s plot whole spatial population configuration, make sure set things correctly: far, way model specified, population stuck circular “island”. can change programming gene flow events using slendr function gene_flow(). , let’s first program simple helper function generate gene flow events according neighborhood relationships two-dimensional grid, allowing population exchange migrants neighbors (making sure coordinates population stay within grid using simple modulo arithmetic population index ). Let’s test function. gene flow events population lower left corner grid (, first population series)? everything works, population allowed exchange migrants neighbor right (population number 2) neighbor . Looks right! Let’s generate entire set continuous gene flow events: total number individual gene flow events : Finally, can compile whole model: familiar SLiM manual recognize model described section 5.3.3. Finally, can run simulation using slim() function.","code":"library(slendr) init_env() #> The interface to all required Python modules has been activated. map <- world( xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\" ) create_pop <- function(i, n_side, map, N, radius) { # get dimensions of the world map dim <- c(diff(attr(map, \"xrange\")), diff(attr(map, \"yrange\"))) # position of the i-th population on the two-dimensional lattice grid coords <- c((i - 1) %% n_side, (i - 1) %/% n_side) center <- coords / n_side * dim + dim / (2 * n_side) pop <- tryCatch({ population( name = sprintf(\"pop%d\", i), N = N, time = 1, map = map, center = center + c(attr(map, \"xrange\")[1], attr(map, \"yrange\")[1]), radius = radius ) }, error = function(e) NULL) pop } n <- 5 populations <- seq(1, n * n) %>% lapply(create_pop, n_side = n, map = map, N = 100, radius = 40) do.call(plot_map, populations) + ggplot2::theme(legend.position = \"none\") set_geneflow <- function(i, n_side, rate, start, end, populations) { pop <- populations[[i]] # get the position of the i-th population on the n*n grid coords <- c((i - 1) %% n_side, (i - 1) %/% n_side) # get coordinates of the i-th population's neighbors on the grid neighbor_pos <- list( c(coords[1] - 1, coords[2]), c(coords[1] + 1, coords[2]), c(coords[1], coords[2] + 1), c(coords[1], coords[2] - 1) ) # generate geneflow events for population coordinates inside the grid geneflows <- lapply(neighbor_pos, function(pos) { if (any(pos < 0 | pos >= n_side)) return(NULL) neighbor <- populations[[pos[2] * n_side + pos[1] + 1]] if (is.null(neighbor)) return(NULL) rbind( gene_flow(from = pop, to = neighbor, rate = rate, start = start, end = end, overlap = FALSE), gene_flow(from = neighbor, to = pop, rate = rate, start = start, end = end, overlap = FALSE) ) }) %>% do.call(rbind, .) geneflows } set_geneflow(1, n, rate = 0.1, start = 2, end = 1000, populations) #> from_name to_name tstart tend rate overlap #> 1 pop1 pop2 2 1000 0.1 FALSE #> 2 pop2 pop1 2 1000 0.1 FALSE #> 3 pop1 pop6 2 1000 0.1 FALSE #> 4 pop6 pop1 2 1000 0.1 FALSE geneflows <- seq(1, n * n) %>% lapply(set_geneflow, n, rate = 0.05, start = 2, end = 1000, populations) %>% do.call(rbind, .) %>% unique # filter out duplicate events due to symmetries nrow(geneflows) #> [1] 80 model <- compile_model( populations = populations, gene_flow = geneflows, generation_time = 1, resolution = 10, competition = 10, mating = 10, dispersal = 10, simulation_length = 1000 ) ts <- slim(model, sequence_length = 10000, recombination_rate = 0) # simulate a single 10kb locus ts #> ╔═══════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════╣ #> ║Trees │ 1║ #> ╟───────────────┼───────╢ #> ║Sequence Length│ 10000║ #> ╟───────────────┼───────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼───────╢ #> ║Sample Nodes │ 5000║ #> ╟───────────────┼───────╢ #> ║Total Size │1.3 MiB║ #> ╚═══════════════╧═══════╝ #> ╔═══════════╤════╤═════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪═════════╪════════════╣ #> ║Edges │9065│283.3 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Individuals│6316│618.4 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Nodes │9090│338.0 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Populations│ 25│ 5.7 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Provenances│ 1│ 34.6 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧════╧═════════╧════════════╝"},{"path":"https://www.slendr.net/articles/vignette-02-grid-model.html","id":"population-grid-on-a-real-geographic-landscape","dir":"Articles","previous_headings":"","what":"Population grid on a real geographic landscape","title":"Demes on a regular spatial grid","text":"can take things one step . wanted similar thing (.e. simulate regularly spaced demes) real geographic context? Let’s zoom interesting part world create grid demes using helper function create_pop defined (population boundary 300 km diameter): course, lay regular grid across map world, population boundaries fall outside African continent. solve issue, go list populations filter least 50% area land, using another helper function: Let’s plot layout population grid real geographic background: Next, probably set scenario gene flow subpopulations; perhaps interested studying selected allele spreads continent based factors interest. , simulate data spatial model, first compile_model() run SLiM via slim() function. Given process described example , won’t repeating .","code":"map <- world( xrange = c(-25, 55), yrange = c(-32, 35), crs = 4326 ) n <- 20 populations <- seq(1, n * n) %>% lapply(create_pop, n_side = n, map = map, N = 100, radius = 1.5) continent <- region( map = map, polygon = list( c(-10, 35), c(-20, 20), c(-15, 8), c(-10, 5), c(0, 2), c(20, -40), c(35, -32), c(50, -25), c(55, -10), c(50, 0), c(53, 13), c(45, 10), c(37, 20), c(32, 30), c(16, 38), c(0, 38) ) ) check_area <- function(pop, map, continent) { if (is.null(pop)) return(NULL) # total population area pop_area <- area(pop)$area # population area overlapping a map map_area <- area(overlap(pop, map)) # population area overlapping African continent continent_area <- area(overlap(pop, continent)) # at least 50% of population's boundary be on land, and it must fall # on to the African continent itself if (continent_area == 0 || (map_area / pop_area) < 0.5) return(NULL) else return(pop) } filtered <- lapply(populations, check_area, map, continent) %>% Filter(Negate(is.null), .) do.call(plot_map, filtered) + ggplot2::theme(legend.position = \"none\")"},{"path":"https://www.slendr.net/articles/vignette-02-grid-model.html","id":"more-customized-spatial-model","dir":"Articles","previous_headings":"","what":"More customized spatial model","title":"Demes on a regular spatial grid","text":"want introduce spatiality model need manual control position subpopulation, can course customize spatial layout much detail. Consider followin map South America: Let’s lay demes scattered, irregular fashion. illustration purposes, define population’s geographic range circle radius 200 km. Importantly, note introduced one ancestral population population associated location world map! want simulate data coalescent backend, formally encode population genealogies eventually coalesce. words, models specified run msprime() back end contain isolated demes formally descend single ancestor run models msprime, get error infinite coalescent times. formally introduce ancestral population : Furthermore, let’s say fairly good idea complex interaction/gene-flow network deme, can encode like (instead forcing regular arrangement demes gene-flow interactions previous examples): Now can compile model `twist, however: try simulate data non-spatial way using msprime, skip serialization model data disk, skipping spatial interaction dispersal parameters. words, care simulating demographic model traditional, Wright-Fisher, random-mating demes gene flow , dispersal within individual deme. ? Mostly just demonstrate possible! However, certainly situations “half-spatial” model useful – instance, situation within-deme individual dynamics interest, location subpopulation . can make sure demographic model specified correctly quickly visualizing : can also plot spatial organization demes map glory, including gene flow events (one arrow per unidirectional gene flow). Note get warning message stating (non-spatial) ancestral population won’t visualized map: Finally, can simulate tree sequence model! Notice simulating data using msprime(), effectively dropping continuous space dimension model. situation, map serves visual aid, making easier set complex “spatial” position demes map.","code":"xrange <- c(-90, -20) yrange <- c(-58, 15) map <- world(xrange = xrange, yrange = yrange, crs = \"EPSG:31970\") #> Reading layer `ne_110m_land' from data source #> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpI0CWYj/naturalearth/ne_110m_land.shp' #> using driver `ESRI Shapefile' #> Simple feature collection with 127 features and 3 fields #> Geometry type: POLYGON #> Dimension: XY #> Bounding box: xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513 #> Geodetic CRS: WGS 84 plot_map(map) # non-spatial ancestral population p_anc <- population(\"p_anc\", N = 1000, time = 1) # spatial populations p1 <- population(\"p1\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-75, 0), radius = 200e3) p2 <- population(\"p2\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-60, 5), radius = 200e3) p3 <- population(\"p3\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-65, -5), radius = 200e3) p4 <- population(\"p4\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-60, -20), radius = 200e3) p5 <- population(\"p5\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-65, -35), radius = 200e3) p6 <- population(\"p6\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-69, -42), radius = 200e3) p7 <- population(\"p7\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-51, -10), radius = 200e3) p8 <- population(\"p8\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-45, -15), radius = 200e3) p9 <- population(\"p9\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-71, -12), radius = 200e3) p10 <- population(\"p10\", N = 1000, time = 500, parent = p_anc, map = map, center = c(-55, -25), radius = 200e3) gf <- list( gene_flow(p1, p2, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p2, p1, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p1, p3, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p3, p1, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p2, p3, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p3, p2, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p2, p7, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p7, p2, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p3, p7, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p7, p3, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p7, p8, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p8, p7, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p4, p7, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p7, p4, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p4, p5, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p5, p4, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p5, p6, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p6, p5, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p3, p4, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p4, p3, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p1, p9, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p9, p1, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p3, p9, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p9, p3, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p4, p9, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p9, p4, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p10, p4, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p4, p10, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p10, p8, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p8, p10, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p10, p5, 0.1, 1000, 2000, overlap = FALSE), gene_flow(p5, p10, 0.1, 1000, 2000, overlap = FALSE) ) model <- compile_model( populations = list(p_anc, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), gene_flow = gf, generation_time = 1, simulation_length = 5000, serialize = FALSE ) #> Warning: Model containing a mix of spatial and non-spatial populations will be compiled. #> Although this is definitely supported, make sure this is really what you want. #> Warning: Spatial models must be serialized to disk for SLiM to simulate data from. #> Compiled like this, your model can only be simulated with msprime. plot_model(model) plot_map(model, gene_flow = TRUE) #> Warning: All gene-flow event will be visualized at once. If you wish to visualize #> gene flows at a particular point in time, use the `time` argument. #> Warning: Non-spatial populations in your model won't be visualized ts <- msprime(model, sequence_length = 10e6, recombination_rate = 1e-8, random_seed = 42) ts #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 34057║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 10000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 22000║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 9.4 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │182742│ 5.6 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 11000│300.8 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │ 74344│ 2.0 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 11│605 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 1│ 10.5 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧══════╧═════════╧════════════╝"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"setting-up-python-environment","dir":"Articles","previous_headings":"","what":"Setting up Python environment","title":"Tree-sequence processing and statistics","text":"First, order able interface tskit pyslim using reticulate package (run simulations using msprime, ), need working Python environment required Python modules pyslim, tskit msprime already installed. setting Python environments can quite hassle, slendr provides single function setup_env() make things easier. call without arguments, slendr automatically download, install, setup completely separate Python environment (based “miniconda” distribution) just slendr activate background. important stress setup_env() interfere way Python installations might already computer. Python installation environment entirely isolated used just purpose slendr workflows. Python environment set , can activate calling: can use another built-function check_env() make sure slendr installed configured correct environment us: Now ’re good go ready simulate analyse tree sequence outputs R!","code":"setup_env() init_env() #> The interface to all required Python modules has been activated. check_env() #> Summary of the currently active Python environment: #> #> Python binary: /Users/mp/Library/r-miniconda-arm64/envs/Python-3.12_msprime-1.3.0_tskit-0.5.6_pyslim-1.0.4_tspop-0.0.2/bin/python #> Python version: 3.12.1 | packaged by conda-forge | (main, Dec 23 2023, 08:01:35) [Clang 16.0.6 ] #> #> slendr requirements: #> - tskit: version 0.5.6 ✓ #> - msprime: version 1.3.0 ✓ #> - pyslim: version 1.0.4 ✓ #> - tspop: present ✓"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"model-of-neanderthal-introgression-into-eurasians","dir":"Articles","previous_headings":"Setting up Python environment","what":"Model of Neanderthal introgression into Eurasians","title":"Tree-sequence processing and statistics","text":"First, let’s set simple non-spatial model Neanderthal introgression using slendr. essentially procedure shown another vignette introducing non-spatial slendr models. different spatial model, except left map argument calling population(). ’s toy model visualized “demographic graph” sorts (.e., tree-like structure specifying population splits additional edges representing gene flow events). particularly illuminating simple example, ’s always worth keeping mind graph embedded within every slendr model can always invoked make sure model ’re setting correct:","code":"library(ggplot2) library(dplyr) #> #> Attaching package: 'dplyr' #> The following objects are masked from 'package:stats': #> #> filter, lag #> The following objects are masked from 'package:base': #> #> intersect, setdiff, setequal, union set.seed(314159) # create the ancestor of everyone and a chimpanzee outgroup # (we set both N = 1 to reduce the computational time for this model) chimp <- population(\"CH\", time = 6.5e6, N = 1000) # two populations of anatomically modern humans: Africans and Europeans afr <- population(\"AFR\", parent = chimp, time = 6e6, N = 10000) eur <- population(\"EUR\", parent = afr, time = 70e3, N = 5000) # Neanderthal population splitting at 600 ky ago from modern humans # (becomes extinct by 40 ky ago) nea <- population(\"NEA\", parent = afr, time = 600e3, N = 1000, remove = 40e3) # 3% Neanderthal introgression into Europeans between 55-50 ky ago gf <- gene_flow(from = nea, to = eur, rate = 0.03, start = 55000, end = 45000) model <- compile_model( populations = list(chimp, nea, afr, eur), gene_flow = gf, generation_time = 30, path = paste0(tempfile(), \"_introgression\") ) cowplot::plot_grid( plot_model(model, sizes = FALSE), plot_model(model, sizes = FALSE, log = TRUE), nrow = 1 )"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"scheduling-of-sampling-events","dir":"Articles","previous_headings":"","what":"Scheduling of sampling events","title":"Tree-sequence processing and statistics","text":"Now defined model, sample data ? Ideally, like schedule sampling events given time, sampling defined number individuals given population. slendr provides function schedule_sampling() serves define sampling schedule automatically enforces populations already (.e. appearance simulation) still (removed simulation) present sampled . example, want sample two Neanderthal individuals (older one Altai Neanderthal published Pruefer et al. 2014, younger one Vindija Neanderthal published Pruefer et al., 2017). two genomes need estimate Neanderthal ancestry proportion using -called \\(f_4\\)-ratio statistic (, also see Petr et al., PNAS 2019): can see, schedule_sampling() function simply accepts vector times remembering schedule, list pairs (, ) encoding populations many individuals remembered time points given times vector. Next, want sample present-day individuals: outgroup representing chimpanzee, couple Africans Europeans: can see , schedule_sampling() function returns plain old data frame simple structure three columns: time, population name, number individuals. means can define sampling events using whatever input data might already available (radiocarbon-dated ancient DNA samples Excel sheet publication). instance, lot interest estimate trajectory Neanderthal ancestry Europe time using ancient DNA data anatomically modern human individuals (also called early modern humans, EMH) across last couple tens thousands years. can simulate something close available EMH ancient DNA data set last 50 thousand years running : samples single ancient European individuals randomly chosen times 40 10 ky ago. One nice feature schedule_sampling() function schedules sampling events population, population present simulation given time. makes possible simply take wide time range sampling, specify populations sizes samples, let function generate sampling events populations present time. reason stricter control sampling required, behavior can switched setting strict = TRUE like : Now already model object ready, can simulate data , sampling individuals according sampling schedule. Although use slim() function shown previous vignettes, case run simulation msprime() coalescent back end. , model non-spatial using coalescent simulator much efficient forward simulation. Switching msprime SLiM back ends slendr demonstrated much detail dedicated vignette. simulation back end utilized msprime() function (well slim() function) produces tree-sequence output immediately loaded ready downstream analysis. Note bind individual sampling schedule data frames using rbind function provided base R (show , sampling schedule really just data frame can manipulate ).","code":"nea_samples <- schedule_sampling(model, times = c(70000, 40000), list(nea, 1)) nea_samples #> # A tibble: 2 × 7 #> time pop n y_orig x_orig y x #> #> 1 40000 NEA 1 NA NA NA NA #> 2 70000 NEA 1 NA NA NA NA present_samples <- schedule_sampling(model, times = 0, list(chimp, 1), list(afr, 5), list(eur, 10)) present_samples #> # A tibble: 3 × 7 #> time pop n y_orig x_orig y x #> #> 1 0 CH 1 NA NA NA NA #> 2 0 AFR 5 NA NA NA NA #> 3 0 EUR 10 NA NA NA NA emh_samples <- schedule_sampling(model, times = runif(n = 40, min = 10000, max = 40000), list(eur, 1)) emh_samples #> # A tibble: 40 × 7 #> time pop n y_orig x_orig y x #> #> 1 10320 EUR 1 NA NA NA NA #> 2 11188 EUR 1 NA NA NA NA #> 3 11396 EUR 1 NA NA NA NA #> 4 11529 EUR 1 NA NA NA NA #> 5 11927 EUR 1 NA NA NA NA #> 6 12675 EUR 1 NA NA NA NA #> 7 13689 EUR 1 NA NA NA NA #> 8 13744 EUR 1 NA NA NA NA #> 9 14775 EUR 1 NA NA NA NA #> 10 16362 EUR 1 NA NA NA NA #> # ℹ 30 more rows # this attempts to sample a Neanderthal individual at a point when Neanderthals # are already extinct, resulting in an error schedule_sampling(model, times = 10000, list(nea, 1), strict = TRUE) Error: Cannot schedule sampling for 'NEA' at time 10000 because the population will not be present in the simulation at that point. Consider running this function with `strict = FALSE` which will automatically retain only valid sampling events. ts <- msprime( model, sequence_length = 100e6, recombination_rate = 1e-8, samples = rbind(nea_samples, present_samples, emh_samples), random_seed = 314159, verbose = TRUE ) #> -------------------------------------------------- #> msprime command: #> #> /Users/mp/Library/r-miniconda-arm64/envs/Python-3.12_msprime-1.3.0_tskit-0.5.6_pyslim-1.0.4_tspop-0.0.2/bin/python /private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpQbon7e/filee17860409253_introgression/script.py --seed 314159 --model /private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpQbon7e/filee17860409253_introgression --output /var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpQbon7e/filee1784cccb6b3.trees --sequence-length 100000000 --recombination-rate 1e-08 --sampling-schedule /var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpQbon7e/filee17859cbb4d3 --verbose #> -------------------------------------------------- #> #> Tree sequence was saved to: #> /var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpQbon7e/filee1784cccb6b3.trees #> Loading the tree-sequence file... ts #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 240041║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 116║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 40.0 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │916588│ 28.0 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 58│ 1.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │189654│ 5.1 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 1│ 7.0 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧══════╧═════════╧════════════╝"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"r-interface-for-tskit-and-pyslim","dir":"Articles","previous_headings":"","what":"R interface for tskit and pyslim","title":"Tree-sequence processing and statistics","text":"Tree-sequences one revolutionary developments population genetics last couple decades number reasons. One possibility store extremely large data sets succinctly encoding entire evolutionary history sample individuals series correlated tree genealogies along genome. Going much detail topic clearly beyond scope tutorial, especially everything explain much better elsewhere. Instead, demonstrate rest vignette can access manipulate tree-sequence outputs generated slendr models perform various statistics using Python modules tskit pyslim directly slendr, without leave R! key magical R package reticulate creates seamless binding Python modules R. means even don’t know Python, slendr allows quite lot tree-sequences R. course, proficient Python user, needs said tree-sequence file generated slendr & SLiM, can easily perform every conceivable analysis directly using tskit. intention show can continue working tree-sequence files R even run entire slendr simulation.","code":""},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"loading-and-processing-tree-sequence-output-files","dir":"Articles","previous_headings":"","what":"Loading and processing tree-sequence output files","title":"Tree-sequence processing and statistics","text":"default, msprime() slim() run produce tree-sequence object (saved temporary file) immediately load . Thus, use-cases, explicit loading simulated tree sequence needed. said, sake completeness, let’s run simulation specify custom path tree-sequence file . case tree-sequence output saved custom location disk, can load tree sequence using slendr function ts_load(). ’re dealing tree sequence produced SLiM back end (case ), can also instruct function simplify tree-sequence individuals explicitly sampled (recall sampling schedule set schedule_sampling() function ). Note provide model object generated compile_model() order model annotation information simulated tree-sequence data (, loading): surprisingly, get output got printed tree sequence returned msprime() function. shows normal circumstances, loading output manually via ts_load() needed. try simplify msprime-generated tree sequence, get warning. tree sequence already simplified form, definition coming coalescent simulator. default, simplification trims tree sequence remembered individuals (.e. explicitly scheduled sampling), true every msprime tree sequence. Alternatively, can also narrow simplification defined set individuals using simplify_to = argument. Internally, simplification implemented dedicated function ts_simplify() can always call explicitly, like : Similarly, slendr provides function ts_recapitate() performs [recapitation]https://tskit.dev/pyslim/docs/latest/tutorial.html#recapitation). , needed msprime tree sequence, fully coalesced (recapitated) definition. current tree sequence object, simply get warning informing us ’re attempting something effect: can make sure tree sequence fully coalesced calling another slendr function ts_coalesced(). useful dealing slim()-produced tree sequences: might noticed simulate mutations SLiM run. computational efficiency. Luckily, tree-sequence contains complete history sample individuals makes easy sprinkle mutations genealogies simulation . can add mutations given rate running: processed simulated tree sequence, can calculate basic statistics simulated data. However, , first like note everything rest vignette (.e. whenever call function prefix ts_*() slendr), interfacing tskit Python module hood. goal capture analyses one might want perform tree-sequences R wrap neat interface indistinguishable R function—, , reason reticulate created first place (making various Python data science modules appear regular R packages).","code":"output_file <- tempfile() ts <- msprime( model, sequence_length = 100e6, recombination_rate = 1e-8, samples = rbind(nea_samples, present_samples, emh_samples), output = output_file, random_seed = 314159 ) output_file #> [1] \"/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//RtmpQbon7e/filee17821d8acf8\" ts <- ts_load(output_file, model) ts #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 240041║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 116║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 40.0 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │916588│ 28.0 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 58│ 1.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │189654│ 5.1 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 1│ 7.0 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧══════╧═════════╧════════════╝ ts_simplify(ts) #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 238681║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 116║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 36.7 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │864772│ 26.4 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 58│ 1.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │139203│ 3.7 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 2│ 7.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧══════╧═════════╧════════════╝ ts_small <- ts_simplify(ts, simplify_to = c(\"CH_1\", \"NEA_1\", \"NEA_2\", \"AFR_1\", \"AFR_2\", \"EUR_20\", \"EUR_50\")) ts_small #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 132496║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 14║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 19.0 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │441206│ 13.5 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 7│220 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │ 79249│ 2.1 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 2│ 7.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧══════╧═════════╧════════════╝ ts <- ts_recapitate(ts, recombination_rate = 1e-8, Ne = 10000) ts_coalesced(ts) #> [1] TRUE ts <- ts_mutate(ts, mutation_rate = 1e-8, random_seed = 314159) ts #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 240041║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 116║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 76.8 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │916588│ 28.0 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 58│ 1.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │623249│ 22.0 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │189654│ 5.1 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 2│ 7.8 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │621331│ 14.8 MiB│ No║ #> ╚═══════════╧══════╧═════════╧════════════╝"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"visualisation-of-trees-and-tree-sequences","dir":"Articles","previous_headings":"","what":"Visualisation of trees and tree-sequences","title":"Tree-sequence processing and statistics","text":"Now introduce function ts_phylo() can used extract one tree tree-sequence (either -th tree sequence, tree overlapping -th position simulated genome, depending value mode argument) convert phylo class, standard format phylogenetic trees R world. phylo format, see packages ape, phangorn, phytools. type tree object R console, can verify got ordinary phylo object: means whole R phylogenetic ecosystem disposal analyze trees. instance can use powerful package ggtree plot tree just extracted:","code":"# extract the 42nd tree in the tree sequence tree <- ts_phylo(ts_small, 42 - 1) #> Starting checking the validity of tree... #> Found number of tips: n = 14 #> Found number of nodes: m = 13 #> Done. tree #> #> Phylogenetic tree with 14 tips and 13 internal nodes. #> #> Tip labels: #> 13 (EUR_50), 12 (EUR_50), 11 (CH_1), 10 (CH_1), 9 (AFR_2), 8 (AFR_2), ... #> Node labels: #> 77386, 70, 2699, 5175, 5199, 6642, ... #> #> Rooted; includes branch lengths. library(ggtree) #> ggtree v3.10.0 For help: https://yulab-smu.top/treedata-book/ #> #> If you use the ggtree package suite in published research, please cite #> the appropriate paper(s): #> #> Guangchuang Yu, David Smith, Huachen Zhu, Yi Guan, Tommy Tsan-Yuk Lam. #> ggtree: an R package for visualization and annotation of phylogenetic #> trees with their covariates and other associated data. Methods in #> Ecology and Evolution. 2017, 8(1):28-36. doi:10.1111/2041-210X.12628 #> #> Guangchuang Yu. Data Integration, Manipulation and Visualization of #> Phylogenetic Trees (1st edition). Chapman and Hall/CRC. 2022, #> doi:10.1201/9781003279242 #> #> G Yu. Data Integration, Manipulation and Visualization of Phylogenetic #> Trees (1st ed.). Chapman and Hall/CRC. 2022. ISBN: 9781032233574 ggtree(tree) + geom_point2(aes(subset = !isTip)) + # points for internal nodes geom_tiplab() + # sample labels for tips hexpand(0.1) # make more space for the tip labels library(ape) plot(tree) nodelabels()"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"accessing-tskit-functionality-directly","dir":"Articles","previous_headings":"","what":"Accessing tskit functionality directly","title":"Tree-sequence processing and statistics","text":"mentioned previous section, goal vignette show use slendr perform main tree-sequence operations using convenient R interface tskit. However, always keep mind restricted subset tskit functionality slendr translated R (.e. functions prefix ts_). Thanks incredible R package reticulate, can access Python methods object variables directly, using $ operator. example, instead calling function ts_coalesced() tree-sequence , check trees coalesced running following snippet instead (note inefficient ’re operation first one hundred trees): believe makes sense use R interface whenever possible (even makes many operations little bit convenient). However, functionality slendr missing, can always resort accessing Python objects directly just demonstrated. can verify methods attributes Python tree-sequence object still accessible R: fact, recognize elements output examples involving ts_ functions vignette! short, blackbox—slendr provides slightly convenient layer tskit R users.","code":"# iterate over all trees in the tree-sequence and check if each # has only one root (i.e. is fully coalesced) - note that Python # lists are 0-based, which is something we need to take care of all(sapply(seq_len(ts$num_trees)[1:100], function(i) ts$at_index(i - 1)$num_roots == 1)) names(ts) #> [1] \"alignments\" \"allele_frequency_spectrum\" #> [3] \"as_fasta\" \"as_nexus\" #> [5] \"as_vcf\" \"aslist\" #> [7] \"at\" \"at_index\" #> [9] \"breakpoints\" \"check_index\" #> [11] \"coalescence_time_distribution\" \"coiterate\" #> [13] \"count_topologies\" \"decapitate\" #> [15] \"delete_intervals\" \"delete_sites\" #> [17] \"diffs\" \"discrete_genome\" #> [19] \"discrete_time\" \"divergence\" #> [21] \"divergence_matrix\" \"diversity\" #> [23] \"draw_svg\" \"draw_text\" #> [25] \"dump\" \"dump_tables\" #> [27] \"dump_text\" \"edge\" #> [29] \"edge_diffs\" \"edges\" #> [31] \"edges_child\" \"edges_left\" #> [33] \"edges_parent\" \"edges_right\" #> [35] \"edgesets\" \"equals\" #> [37] \"f2\" \"f3\" #> [39] \"f4\" \"file_uuid\" #> [41] \"first\" \"Fst\" #> [43] \"genealogical_nearest_neighbours\" \"general_stat\" #> [45] \"genetic_relatedness\" \"genetic_relatedness_weighted\" #> [47] \"genotype_matrix\" \"get_ll_tree_sequence\" #> [49] \"get_num_mutations\" \"get_num_nodes\" #> [51] \"get_num_records\" \"get_num_sites\" #> [53] \"get_num_trees\" \"get_pairwise_diversity\" #> [55] \"get_population\" \"get_sample_size\" #> [57] \"get_samples\" \"get_sequence_length\" #> [59] \"get_time\" \"haplotypes\" #> [61] \"has_reference_sequence\" \"ibd_segments\" #> [63] \"impute_unknown_mutations_time\" \"indexes_edge_insertion_order\" #> [65] \"indexes_edge_removal_order\" \"individual\" #> [67] \"individual_locations\" \"individual_populations\" #> [69] \"individual_times\" \"individuals\" #> [71] \"individuals_flags\" \"individuals_location\" #> [73] \"individuals_population\" \"individuals_time\" #> [75] \"kc_distance\" \"keep_intervals\" #> [77] \"last\" \"ll_tree_sequence\" #> [79] \"load\" \"load_tables\" #> [81] \"ltrim\" \"max_root_time\" #> [83] \"max_time\" \"mean_descendants\" #> [85] \"metadata\" \"metadata_schema\" #> [87] \"migration\" \"migrations\" #> [89] \"migrations_dest\" \"migrations_left\" #> [91] \"migrations_node\" \"migrations_right\" #> [93] \"migrations_source\" \"migrations_time\" #> [95] \"min_time\" \"mutation\" #> [97] \"mutations\" \"mutations_node\" #> [99] \"mutations_parent\" \"mutations_site\" #> [101] \"mutations_time\" \"nbytes\" #> [103] \"newick_trees\" \"node\" #> [105] \"nodes\" \"nodes_flags\" #> [107] \"nodes_individual\" \"nodes_population\" #> [109] \"nodes_time\" \"num_edges\" #> [111] \"num_individuals\" \"num_migrations\" #> [113] \"num_mutations\" \"num_nodes\" #> [115] \"num_populations\" \"num_provenances\" #> [117] \"num_samples\" \"num_sites\" #> [119] \"num_trees\" \"pairwise_diversity\" #> [121] \"parse_windows\" \"population\" #> [123] \"populations\" \"provenance\" #> [125] \"provenances\" \"records\" #> [127] \"reference_sequence\" \"rtrim\" #> [129] \"sample_count_stat\" \"sample_size\" #> [131] \"samples\" \"segregating_sites\" #> [133] \"sequence_length\" \"simplify\" #> [135] \"site\" \"sites\" #> [137] \"sites_position\" \"split_edges\" #> [139] \"subset\" \"table_metadata_schemas\" #> [141] \"tables\" \"tables_dict\" #> [143] \"Tajimas_D\" \"time_units\" #> [145] \"to_macs\" \"to_nexus\" #> [147] \"trait_correlation\" \"trait_covariance\" #> [149] \"trait_linear_model\" \"trait_regression\" #> [151] \"trees\" \"trim\" #> [153] \"union\" \"variants\" #> [155] \"write_fasta\" \"write_nexus\" #> [157] \"write_vcf\" \"Y1\" #> [159] \"Y2\" \"Y3\""},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"calculating-f-statistics","dir":"Articles","previous_headings":"","what":"Calculating f-statistics","title":"Tree-sequence processing and statistics","text":"addition revolutionary breakthrough terms computation efficiency, many statistics often interested population genetics natural consequence direct access tree sequence genealogies, simply genealogies capture true demographic history sample. , can’t go much detail encourage take look paper Ralph et al. duality statistics expressed terms branch lengths traditional summaries based samples genetic variation. instance, functions ts_f2(), ts_f3(), ts_f4() ts_f4ratio() calculate well-known set Patterson’s \\(f\\)-statistics: functions accept mode = argument, specifying whether statistics calculated using mutation site patterns (mode = \"site\", default), branch lengths (mode = \"branch\"), node (mode = \"node\"), well windows argument, similarly “multiway” statistics implemented tskit. See relevant sections official tskit documentation topic. Note previous chunk referred individuals names (numeric IDs nodes tskit Python). allow readability make easier see individuals based specified sampling schedule (names assigned individuals based order sampling). can get overview individuals scheduled sampling (.e. permanently remembered) names helper function ts_samples(): said, like run statistics nodes rather individuals, can simply using integer IDs instead character names function’s interface.","code":"# f2 is a measure of the branch length connecting A and B ts_f2(ts, A = \"EUR_1\", B = \"AFR_1\") #> # A tibble: 1 × 3 #> A B f2 #> #> 1 EUR_1 AFR_1 0.0000448 # f4 is a measure of the drift shared between A and B after their split from C ts_f3(ts, A = \"EUR_1\", B = \"AFR_1\", C = \"CH_1\") #> # A tibble: 1 × 4 #> A B C f3 #> #> 1 EUR_1 AFR_1 CH_1 0.0000130 # this value should be very close to zero (no introgression in Africans) ts_f4(ts, \"AFR_1\", \"AFR_2\", \"NEA_1\", \"CH_1\", mode = \"branch\") #> # A tibble: 1 × 5 #> W X Y Z f4 #> #> 1 AFR_1 AFR_2 NEA_1 CH_1 -118. # this value should be significantly negative (many more ABBA sites # compared to BABA site due to the introgression into Europeans) ts_f4(ts, \"AFR_1\", \"EUR_1\", \"NEA_1\", \"CH_1\", mode = \"branch\") #> # A tibble: 1 × 5 #> W X Y Z f4 #> #> 1 AFR_1 EUR_1 NEA_1 CH_1 -741. ts_samples(ts) #> # A tibble: 58 × 3 #> name time pop #> #> 1 NEA_1 70000 NEA #> 2 NEA_2 40000 NEA #> 3 EUR_1 39171 EUR #> 4 EUR_2 39134 EUR #> 5 EUR_3 37739 EUR #> 6 EUR_4 36531 EUR #> 7 EUR_5 36362 EUR #> 8 EUR_6 35945 EUR #> 9 EUR_7 33900 EUR #> 10 EUR_8 33854 EUR #> # ℹ 48 more rows"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"estimating-neanderthal-ancestry-proportions","dir":"Articles","previous_headings":"","what":"Estimating Neanderthal ancestry proportions","title":"Tree-sequence processing and statistics","text":"Let’s try put new tools practice estimate proportion Neanderthal ancestry Africans Europeans simulated data. can using Patterson’s \\(f_4\\)-ratio statistic implemented ts_f4ratio() function slendr (can find information particular version statistic Petr et al., PNAS 2019): now summarise inferred Neanderthal distribution populations, see Neanderthal ancestry Africans (expected model–Africans receive Neanderthal introgression pulse) small proportion Neanderthal ancestry Europeans (consistent 3% introgression pulse simulated ): exactly specified model configuration , suggesting simulations work . can see quite bit noise ’s simulated small amount sequence. can also plot trajectory Neanderthal ancestry Europe time-window simulated ancient present-day DNA samples: , result consistent empirical estimates Neanderthal ancestry using ancient DNA data (see Petr et al., PNAS 2019).","code":"# first get a table of simulated African and European individuals in the tree-sequence inds <- ts_samples(ts) %>% dplyr::filter(pop %in% c(\"AFR\", \"EUR\")) # estimate the amounts of Neanderthal ancestry in these individuals and add # these values to the table inds$ancestry <- ts_f4ratio(ts, X = inds$name, \"NEA_1\", \"NEA_2\", \"AFR_1\", \"CH_1\")$alpha ggplot(inds, aes(pop, ancestry, fill = pop)) + geom_boxplot() + geom_jitter() + labs(y = \"Neanderthal ancestry proportion\", x = \"\") + theme(legend.position = \"none\") + coord_cartesian(ylim = c(0, 0.1)) dplyr::filter(inds, pop == \"EUR\") %>% ggplot(aes(time, ancestry)) + geom_point() + geom_smooth(method = \"lm\", linetype = 2, color = \"red\", linewidth = 0.5) + xlim(40000, 0) + coord_cartesian(ylim = c(0, 0.1)) + labs(x = \"time [years ago]\", y = \"Neanderthal ancestry proportion\") #> `geom_smooth()` using formula = 'y ~ x'"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"admixtools-analyses","dir":"Articles","previous_headings":"","what":"ADMIXTOOLS analyses","title":"Tree-sequence processing and statistics","text":"case like verify f-statistics results using venerable ADMIXTOOLS software (see linked paper formally introduced statistics first place), can convert tree-sequence data file format called EIGENSTRAT using ts_eigenstrat() function. file conversion internally handled R package admixr returns EIGENSTRAT object ties individual EIGENSTRAT file components together (see tutorial admixr extensive overview). admixr R package running automated ADMIXTOOLS analyses entirely R makes types analyses convenient. Running admixr analysis easy plugging object admixr function. instance, can estimate proportion Neanderthal ancestry couple individuals \\(X\\) like (admixr calls proportion alpha): fact, lets compare values obtained tskit admixr/ADMIXTOOLS individuals: correspondence two looks good! 🎉 , note large amount variance around expected value 3% ancestry due extremely small amount sequence data simulated .","code":"snps <- ts_eigenstrat(ts, prefix = file.path(tempdir(), \"eigenstrat\", \"data\")) #> 1282 multiallelic sites (0.206% out of 621331 total) detected and removed library(admixr) f4ratio(data = snps, X = c(\"EUR_1\", \"EUR_2\", \"AFR_2\"), A = \"NEA_1\", B = \"NEA_2\", C = \"AFR_1\", O = \"CH_1\") #> Rows: 3 Columns: 12 #> ── Column specification ──────────────────────────────────────────────────────── #> Delimiter: \" \" #> chr (8): X1, X2, X3, X4, X5, X6, X7, X8 #> dbl (4): X9, X10, X11, X12 #> #> ℹ Use `spec()` to retrieve the full column specification for this data. #> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message. #> # A tibble: 3 × 8 #> A B X C O alpha stderr Zscore #> #> 1 NEA_1 NEA_2 EUR_1 AFR_1 CH_1 0.0218 0.00506 4.30 #> 2 NEA_1 NEA_2 EUR_2 AFR_1 CH_1 0.0328 0.00788 4.16 #> 3 NEA_1 NEA_2 AFR_2 AFR_1 CH_1 0.00408 0.00208 1.96 europeans <- inds[inds$pop == \"EUR\", ]$name # tskit result result_ts <- ts_f4ratio(ts, X = europeans, A = \"NEA_1\", B = \"NEA_2\", C = \"AFR_1\", O = \"CH_1\") %>% select(alpha_ts = alpha) # result obtained by admixr/ADMIXTOOLS result_admixr <- f4ratio(snps, X = europeans, A = \"NEA_1\", B = \"NEA_2\", C = \"AFR_1\", O = \"CH_1\") %>% select(alpha_admixr = alpha) #> Rows: 50 Columns: 12 #> ── Column specification ──────────────────────────────────────────────────────── #> Delimiter: \" \" #> chr (8): X1, X2, X3, X4, X5, X6, X7, X8 #> dbl (4): X9, X10, X11, X12 #> #> ℹ Use `spec()` to retrieve the full column specification for this data. #> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message. bind_cols(result_admixr, result_ts) %>% ggplot(aes(alpha_ts, alpha_admixr)) + geom_point() + geom_abline(slope = 1, linetype = 2, color = \"red\", linewidth = 0.5) + labs(x = \"f4-ratio statistic calculated with admixr/ADMIXTOOLS\", y = \"f4-ratio statistic calculated with tskit\")"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"vcf-output","dir":"Articles","previous_headings":"","what":"VCF output","title":"Tree-sequence processing and statistics","text":"case need process simulated data software, can use function ts_vcf() save simulated genotypes VCF format: can also specify subset individuals saved VCF:","code":"ts_vcf(ts, path = file.path(tempdir(), \"output.vcf.gz\")) ts_vcf(ts, path = file.path(tempdir(), \"output_subset.vcf.gz\"), individuals = c(\"CH_1\", \"NEA_1\", \"EUR_1\", \"AFR_1\"))"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"other-statistics","dir":"Articles","previous_headings":"","what":"Other statistics","title":"Tree-sequence processing and statistics","text":"follows brief overview statistics implemented tskit slendr provides easy--use R interface. see, goal functions get result using single function call, making convenient quick interactive exploratory analyses simulated data right R console. continue use simulated Neanderthal introgression tree-sequence data examples.","code":""},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"f_st","dir":"Articles","previous_headings":"Other statistics","what":"\\(F_{st}\\)","title":"Tree-sequence processing and statistics","text":"\\(F_{st}\\) statistic implemented function ts_fst(). single genome-wide \\(F_{st}\\) calculated (.e. window-based calculation), ts_fst() returns simple three-column data frame case non-named list sample sets provided, set names generated automatically: course, much less readable encourage name sample sets appropriately. case two sample sets specified, pairwise statistics computed: many statistics implemented tskit, ts_fst() accepts windows argument, specifying breakpoints windows. case, Fst column resulting data frame called “list-column”, item column vector \\(F_{st}\\) values, one per window. List-columns can little confusing new R users, highly encourage get used allow extremely concise elegant handling structured data within normal data frames (can start introduction). instance, window-based \\(F_st\\) values afr-vs-eur calculation (first row table ):","code":"ts_fst(ts, sample_sets = list(afr = c(\"AFR_1\", \"AFR_2\", \"AFR_3\"), eur = c(\"EUR_1\", \"EUR_2\"))) #> # A tibble: 1 × 3 #> x y Fst #> #> 1 afr eur 0.0495 ts_fst(ts, sample_sets = list(c(\"AFR_1\", \"AFR_2\", \"AFR_3\"), c(\"EUR_1\", \"EUR_2\"))) #> # A tibble: 1 × 3 #> x y Fst #> #> 1 set_1 set_2 0.0495 ts_fst(ts, sample_sets = list(afr = c(\"AFR_1\", \"AFR_2\", \"AFR_3\"), eur = c(\"EUR_1\", \"EUR_2\"), nea = c(\"NEA_1\", \"NEA_2\"))) #> # A tibble: 3 × 3 #> x y Fst #> #> 1 afr eur 0.0495 #> 2 afr nea 0.555 #> 3 eur nea 0.541 # define breakpoints between 20 windows breakpoints <- seq(0, ts$sequence_length, length.out = 21) # calculate window-based Fst statistic win_fst <- ts_fst( ts, windows = breakpoints, sample_sets = list(afr = c(\"AFR_1\", \"AFR_2\", \"AFR_3\"), eur = c(\"EUR_1\", \"EUR_2\"), nea = c(\"NEA_1\", \"NEA_2\")) ) # we get 20 values for each parwise calculation win_fst #> # A tibble: 3 × 3 #> x y Fst #> #> 1 afr eur #> 2 afr nea #> 3 eur nea win_fst[1, ]$Fst #> $`1` #> [1] 0.04241163 0.06803338 0.04129167 0.06031210 0.05516414 0.03059425 #> [7] 0.03320629 0.05755971 0.05271680 0.04346970 0.03659568 0.05432308 #> [13] 0.05913699 0.05905198 0.04119386 0.04389669 0.05086942 0.06181126 #> [19] 0.03929837 0.06373172"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"tajimas-d","dir":"Articles","previous_headings":"Other statistics","what":"Tajima’s \\(D\\)","title":"Tree-sequence processing and statistics","text":"function ts_tajima() nearly interface ts_fst() shown . non-window version calculated, get single genome-wide values sample set (named non-named list character vectors individual names): window-based version, function returns D column list column vectors \\(\\)-th element Tajima’s D value \\(\\)-th window:","code":"ts_tajima(ts, list(afr = c(\"AFR_1\", \"AFR_2\", \"AFR_3\"), eur = c(\"EUR_1\", \"EUR_2\"))) #> # A tibble: 2 × 2 #> set D #> #> 1 afr -0.000701 #> 2 eur -0.0140 ts_tajima(ts, list(afr = c(\"AFR_1\", \"AFR_2\"), eur = c(\"EUR_1\", \"EUR_2\")), windows = breakpoints) #> # A tibble: 2 × 2 #> set D #> #> 1 afr #> 2 eur "},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"diversity","dir":"Articles","previous_headings":"Other statistics","what":"Diversity","title":"Tree-sequence processing and statistics","text":"can calculate diversity within given groups individuals function ts_diversity(). instance, even extremely simplified example, expect highest levels diversity Africans, followed Europeans, Neanderthals “degenerate” single individual outgroup “chimpanzee”. true? Let’s find . First extract individuals populations, creating list character vectors group (functions ts_diversity() expects input): Now can calculate diversity population sort results increasing order diversity: Great! matches expectations. simulated chimp “population” one individual, expect essentially diversity millions years evolution.","code":"# get sampled individuals from all populations sample_sets <- ts_samples(ts) %>% split(., .$pop) %>% lapply(function(pop) pop$name) sample_sets #> $AFR #> [1] \"AFR_1\" \"AFR_2\" \"AFR_3\" \"AFR_4\" \"AFR_5\" #> #> $CH #> [1] \"CH_1\" #> #> $EUR #> [1] \"EUR_1\" \"EUR_2\" \"EUR_3\" \"EUR_4\" \"EUR_5\" \"EUR_6\" \"EUR_7\" \"EUR_8\" #> [9] \"EUR_9\" \"EUR_10\" \"EUR_11\" \"EUR_12\" \"EUR_13\" \"EUR_14\" \"EUR_15\" \"EUR_16\" #> [17] \"EUR_17\" \"EUR_18\" \"EUR_19\" \"EUR_20\" \"EUR_21\" \"EUR_22\" \"EUR_23\" \"EUR_24\" #> [25] \"EUR_25\" \"EUR_27\" \"EUR_26\" \"EUR_28\" \"EUR_29\" \"EUR_30\" \"EUR_31\" \"EUR_32\" #> [33] \"EUR_33\" \"EUR_34\" \"EUR_35\" \"EUR_36\" \"EUR_37\" \"EUR_38\" \"EUR_39\" \"EUR_40\" #> [41] \"EUR_41\" \"EUR_42\" \"EUR_43\" \"EUR_44\" \"EUR_45\" \"EUR_46\" \"EUR_47\" \"EUR_48\" #> [49] \"EUR_49\" \"EUR_50\" #> #> $NEA #> [1] \"NEA_1\" \"NEA_2\" ts_diversity(ts, sample_sets) %>% dplyr::arrange(diversity) #> # A tibble: 4 × 2 #> set diversity #> #> 1 CH 0.0000431 #> 2 NEA 0.0000455 #> 3 EUR 0.000394 #> 4 AFR 0.000400"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"divergence","dir":"Articles","previous_headings":"Other statistics","what":"Divergence","title":"Tree-sequence processing and statistics","text":"can calculate pairwise divergence groups individuals using function ts_divergence(). Given model, expect lowest divergence two modern human groups AFR EUR, Neanderthals two modern humans, three groups (AFR, EUR NEA) equal, much deeper divergence outgroup chimpanzee CH. sorting table based value divergence column, can see results fit expectations.","code":"ts_divergence(ts, sample_sets) %>% arrange(divergence) #> # A tibble: 6 × 3 #> x y divergence #> #> 1 AFR EUR 0.000449 #> 2 EUR NEA 0.000757 #> 3 AFR NEA 0.000780 #> 4 CH NEA 0.00401 #> 5 CH EUR 0.00402 #> 6 AFR CH 0.00402"},{"path":"https://www.slendr.net/articles/vignette-05-tree-sequences.html","id":"more-information","dir":"Articles","previous_headings":"","what":"More information","title":"Tree-sequence processing and statistics","text":"couple examples statistical functions implemented tskit provide native R interface slendr. can find tree-sequence statistics reference manual project website. statistics tskit library implemented, intend expand selection provided slendr near future. functionality like use project missing slendr, please don’t hesitate let us now creating issue GitHub page. Finally, like see examples tskit interface action, take look vignette describes switching SLiM msprime back ends slendr package.","code":""},{"path":"https://www.slendr.net/articles/vignette-06-locations.html","id":"introduction","dir":"Articles","previous_headings":"","what":"Introduction","title":"Spatially annotated tree sequences","text":"main selling point slendr R package programming complex spatially explicit population genetic models. use SLiM simulation engine, can store simulated data efficiently tree sequence format allows us run large population-scale simulations. previous vignettes, described can specify spatial population dynamics can access tree sequence data calculate population genetic statistics (focusing non-spatial models simplicity). Now ’s time show work simulated tree sequence spatial context.","code":""},{"path":"https://www.slendr.net/articles/vignette-06-locations.html","id":"model-specification","dir":"Articles","previous_headings":"","what":"Model specification","title":"Spatially annotated tree sequences","text":"Let’s first load required R libraries: begin specifying spatial model. use demographic model modern human history West Eurasia, extensively discussed introductory tutorial main landing page. complete model definition script, without comments: sanity check defined demography correctly, can plot graph summarizing population divergences geneflow events calling plot_model(model): completeness, (slightly busy) overview spatial population ranges defined :","code":"library(slendr) library(dplyr) library(ggplot2) init_env() seed <- 314159 set.seed(seed) # simulated world map map <- world( xrange = c(-13, 70), # min-max longitude yrange = c(18, 65), # min-max latitude crs = \"EPSG:3035\" # coordinate reference system (CRS) for West Eurasia ) # couple of broad geographic regions africa <- region( \"Africa\", map, polygon = list(c(-18, 20), c(38, 20), c(30, 33), c(20, 33), c(10, 38), c(-6, 35)) ) europe <- region( \"Europe\", map, polygon = list( c(-8, 35), c(-5, 36), c(10, 38), c(20, 35), c(25, 35), c(33, 45), c(20, 58), c(-5, 60), c(-15, 50) ) ) anatolia <- region( \"Anatolia\", map, polygon = list(c(28, 35), c(40, 35), c(42, 40), c(30, 43), c(27, 40), c(25, 38)) ) # define population histories # African ancestral population afr <- population( \"AFR\", time = 52000, N = 3000, map = map, polygon = africa ) # population of the first migrants out of Africa ooa <- population( \"OOA\", parent = afr, time = 51000, N = 500, remove = 25000, center = c(33, 30), radius = 400e3 ) %>% move( trajectory = list(c(40, 30), c(50, 30), c(60, 40)), start = 50000, end = 40000, snapshots = 20 ) # Eastern hunter-gatherers ehg <- population( \"EHG\", parent = ooa, time = 28000, N = 1000, remove = 6000, polygon = list( c(26, 55), c(38, 53), c(48, 53), c(60, 53), c(60, 60), c(48, 63), c(38, 63), c(26, 60)) ) # European population eur <- population(name = \"EUR\", parent = ehg, time = 25000, N = 2000, polygon = europe) # Anatolian farmers ana <- population( name = \"ANA\", time = 28000, N = 3000, parent = ooa, remove = 4000, center = c(34, 38), radius = 500e3, polygon = anatolia ) %>% expand_range( by = 2500e3, start = 10000, end = 7000, polygon = join(europe, anatolia), snapshots = 20 ) # expand the range by 2.500 km # Yamnaya steppe population yam <- population( name = \"YAM\", time = 7000, N = 500, parent = ehg, remove = 2500, polygon = list(c(26, 50), c(38, 49), c(48, 50), c(48, 56), c(38, 59), c(26, 56)) ) %>% move(trajectory = list(c(15, 50)), start = 5000, end = 3000, snapshots = 10) # geneflow events gf <- list( gene_flow(from = ana, to = yam, rate = 0.5, start = 6000, end = 5000, overlap = FALSE), gene_flow(from = ana, to = eur, rate = 0.5, start = 8000, end = 6000), gene_flow(from = yam, to = eur, rate = 0.75, start = 4000, end = 3000) ) # compile the spatial model model <- compile_model( populations = list(afr, ooa, ehg, eur, ana, yam), gene_flow = gf, generation_time = 30, resolution = 10e3, competition = 150e3, mating = 120e3, dispersal = 90e3 ) plot_model(model) plot_map(afr, ooa, ehg, eur, ana, yam)"},{"path":"https://www.slendr.net/articles/vignette-06-locations.html","id":"scheduling-sampling-events-and-simulation","dir":"Articles","previous_headings":"","what":"Scheduling sampling events and simulation","title":"Spatially annotated tree sequences","text":"Now schedule sampling single individual population every two thousand years, starting 40 thousand years ago way present (feature discussed basic tree sequence overview): Finally, can simulate data model process output tree sequence (recapitate simplify ):","code":"# one ancient individual every two thousand years ancient <- schedule_sampling(model, times = seq(40000, 1, by = -500), list(ooa, 1), list(ehg, 1), list(eur, 1), list(ana, 1), list(yam, 1)) # present-day Africans and Europeans present <- schedule_sampling(model, times = 0, list(afr, 5), list(eur, 30)) samples <- rbind(ancient, present) ts <- slim( model, sequence_length = 100e3, recombination_rate = 1e-8, burnin = 200e3, samples = samples, method = \"batch\", random_seed = 314159, max_attempts = 1 ) %>% ts_recapitate(recombination_rate = 1e-8, Ne = 10000, random_seed = seed) %>% ts_simplify() ts #> ╔═════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═════════╣ #> ║Trees │ 87║ #> ╟───────────────┼─────────╢ #> ║Sequence Length│ 100000║ #> ╟───────────────┼─────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼─────────╢ #> ║Sample Nodes │ 432║ #> ╟───────────────┼─────────╢ #> ║Total Size │205.8 KiB║ #> ╚═══════════════╧═════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │1173│36.7 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 711│71.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 939│35.4 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 7│ 2.7 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 3│37.8 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Sites │ 0│16 Bytes│ No║ #> ╚═══════════╧════╧════════╧════════════╝"},{"path":"https://www.slendr.net/articles/vignette-06-locations.html","id":"extracting-spatial-tree-sequence-information","dir":"Articles","previous_headings":"","what":"Extracting spatial tree sequence information","title":"Spatially annotated tree sequences","text":"showed basic tutorial, important function data exploration ts_nodes(). function extracts information individuals nodes recorded tree sequence object loaded annotated slendr : completeness, also functions ts_individuals(), ts_nodes() ts_edges() extract tree sequence tables “raw” unprocessed form, ts_nodes() much convenient data exploration analyses. First, combined information low-level tables individuals nodes single table importantly, model generated data spatial model, ts_nodes() automatically annotates node/individual tables position node space (real projected coordinates) time. means can spatial data analysis directly table returned ts_nodes(). Even better, although can see returned object belongs slendr’s class slendr_ts_nodes, internally stored spatial sf object. means can use functionality powerful R package sf well many packages geospatial analyses directly data: Typing object R console presents user-friendly summary spatio-temporal data extracted tree sequence: first part summary, see many individuals (sampled retained) nodes present tree sequence together additional useful information, including section internally stored sf object. crucial point—**can always use internal sf object spatial data directly*. data returned ts_nodes() internally transformed projected CRS used model, can use returned object data class sf. instance, beginning vignette, specified world map model represented projected CRS (EPSG 3035) can verify typing: fact ts_nodes() result just another sf object makes easy visualize overlay contents map, see .","code":"data <- ts_nodes(ts) class(data) #> [1] \"slendr\" \"slendr_nodes\" \"sf\" \"tbl_df\" \"tbl\" #> [6] \"data.frame\" data #> Simple feature collection with 939 features and 12 fields (with 11 geometries empty) #> Geometry type: POINT #> Dimension: XY #> Bounding box: xmin: 2426565 ymin: 257945.3 xmax: 8576618 ymax: 4878988 #> Projected CRS: ETRS89-extended / LAEA Europe #> # A tibble: 939 × 13 #> name pop node_id time time_tskit location sampled #> #> 1 AFR_1 AFR 362 0 0 (3716841 1078277) TRUE #> 2 AFR_1 AFR 363 0 0 (3716841 1078277) TRUE #> 3 AFR_2 AFR 364 0 0 (3541863 257945.3) TRUE #> 4 AFR_2 AFR 365 0 0 (3541863 257945.3) TRUE #> 5 AFR_3 AFR 366 0 0 (3366331 688429.9) TRUE #> 6 AFR_3 AFR 367 0 0 (3366331 688429.9) TRUE #> 7 AFR_4 AFR 368 0 0 (3329518 1360326) TRUE #> 8 AFR_4 AFR 369 0 0 (3329518 1360326) TRUE #> 9 AFR_5 AFR 370 0 0 (3263687 1123829) TRUE #> 10 AFR_5 AFR 371 0 0 (3263687 1123829) TRUE #> # ℹ 929 more rows #> # ℹ 6 more variables: remembered , retained , alive , #> # pedigree_id , ind_id , pop_id map #> slendr 'map' object #> ------------------- #> map: internal coordinate reference system EPSG 3035 #> spatial limits (in degrees longitude and latitude): #> - vertical -13 ... 70 #> - horizontal 18 ... 65"},{"path":"https://www.slendr.net/articles/vignette-06-locations.html","id":"using-the-simple-features-interface","dir":"Articles","previous_headings":"","what":"Using the simple features interface","title":"Spatially annotated tree sequences","text":"’s hard overstate powerful R ecosystem around sf package . However, getting familiar package geospatial analysis general can bit hurdle, especially novice users takes time get familiar many new concepts. Although many slendr features encoding programming spatial models handling simulated tree sequence data discussed far designed abstract away complexities underlying low-level details let focus problem hand, spatial data analysis unfortunately whole another matter. Luckily, data generated slendr different source spatial data great free resources disposal. bottom line : spatio-temporal data extracted tree sequences slendr different normal sf object. resource find manipulating, plotting, analysing sf data can applied slendr results well. remainder vignette look couple examples.","code":""},{"path":"https://www.slendr.net/articles/vignette-06-locations.html","id":"plotting-locations-of-simulated-sampled-individuals","dir":"Articles","previous_headings":"","what":"Plotting locations of simulated sampled individuals","title":"Spatially annotated tree sequences","text":"Every spatial object slendr internally class sf. flexibility ggplot2 sf packages means can overlay locations sampled individuals (saved sf format ts_nodes()) top world map (also sf object): sf simple features objects (, extension, even slendr_spatial objects) internally stored normal data frames couple bells whistles top , powerful tools manipulating tabular data disposal. example, let’s say wanted split sampled individuals tree sequence epochs plot individually using standard ggplot2 features. simply first , adding new column specifying epoch simulated individual belong: chunk code simply adds new column epoch sf spatial data frame object called epochs . can use ggplot2 function geom_sf plot locations sampled individuals map, facet corresponding one epoch (warning can safely ignored): hope little excursion handling slendr spatial objects (, extension, sf objects) standard data frame manipulation functions ggplot2 visualisation convinced great flexibility analysing spatial slendr data. best introduction -called “tidy” data analysis, encourage read freely-available book R Data Science.","code":"sampled_data <- ts_nodes(ts) %>% filter(sampled) ggplot() + geom_sf(data = map, fill = \"lightgray\", color = NA) + geom_sf(data = sampled_data, aes(shape = pop, color = time)) + ggtitle(\"Locations of simulated sampled individuals\") + scale_color_continuous(type = \"viridis\") + theme_bw() epochs <- sampled_data %>% mutate(epoch = cut(time, breaks = c(40000, 30000, 10000, 4000, 0)), epoch = ifelse(is.na(epoch), 0, epoch), epoch = factor(epoch, labels = c(\"present\", \"(present, 4 ky]\", \"(4 ky, 10 ky]\", \"(10 ky, 30 y]\", \"(30 ky, 40 ky]\"))) ggplot() + geom_sf(data = map, fill = \"lightgray\", color = NA) + geom_sf(data = epochs, aes(shape = pop, color = pop)) + facet_wrap(~ epoch) + ggtitle(\"Locations of simulated sampled individuals in different epochs\") + theme_bw()"},{"path":"https://www.slendr.net/articles/vignette-06-locations.html","id":"extracting-spatio-temporal-ancestral-relationships","dir":"Articles","previous_headings":"","what":"Extracting spatio-temporal ancestral relationships","title":"Spatially annotated tree sequences","text":"Perhaps even useful plotting locations simulated individuals accessing locations (times) ancestors particular tree sequence node (“focal node”). Starting focal node individual, can trace geographical location nodes lineage going back way root function ts_ancestors(). record time location every individual happens ancestor least one sampled individual, means know true location every node tree sequence. simplest use case determining locations times every single node genealogical history individual along tree sequence (possible recover ancestral relationships multiple samples ): function starts given node (, name sampled diploid individual provided, two nodes), extracts information parent nodes node entire tree sequence, records locations times, proceeds one level “higher” genealogical history gather information parents parent nodes, etc., reaches root node. result process another sf object row table encodes information single branch genealogy “focal” node individual (example, \"EUR_25\"): row table, two columns location parent_location carry spatial location node (node_id) parent node (parent_id), respectively, columns time parent_time (times nodes) pop parent_pop (populations nodes belong). column connection contains sf geometry object line connecting two nodes coordinate reference system “model world”. column focal_id tells us focal node’s genealogy rows table belong , level column shows deep genealogical past branch (.e. row table) belong . table contains complete information spatio-temporal relationships nodes genealogy given focal sample. spirit demonstrating slendr tree sequence tables interact sf ggplot2 environments, let’s look immediate parent nodes two nodes sampled individual (.e. nodes level 1) using filter function R package dplyr: mentioned , three columns encoding spatial information: location parent_location carry information location child parent node (POINT class), connection object (LINESTRING class) contains line connecting two nodes (branch tree sequence also spatial connection). can plot three spatial features (two points line) individually map: figure can see red focal node immediate parents tree sequence genealogy (coalescent sense, immediate parents individual!). case ’re surprised see two parents, recall recombination events make history encoded sample complicated can involve ancestors “move ” tree sample, just two ancestors. Looking example detail, can see one node (chromosome) individual “EUR_67” two ancestors, covering portion individuals chromosome, chromosome covered single ancestor (columns left_pos right_pos): convenient way analysis companion function ts_ancestors() called plot_ancestors(). function accepts sf object spatial branching data created ts_ancestors() plots paths nodes map leading focal node root(s) tree sequence (instead just paths immediate parents shown previous figure). case, working single diploid individual, get two sets paths nodes (chromosomes) plot two facets: can compare result animation recapitulates simulation, presented first vignette. comparing spatial tree sequence figure animation, can immediately notice several things: spatial tree sequence paths trace ancestry single European individual back Africa. fact, also see cluster past ancestral nodes (.e. concentrated coalescent events) place Africa (OOA) migrant population settled around 40,000 thousand years ago (yellow population animation). One chromosome traces ancestry EHG population indicated green square expected programmed Yamnaya migration (descending EHG) east central Europe contribute significant part ancestry present-day Europeans (compare demographic graph top vignette). also see chromosome traces ancestry Anatolia (blue crosses). makes sense, simulated European ancestry part Anatolian. Let’s look spatial ancestry another sample. instance, know simulated history Anatolian population model much simpler. According demographic graph , Anatolians split ancestral population Eurasians Anatolia expanded wave Europe. sampled following individuals: Can see hint spatial dynamics Anatolians spatio-temporal distribution ancestral node locations one sampled individuals? Let’s pick last individual immediately plot spatial ancestry tidyverse-style using pipe operator %>%: might expect given late age sample, position map (red crossed circle) Anatolia Europe represents one descendants migrants moved Anatolia Europe. can clearly seen position parental nodes tree sequence: nodes represent real individuals lived point past, can see , indeed, lived Anatolia.","code":"ind <- \"EUR_67\" lineages <- ts_ancestors(ts, ind, verbose = TRUE) #> Collecting ancestors of EUR_67 [1/1]... #> #> Generating data about spatial relationships of nodes... lineages #> Simple feature collection with 112 features and 12 fields #> Active geometry column: connection #> Geometry type: LINESTRING #> Dimension: XY #> Bounding box: xmin: 2736603 ymin: 607014.9 xmax: 8374222 ymax: 4762949 #> Projected CRS: ETRS89-extended / LAEA Europe #> # A tibble: 112 × 15 #> name pop node_id level child_id parent_id child_time parent_time child_pop #> * #> 1 EUR_… EUR 406 1 406 456 0 1900 EUR #> 2 EUR_… EUR 406 2 456 460 1900 2020 EUR #> 3 EUR_… EUR 406 3 460 469 2020 3010 EUR #> 4 EUR_… EUR 406 4 469 488 3010 5080 EUR #> 5 EUR_… EUR 406 5 488 495 5080 5740 EUR #> 6 EUR_… EUR 406 6 495 543 5740 9760 EUR #> 7 EUR_… EUR 406 7 543 608 9760 16090 EUR #> 8 EUR_… EUR 406 7 543 695 9760 22960 EUR #> 9 EUR_… EUR 406 8 608 695 16090 22960 EUR #> 10 EUR_… EUR 406 8 695 704 22960 23560 EUR #> # ℹ 102 more rows #> # ℹ 6 more variables: parent_pop , child_location , #> # parent_location , connection , left_pos , #> # right_pos filter(lineages, level == 1) #> Simple feature collection with 2 features and 12 fields #> Active geometry column: connection #> Geometry type: LINESTRING #> Dimension: XY #> Bounding box: xmin: 3965813 ymin: 2689630 xmax: 4683571 ymax: 2918506 #> Projected CRS: ETRS89-extended / LAEA Europe #> # A tibble: 2 × 15 #> name pop node_id level child_id parent_id child_time parent_time child_pop #> * #> 1 EUR_67 EUR 406 1 406 456 0 1900 EUR #> 2 EUR_67 EUR 407 1 407 451 0 1390 EUR #> # ℹ 6 more variables: parent_pop , child_location , #> # parent_location , connection , left_pos , #> # right_pos level1_branches <- ts_ancestors(ts, \"EUR_67\") %>% filter(level == 1) ggplot() + geom_sf(data = map, fill = \"lightgray\", color = NA) + geom_sf(data = level1_branches[, ]$child_location, shape = 13, size = 3, color = \"red\") + geom_sf(data = level1_branches[, ]$connection, linetype = 3) + geom_sf(data = level1_branches[, ]$parent_location, shape = 20, color = \"blue\") + theme_bw() + ggtitle(\"Parent nodes (blue) of a focal individual (red)\") as_tibble(level1_branches)[, c(\"name\", \"node_id\", \"child_id\", \"parent_id\", \"left_pos\", \"right_pos\")] #> # A tibble: 2 × 6 #> name node_id child_id parent_id left_pos right_pos #> #> 1 EUR_67 406 406 456 0 100000 #> 2 EUR_67 407 407 451 0 100000 ggplot() + geom_sf(data = map) + geom_sf(data = lineages, size = 0.5, alpha = 0.2) + geom_sf(data = sf::st_set_geometry(lineages, \"parent_location\"), aes(shape = parent_pop, color = parent_pop)) + geom_sf(data = filter(ts_nodes(ts), name == ind), size = 3) + guides(alpha = \"none\") + coord_sf(expand = 0) + labs(x = \"longitude\", y = \"latitude\") + facet_grid(. ~ node_id) + ggtitle(\"Ancestry encoded by two nodes (chromosomes) of EUR_67\") ts_samples(ts) %>% filter(pop == \"ANA\") #> # A tibble: 48 × 3 #> name time pop #> #> 1 ANA_1 27500 ANA #> 2 ANA_2 27000 ANA #> 3 ANA_3 26500 ANA #> 4 ANA_4 26000 ANA #> 5 ANA_5 25500 ANA #> 6 ANA_6 25000 ANA #> 7 ANA_7 24500 ANA #> 8 ANA_8 24000 ANA #> 9 ANA_9 23500 ANA #> 10 ANA_10 23000 ANA #> # ℹ 38 more rows lineages <- ts_ancestors(ts, \"ANA_45\") ggplot() + geom_sf(data = map) + geom_sf(data = lineages, size = 0.5, alpha = 0.2) + geom_sf(data = sf::st_set_geometry(lineages, \"parent_location\"), aes(shape = parent_pop, color = parent_pop)) + geom_sf(data = filter(ts_nodes(ts), name == \"ANA_45\"), size = 3) + guides(alpha = \"none\") + coord_sf(expand = 0) + labs(x = \"longitude\", y = \"latitude\") + facet_grid(. ~ node_id) + ggtitle(\"Ancestry encoded by two nodes (chromosomes) of ANA_45\")"},{"path":"https://www.slendr.net/articles/vignette-06-locations.html","id":"calculating-distances-and-other-statistics-using-the-sf-package","dir":"Articles","previous_headings":"","what":"Calculating distances and other statistics using the sf package","title":"Spatially annotated tree sequences","text":"can summarise spatial ancestral dynamics figures using statistics? Lets take one look sf object locations times ancestral nodes sampled individuals, focusing following subset columns: can use standard dplyr table manipulation functions compute distances connected notes times separate (.e. branch lengths traditional phylogenetic sense). can use two quantities compute fast () movement ancestral individuals different time periods history sample: Let’s also convert data (absolute distances distance per generation – .e., “speed”) long format easier plotting side side: Let’s try summarise information distances “traveled” nodes different time period fitting spline (rather plotting raw data individual nodes):","code":"lineages <- ts_samples(ts) %>% pull(name) %>% ts_ancestors(ts, x = .) select(lineages, connection, child_time, parent_time) #> Simple feature collection with 20798 features and 2 fields #> Geometry type: LINESTRING #> Dimension: XY #> Bounding box: xmin: 2426565 ymin: 257945.3 xmax: 8576618 ymax: 4878988 #> Projected CRS: ETRS89-extended / LAEA Europe #> # A tibble: 20,798 × 3 #> connection child_time parent_time #> #> 1 (8481422 2958176, 8289917 2751867) 40000 40690 #> 2 (8289917 2751867, 8110419 2813524) 40690 41710 #> 3 (8110419 2813524, 3348636 939123) 41710 67030 #> 4 (8110419 2813524, 2736603 1136489) 41710 83530 #> 5 (8110419 2813524, 3202720 1100178) 41710 203980 #> 6 (8110419 2813524, 3475143 607014.9) 41710 205270 #> 7 (8110419 2813524, 4086614 772146.9) 41710 243100 #> 8 (3348636 939123, 3202720 1100178) 67030 203980 #> 9 (2736603 1136489, 3969941 671890.4) 83530 88810 #> 10 (3969941 671890.4, 3991115 816590.1) 88810 96730 #> # ℹ 20,788 more rows distances <- lineages %>% mutate(branch_length = abs(parent_time - child_time) / model$generation_time, distance = sf::st_length(connection) %>% units::set_units(km) %>% as.numeric(), speed = distance / branch_length, epoch = cut(parent_time, breaks = c(Inf, seq(60000, 0, by = -3000)), dig.lab = 10, include.lowest = TRUE)) %>% as_tibble() %>% # strip away the spatial annotation select(name, pop, node_id, branch_length, distance, speed, parent_pop, parent_time, child_pop, child_time, epoch) distances_long <- distances %>% filter(child_time < 60000) %>% filter(!pop %in% c(\"AFR\", \"OOA\")) %>% tidyr::pivot_longer(cols = c(distance, speed), names_to = \"stat\", values_to = \"value\") %>% mutate(facet = case_when( stat == \"distance\" ~ \"absolute distance of a node from parent\", stat == \"speed\" ~ \"distance traveled by a node per generation\")) distances_long %>% ggplot(aes(child_time, value, color = child_pop)) + geom_smooth(method = \"loess\", aes(group = child_pop)) + geom_hline(yintercept = 0, linetype = 2, linewidth = 0.5) + labs(y = \"kilometers\", x = \"time [years ago]\") + theme(axis.text.x = element_text(hjust = 1, angle = 45), legend.position = \"bottom\") + facet_wrap(~ facet, scales = \"free_y\") + guides(color = guide_legend(\"ancestral node population\")) #> `geom_smooth()` using formula = 'y ~ x'"},{"path":[]},{"path":"https://www.slendr.net/articles/vignette-07-backends.html","id":"defining-a-model","dir":"Articles","previous_headings":"Detecting gene flow from msprime and SLiM tree sequences","what":"Defining a model","title":"Simulating data with SLiM and msprime backends","text":"now define simple non-spatial model gene flow populations (also known population admixture introgression). involve essentially procedure shown another vignette introducing non-spatial slendr models. Note different normally specify spatial model, except left map argument making population() calls. demonstrate additional features slendr interface tskit Python library, perform gene flow detection test using -called \\(f_4\\) \\(f_4\\)-ratio statistics (briefly introduces vignette). make things little interesting, define two population models: one model without gene flow, another includes gene flow. defining model expressing \\(f\\)-statistics use nomenclature used first study Patterson et al. described \\(f_4-ratio\\) statistic first place. ’re familiar statistical tests gene flow, recommend take look relevant sections linked paper. shiny_graph Let’s start first defining populations splits established figure : Note Ne populations x1 x2 set much higher rest. set \\(N_e\\) populations lower values speed forward SLiM simulations (won’t affect results ’re interested anyway). Higher values \\(N_e\\) x1 x2 populations ensure effect drift acting two populations much smaller. simulate later measure proportion ancestry population b x1, ensure ancestry proportion drift far away expectation make interesting patterns stand clearly. (course, done demonstration purposes speed SLiM simulations making \\(N_e\\) populations smaller. practice, running kinds simulations using msprime back end.)","code":"seq_len <- 100e6 # amount of sequence to simulate rec_rate <- 1e-8 # uniform recombination rate mut_rate <- 1e-8 # mutation rate o <- population(\"outgroup\", time = 1, N = 100) c <- population(\"c\", time = 2500, N = 100, parent = o) a <- population(\"a\", time = 3000, N = 100, parent = c) b <- population(\"b\", time = 3500, N = 100, parent = a) x1 <- population(\"x1\", time = 3800, N = 5000, parent = c) x2 <- population(\"x2\", time = 4000, N = 5000, parent = x1)"},{"path":"https://www.slendr.net/articles/vignette-07-backends.html","id":"compiling-the-model-and-simulating-data","dir":"Articles","previous_headings":"","what":"Compiling the model and simulating data","title":"Simulating data with SLiM and msprime backends","text":"now use populations compile two models: first model without gene flow (left panel figure ), second model include 10% gene flow b x1 (right panel figure ). also schedule sampling couple individuals end simulation: 50 individuals populations x1 x2 capture bit natural variation b ancestry x1, one individual rest. running simulations, let’s first make sure models set correctly: Now run models (without gene flow) two slendr backends, SLiM msprime: Note using exactly model configuration object simulation runs! fact, even function interface looks nearly exactly . doesn’t matter specific details demographic models , slendr interpret correctly regardless back end simulation engine choose use.","code":"# no gene flow model model_nogf <- compile_model(populations = list(a, b, x1, x2, c, o), generation_time = 1, simulation_length = 4500) samples <- schedule_sampling( model_nogf, times = 4500, list(a, 1), list(b, 1), list(x1, 50), list(x2, 50), list(c, 1), list(o, 1) ) # model with gene flow gf <- gene_flow(from = b, to = x1, start = 4100, end = 4400, rate = 0.1) model_gf <- compile_model(populations = list(a, b, x1, x2, c, o), gene_flow = gf, generation_time = 1, simulation_length = 4500) samples <- schedule_sampling( model_gf, times = 4500, list(a, 1), list(b, 1), list(x1, 50), list(x2, 50), list(c, 1), list(o, 1) ) plot_model(model_nogf, sizes = FALSE) plot_model(model_gf, sizes = FALSE, proportions = TRUE) # model without gene flow slim_nogf <- slim(model_nogf, sequence_length = seq_len, recombination_rate = rec_rate, samples = samples, random_seed = seed) msprime_nogf <- msprime(model_nogf, sequence_length = seq_len, recombination_rate = rec_rate, samples = samples, random_seed = seed) # model with b -> x1 gene flow slim_gf <- slim(model_gf, sequence_length = seq_len, recombination_rate = rec_rate, samples = samples, random_seed = seed) msprime_gf <- msprime(model_gf, sequence_length = seq_len, recombination_rate = rec_rate, samples = samples, random_seed = seed)"},{"path":"https://www.slendr.net/articles/vignette-07-backends.html","id":"comparing-the-outputs-of-msprime-and-slim-runs-of-a-slendr-model","dir":"Articles","previous_headings":"Compiling the model and simulating data","what":"Comparing the outputs of msprime and SLiM runs of a slendr model","title":"Simulating data with SLiM and msprime backends","text":"run introgression models two simulation back ends, let’s load SLiM msprime tree sequence outputs compare contents (hoping !). can see , tree sequence summary data loaded processed slendr’s ts_load() function (data produced SLiM backend) similar got “manually” msprime-produced tree sequence using custom defined functions. somehow obvious nice cheap sanity check indicating tree sequence data structure produced two backends demographic model almost .","code":"# SLiM outputs -- we can use built-in slendr functions for those slim_nogf <- slim_nogf %>% ts_recapitate(Ne = 10, recombination_rate = rec_rate, random_seed = seed) %>% ts_mutate(mut_rate, random_seed = seed) slim_gf <- slim_gf %>% ts_recapitate(Ne = 10, recombination_rate = rec_rate, random_seed = seed) %>% ts_mutate(mut_rate, random_seed = seed) # msprime outputs (note that recapitation and simplification doesn't make # sense here because we already have fully coalesced genealogies for our # individuals of interest msprime_nogf <- ts_mutate(msprime_nogf, mut_rate, random_seed = seed) msprime_gf <- ts_mutate(msprime_gf, mut_rate, random_seed = seed) slim_nogf #> ╔═════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═════════╣ #> ║Trees │ 248158║ #> ╟───────────────┼─────────╢ #> ║Sequence Length│100000000║ #> ╟───────────────┼─────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼─────────╢ #> ║Sample Nodes │ 21008║ #> ╟───────────────┼─────────╢ #> ║Total Size │ 70.6 MiB║ #> ╚═══════════════╧═════════╝ #> ╔═══════════╤══════╤════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪════════╪════════════╣ #> ║Edges │972815│29.7 MiB│ No║ #> ╟───────────┼──────┼────────┼────────────╢ #> ║Individuals│131750│12.6 MiB│ Yes║ #> ╟───────────┼──────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼────────┼────────────╢ #> ║Mutations │257348│ 9.1 MiB│ No║ #> ╟───────────┼──────┼────────┼────────────╢ #> ║Nodes │157230│ 5.7 MiB│ Yes║ #> ╟───────────┼──────┼────────┼────────────╢ #> ║Populations│ 7│ 2.8 KiB│ Yes║ #> ╟───────────┼──────┼────────┼────────────╢ #> ║Provenances│ 3│38.0 KiB│ No║ #> ╟───────────┼──────┼────────┼────────────╢ #> ║Sites │257040│ 6.1 MiB│ No║ #> ╚═══════════╧══════╧════════╧════════════╝ msprime_nogf #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 62745║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 208║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 14.4 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │247454│ 7.6 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 104│ 2.9 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 69172│ 2.4 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │ 32685│893.7 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 6│414 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 2│ 3.9 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │ 69144│ 1.6 MiB│ No║ #> ╚═══════════╧══════╧═════════╧════════════╝"},{"path":"https://www.slendr.net/articles/vignette-07-backends.html","id":"comparing-results-of-population-genetics-statistics","dir":"Articles","previous_headings":"Compiling the model and simulating data","what":"Comparing results of population genetics statistics","title":"Simulating data with SLiM and msprime backends","text":"loaded msprime SLiM tree sequences generated model, let’s see can get comparable results calculate statistics interest. Let’s first extract individuals populations x1 x2 estimate values \\(f_4(c, x1 \\textrm{ } x2; b, o)\\) (significantly negative individuals population x1 due ’s ancestry coming b introgression models consistent zero x2) \\(f_4\\textrm{-ratio}(, b, \\textrm{ } x2; c, o)\\), estimates proportion b-like ancestry x1 x2: Now, let’s repeat analysis tree sequences produced msprime backend two slendr demographic models: Finally can proceed plotting SLiM msprime backend results two models compare together. noted , despite fact SLiM forward simulator msprime coalescent simulator, population genetic expectations gene flow gene flow models match closely (barring level uncertainty expected due randomness population genetic processes play). Things seem looking good behave expected! couple observations: model without gene flow, \\(f_4\\) statistic value zero x1 x2 populations. expected, \\(f_4\\) ~0 consistent relationship lineages conforming standard phylogenetic tree (admixture edges). Essentially, \\(f_4\\) hypothesis test “tree-ness” data. model includes gene flow b x1, \\(f_4\\) value significantly negative. means simple tree hypothesis can rejected gene flow must occurred b x1. Note test reveal direction gene flow, ’s presence. Consistently \\(f_4\\) results, \\(f_4-ratio\\) estimates match expectations. Specifically, statistic estimates around 10% ancestry b x1 gene flow model 0% ancestry cases. importantly, results obtained SLiM msprime back ends nearly exactly . means (non-spatial models) can use SLiM msprime backend interchangeably.","code":"# extract vector of names of the \"test individuals\" in populations `x1` and `x2` X <- ts_samples(slim_gf) %>% filter(pop %in% c(\"x1\", \"x2\")) %>% pull(name) X #> [1] \"x1_1\" \"x1_2\" \"x1_3\" \"x1_4\" \"x1_5\" \"x1_6\" \"x1_7\" \"x1_8\" \"x1_9\" #> [10] \"x1_10\" \"x1_11\" \"x1_12\" \"x1_13\" \"x1_14\" \"x1_15\" \"x1_16\" \"x1_17\" \"x1_18\" #> [19] \"x1_19\" \"x1_20\" \"x1_21\" \"x1_22\" \"x1_23\" \"x1_24\" \"x1_25\" \"x1_26\" \"x1_27\" #> [28] \"x1_28\" \"x1_29\" \"x1_30\" \"x1_31\" \"x1_32\" \"x1_33\" \"x1_34\" \"x1_35\" \"x1_36\" #> [37] \"x1_37\" \"x1_38\" \"x1_39\" \"x1_40\" \"x1_41\" \"x1_42\" \"x1_43\" \"x1_44\" \"x1_45\" #> [46] \"x1_46\" \"x1_47\" \"x1_48\" \"x1_49\" \"x1_50\" \"x2_1\" \"x2_2\" \"x2_3\" \"x2_4\" #> [55] \"x2_5\" \"x2_6\" \"x2_7\" \"x2_8\" \"x2_9\" \"x2_10\" \"x2_11\" \"x2_12\" \"x2_13\" #> [64] \"x2_14\" \"x2_15\" \"x2_16\" \"x2_17\" \"x2_18\" \"x2_19\" \"x2_20\" \"x2_21\" \"x2_22\" #> [73] \"x2_23\" \"x2_24\" \"x2_25\" \"x2_26\" \"x2_27\" \"x2_28\" \"x2_29\" \"x2_30\" \"x2_31\" #> [82] \"x2_32\" \"x2_33\" \"x2_34\" \"x2_35\" \"x2_36\" \"x2_37\" \"x2_38\" \"x2_39\" \"x2_40\" #> [91] \"x2_41\" \"x2_42\" \"x2_43\" \"x2_44\" \"x2_45\" \"x2_46\" \"x2_47\" \"x2_48\" \"x2_49\" #> [100] \"x2_50\" # calculate f4-statistics on individuals of `x1` and `x2` populations using data # from the two models (a model with no gene flow and a gene flow model) -- we use # map_dfr to iterate across all individuals from `X_individuals` and binding all # resulting data frames into a single data frame df_slim_f4 <- rbind( map_dfr(X, ~ ts_f4(slim_nogf, \"c_1\", .x, \"b_1\", \"outgroup_1\")) %>% mutate(model = \"no gene flow\"), map_dfr(X, ~ ts_f4(slim_gf, \"c_1\", .x, \"b_1\", \"outgroup_1\")) %>% mutate(model = \"gene flow\") ) %>% select(X, f4, model) %>% mutate(simulator = \"SLiM backend\") # compute the proportions of `b` ancestry in `x1` (expected 10%) and `x2` # (expected 0% because this population did not receive any gene flow from `b`) df_slim_f4ratio <- rbind( ts_f4ratio(slim_nogf, X, \"a_1\", \"b_1\", \"c_1\", \"outgroup_1\") %>% mutate(model = \"no gene flow\"), ts_f4ratio(slim_gf, X, \"a_1\", \"b_1\", \"c_1\", \"outgroup_1\") %>% mutate(model = \"gene flow\") ) %>% select(X, alpha, model) %>% mutate(simulator = \"SLiM backend\") df_msprime_f4 <- rbind( map_dfr(X, ~ ts_f4(msprime_nogf, \"c_1\", .x, \"b_1\", \"outgroup_1\")) %>% mutate(model = \"no gene flow\"), map_dfr(X, ~ ts_f4(msprime_gf, \"c_1\", .x, \"b_1\", \"outgroup_1\")) %>% mutate(model = \"gene flow\") ) %>% select(X, f4, model) %>% mutate(simulator = \"msprime backend\") # compute the proportions of `b` ancestry in `x1` (expected 10%) and `x2` # (expected 0% because this population did not receive any gene flow from `b`) df_msprime_f4ratio <- rbind( ts_f4ratio(msprime_nogf, X, \"a_1\", \"b_1\", \"c_1\", \"outgroup_1\") %>% mutate(model = \"no gene flow\"), ts_f4ratio(msprime_gf, X, \"a_1\", \"b_1\", \"c_1\", \"outgroup_1\") %>% mutate(model = \"gene flow\") ) %>% select(X, alpha, model) %>% mutate(simulator = \"msprime backend\") df_f4 <- rbind(df_slim_f4, df_msprime_f4) %>% mutate(population = ifelse(grepl(\"x1_\", X), \"x1 (received gene flow)\", \"x2 (no gene flow)\")) ggplot(df_f4, aes(f4, fill = population)) + geom_histogram(bins = 50) + facet_grid(simulator ~ model) + geom_vline(xintercept = 0, linetype = 2) + labs(y = \"number of individuals\", x = \"f4 statistic\", title = \"f4(c, x1 or x2; b, outgroup)\", subtitle = \"f4 ~0 is consistent with no gene flow, negative value indicates gene flow with 'b'\") + theme(legend.position = \"bottom\") df_f4ratio <- rbind(df_slim_f4ratio, df_msprime_f4ratio) %>% mutate(population = ifelse(grepl(\"x1_\", X), \"x1 (received gene flow)\", \"x2 (no gene flow)\")) ggplot(df_f4ratio, aes(alpha, fill = population)) + geom_histogram(bins = 30) + facet_grid(simulator ~ model) + geom_vline(xintercept = 0.1, linetype = 2) + labs(y = \"number of individuals\", x = \"ancestry proportion (f4-ratio statistic)\", title = \"f4-ratio estimate of 'b' ancestry calculated from simulated data\", subtitle = \"f4-ratio = f4(a, outgroup; x1 or x2, c) / f4(a, outgroup; b, c)\") + theme(legend.position = \"bottom\")"},{"path":"https://www.slendr.net/articles/vignette-07-backends.html","id":"computing-allele-frequency-spectra","dir":"Articles","previous_headings":"","what":"Computing allele frequency spectra","title":"Simulating data with SLiM and msprime backends","text":"Let’s look one example. Imagine following five demographic models describing changes population size abstract population: models population size change events , depending specifics project, defined using different time units. work radiocarbon-dated samples ancient DNA might used thinking population history units “years present”—case, “present” time (bottom figure) time 0 earlier events specified “5000 years present”, etc. hand, interested modelling theoretical population, might want concern quite happy starting simulation “generation 1” continue specified “generation X”. slendr package makes extremely easy, can specify times whatever direction units want, long kept consistent populations events model. rather unique feature among popgen simulation software programs either make express model “generations forward direction”, explicitly convert time generations going backwards. previous section vignette shown SLiM msprime can used simulation backend. remainder vignette present additional analysis, demonstrating fact can express time models forward backward direction still run models slendr’s SLiM (forward simulator) msprime (backward simulator). Specifically, define five demographic models figure twice, different orientations time – forward backward. compute allele frequency spectrum simulation (five models, forward backward) verify forward backward pairs give result regardless whether use SLiM back end msprime backend.","code":""},{"path":"https://www.slendr.net/articles/vignette-07-backends.html","id":"model-definition","dir":"Articles","previous_headings":"Computing allele frequency spectra","what":"Model definition","title":"Simulating data with SLiM and msprime backends","text":"First, let’s define five population histories forward time direction: Now let’s flip flow time around define population histories units “time ago”: convenience, write helper function , given population history object (ten objects just ), compile slendr model, run SLiM msprime back ends, load tree sequence, compute allele frequency spectrum (AFS) . save us lots code repetition (always good thing), minimize chance copy-pasting bugs (definitely good thing!) compare AFS patterns across different models two slendr simulation back ends (according population genetics theory). Now function doesn’t anything special. simply wraps standard slendr simulation pipeline (1. create population(s); 2. compile model object; 3. simulate model; 4. load results; 5. analyse data) single function. Now whole pipeline, can generate simulated data bind result single data frame: Finally, can plot allele frequency spectra models, two time directions, two simulation back ends: , couple things note: two models involve population contraction (single step exponential collapse), see decrease low frequency variants. hand, models population expansion show high proportion low frequency variants. model constant population size shows intermediate pattern. nice validation simulation works expected exactly predicted population genetics theory. forward backward time models give exactly result. unexpected anything else bug slendr. However, although unsurprising, hope makes clear free use whatever time unit specification want encode slendr models. non-spatial models, results obtained msprime SLiM back ends consistent one another. , makes sense although completely different software, population genetic theory governing shape allele frequency spectra applies equally . fact, example just implemented important part slendr unit test suite verifies simulations created slendr correct.","code":"N <- 1000 N_factor <- 5 # by what factor should Ne change seq_len <- 50e6 rec_rate <- 1e-8 mut_rate <- 1e-8 # constant Ne model forward_const <- population(\"const\", time = 1, N = N) # decreasing step Ne model forward_decr <- population(\"decr\", time = 1, N = N, map = FALSE) %>% resize(time = 2000, N = N / N_factor, how = \"step\") # increasing step Ne model forward_incr <- population(\"inc\", time = 1, N = N) %>% resize(time = 2000, N = N * N_factor, how = \"step\") # exponential increase in size forward_exp_incr <- population(\"exp_inc\", time = 1, N = N) %>% resize(time = 2000, end = 3000, N = N * N_factor, how = \"exponential\") # exponential decrease in size forward_exp_decr <- population(\"exp_decr\", time = 1, N = N) %>% resize(time = 2000, end = 3000, N = N / N_factor, how = \"exponential\") # constant Ne model backward_const <- population(\"const\", time = 5000, N = N) # decreasing step Ne model backward_decr <- population(\"decr\", time = 5000, N = N) %>% resize(time = 3000, N = N / N_factor, how = \"step\") # increasing step Ne model backward_incr <- population(\"inc\", time = 5000, N = N) %>% resize(time = 3000, N = N * N_factor, how = \"step\") # exponential increase in size backward_exp_incr <- population(\"exp_inc\", time = 5000, N = N) %>% resize(time = 3000, end = 2000, N = N * N_factor, how = \"exponential\") # exponential decrease in size backward_exp_decr <- population(\"exp_decr\", time = 5000, N = N) %>% resize(time = 3000, end = 2000, N = N / N_factor, how = \"exponential\") compile_run_afs <- function(model_name, pop, seed = 42) { # maximum length of the simulation (necessary for forward models which start # in generation 1) simulation_length <- 5000 # define sampling times given the direction of time if (attr(pop, \"history\")[[1]]$time == 1) { sampling_time <- simulation_length direction <- \"forward\" } else { sampling_time <- 0 direction <- \"backward\" } # compile model model <- compile_model(pop, generation_time = 15, direction = direction, simulation_length = simulation_length) samples <- schedule_sampling(model, times = sampling_time, list(pop, 50)) # run the model in SLiM ts_slim <- slim(model, sequence_length = seq_len, recombination_rate = rec_rate, samples = samples, random_seed = seed, verbose = FALSE) # run the same model in msprim ts_msprime <- msprime(model, sequence_length = seq_len, recombination_rate = rec_rate, samples = samples, random_seed = seed, verbose = FALSE) # load the SLiM tree sequence ts_slim <- ts_recapitate(ts_slim, Ne = N, recombination_rate = rec_rate, random_seed = seed) %>% ts_mutate(mut_rate, random_seed = seed) # load the msprime tree sequence ts_msprime <- ts_mutate(ts_msprime, mut_rate, random_seed = seed) # compute the AFS from the SLiM and msprime tree sequences and bind the # results (derived allele counts per frequency bin) in a data frame msprime_afs <- ts_afs(ts_msprime, polarised = TRUE)[-1] slim_afs <- ts_afs(ts_slim, polarised = TRUE)[-1] rbind( data.frame(simulator = \"msprime\", model = model_name, f = msprime_afs), data.frame(simulator = \"SLiM\", model = model_name, f = slim_afs) ) %>% group_by(simulator, model) %>% mutate(n = 1:n(), direction = direction) %>% ungroup() } afs <- bind_rows( compile_run_afs(\"constant\", forward_const), compile_run_afs(\"constant\", backward_const), compile_run_afs(\"step contraction\", forward_decr), compile_run_afs(\"step contraction\", backward_decr), compile_run_afs(\"step increase\", forward_incr), compile_run_afs(\"step increase\", backward_incr), compile_run_afs(\"exponential decrease\", forward_exp_decr), compile_run_afs(\"exponential decrease\", backward_exp_decr), compile_run_afs(\"exponential increase\", forward_exp_incr), compile_run_afs(\"exponential increase\", backward_exp_incr) ) %>% mutate(model = factor( model, levels = c(\"step contraction\", \"constant\", \"step increase\", \"exponential decrease\", \"exponential increase\")) ) ggplot(afs, aes(n, f, color = direction, linetype = simulator)) + geom_line(stat = \"identity\") + facet_wrap(~ model) + labs(x = \"number of derived alleles\", y = \"frequency\", title = \"Site frequency spectra obtained from five demographic models\", subtitle = \"Each model was specified in forward or backward direction of time and executed by two different backend scripts in slendr (SLiM and msprime)\") + guides(color = guide_legend(\"direction of\\ntime in slendr\"), linetype = guide_legend(\"slendr backend\\nengine used\")) + scale_linetype_manual(values = c(3, 2)) + scale_x_continuous(breaks = c(1, seq(20, 100, 20)), limits = c(1, 100)) + theme(legend.position = \"bottom\")"},{"path":"https://www.slendr.net/articles/vignette-07-backends.html","id":"conclusion","dir":"Articles","previous_headings":"","what":"Conclusion","title":"Simulating data with SLiM and msprime backends","text":"example shows standard, non-spatial demographic model like implement simulate R, slendr gives way efficiently using ’s msprime back end addition SLiM back end used throughout documentation.","code":""},{"path":"https://www.slendr.net/articles/vignette-08-nonslendr-tskit.html","id":"non-spatial-slim-tree-sequences","dir":"Articles","previous_headings":"","what":"Non-spatial SLiM tree sequences","title":"Analyzing non-slendr tree sequences","text":"Consider following SLiM script, creates couple populations (different \\(N_e\\)) splitting ancestral population p1 (lets save /tmp/nonspatial.slim): run script SLiM, can use slendr load output tree sequence (saved /tmp/nonspatial-slim.trees), simplify , overlay mutations using standard functionality originally developed slendr tree sequences. Note command use loading slendr tree sequences, except direct ts_load() function straight tree-sequence output file rather using ts_load() format used working standard slendr simulations. way, slendr can extract information individual’s names, nodes, population assignments, etc. just slendr tree sequence function ts_nodes(). standard slendr models, function loads “raw” node individual tree-sequences tables, performs couple join operations, presents whole thing nice unified form interactive data analysis (can also include spatial information—see ): Moving tskit statistics, can use data table extract list nodes belonging population (various tskit tree-sequence statistics operate , slendr follows design). computing nucleotide diversity four populations using ts_diversity() function, first creating list lists node IDs (.e. chromosomes) individuals population: Just slendr tree sequences (demonstrated paper) can get individual trees , extracted phylogenetic format provided ape R package. first simplify tree sequence even just 10 nodes make things manageable: R tree object, can use packages like ggtree visualize tree (phylogenetic package work ). Note nodes ‘ape phylo’ trees must conform strict format (must labelled 1...N), extract information node IDs tskit tree-sequence data able plot tree.","code":"initialize() { setSeed(42); initializeTreeSeq(); initializeMutationRate(0); initializeMutationType(\"m1\", 0.5, \"f\", 0.0); initializeGenomicElementType(\"g1\", m1, 1.0); initializeGenomicElement(g1, 0, 1e6); initializeRecombinationRate(1e-8); } 1 early() { sim.addSubpop(\"p1\", 10); } 1000 early() { sim.addSubpopSplit(\"p2\", 500, p1); } 3000 early() { sim.addSubpopSplit(\"p3\", 2500, p1); } 5000 early() { sim.addSubpopSplit(\"p4\", 10000, p1); } 6000 late() { sim.treeSeqOutput(\"/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//Rtmpx99kMg/filee61c7b568e93\"); } ts <- ts_load(nonspatial_trees_file) %>% ts_simplify() %>% ts_mutate(mutation_rate = 1e-7, random_seed = SEED) data <- ts_nodes(ts) %>% dplyr::filter(sampled) data #> # A tibble: 26,020 × 11 #> pop node_id time time_tskit sampled remembered retained alive pedigree_id #> #> 1 p1 0 0 0 TRUE FALSE FALSE TRUE 20073000 #> 2 p1 1 0 0 TRUE FALSE FALSE TRUE 20073000 #> 3 p1 2 0 0 TRUE FALSE FALSE TRUE 20073001 #> 4 p1 3 0 0 TRUE FALSE FALSE TRUE 20073001 #> 5 p1 4 0 0 TRUE FALSE FALSE TRUE 20073002 #> 6 p1 5 0 0 TRUE FALSE FALSE TRUE 20073002 #> 7 p1 6 0 0 TRUE FALSE FALSE TRUE 20073003 #> 8 p1 7 0 0 TRUE FALSE FALSE TRUE 20073003 #> 9 p1 8 0 0 TRUE FALSE FALSE TRUE 20073004 #> 10 p1 9 0 0 TRUE FALSE FALSE TRUE 20073004 #> # ℹ 26,010 more rows #> # ℹ 2 more variables: ind_id , pop_id sample_sets <- split(data$node_id, data$pop) # compute nucleotide diversity in each population # (any other ts_*() tskit R interface function should work) ts_diversity(ts, sample_sets) #> # A tibble: 4 × 2 #> set diversity #> #> 1 p1 0.00000755 #> 2 p2 0.000241 #> 3 p3 0.000463 #> 4 p4 0.000201 samples <- sample(data$node_id, 10) ts_small <- ts_simplify(ts, simplify_to = samples) # extract the 42nd tree in the genealogy to an R 'phylo' format tree <- ts_phylo(ts_small, 42 - 1) #> Starting checking the validity of tree... #> Found number of tips: n = 10 #> Found number of nodes: m = 9 #> Done. tree #> #> Phylogenetic tree with 10 tips and 9 internal nodes. #> #> Tip labels: #> 1, 0, 9, 4, 8, 7, ... #> Node labels: #> 45, 28, 22, 31, 35, 36, ... #> #> Rooted; includes branch lengths. library(ggtree) #> ggtree v3.10.0 For help: https://yulab-smu.top/treedata-book/ #> #> If you use the ggtree package suite in published research, please cite #> the appropriate paper(s): #> #> Guangchuang Yu, David Smith, Huachen Zhu, Yi Guan, Tommy Tsan-Yuk Lam. #> ggtree: an R package for visualization and annotation of phylogenetic #> trees with their covariates and other associated data. Methods in #> Ecology and Evolution. 2017, 8(1):28-36. doi:10.1111/2041-210X.12628 #> #> Guangchuang Yu. Data Integration, Manipulation and Visualization of #> Phylogenetic Trees (1st edition). Chapman and Hall/CRC. 2022, #> doi:10.1201/9781003279242 #> #> LG Wang, TTY Lam, S Xu, Z Dai, L Zhou, T Feng, P Guo, CW Dunn, BR #> Jones, T Bradley, H Zhu, Y Guan, Y Jiang, G Yu. treeio: an R package #> for phylogenetic tree input and output with richly annotated and #> associated data. Molecular Biology and Evolution. 2020, 37(2):599-603. #> doi: 10.1093/molbev/msz240 #> #> Attaching package: 'ggtree' #> The following object is masked from 'package:magrittr': #> #> inset labels <- ts_nodes(tree) %>% select(node = phylo_id, tskit_id = node_id) ggtree(tree, branch.length = \"none\") %<+% labels + geom_label(aes(label = tskit_id)) library(ape) plot(tree, show.tip.label = FALSE) nodelabels() tiplabels()"},{"path":"https://www.slendr.net/articles/vignette-08-nonslendr-tskit.html","id":"msprime-non-slendr-tree-sequences","dir":"Articles","previous_headings":"","what":"msprime (non-slendr) tree sequences","title":"Analyzing non-slendr tree sequences","text":"applies also msprime tree sequences (really surprising, given ’s tskit hood). can start Python: can proceed loading msprime tree sequence R analyze slendr functionality:","code":"import msprime ts = msprime.sim_ancestry(100) ts.dump() ts <- ts_load(msprime_trees_file) ts_nodes(ts) #> # A tibble: 199 × 7 #> pop ind_id node_id time time_tskit sampled pop_id #> #> 1 0 NA 0 0 0 TRUE 0 #> 2 0 NA 1 0 0 TRUE 0 #> 3 0 NA 2 0 0 TRUE 0 #> 4 0 NA 3 0 0 TRUE 0 #> 5 0 NA 4 0 0 TRUE 0 #> 6 0 NA 5 0 0 TRUE 0 #> 7 0 NA 6 0 0 TRUE 0 #> 8 0 NA 7 0 0 TRUE 0 #> 9 0 NA 8 0 0 TRUE 0 #> 10 0 NA 9 0 0 TRUE 0 #> # ℹ 189 more rows"},{"path":"https://www.slendr.net/articles/vignette-08-nonslendr-tskit.html","id":"spatial-slim-non-slendr-tree-sequences","dir":"Articles","previous_headings":"","what":"Spatial SLiM (non-slendr) tree sequences","title":"Analyzing non-slendr tree sequences","text":"Furthermore, generalized interface also supports slendr’s spatial tree-sequence features, bells whistles. instance, lets take following spatial SLiM script (modified SLiM manual) execute SLiM usual way: can load simplify output tree sequence just vignette (anywhere slendr documentation): Finally, can access spatio-temporal data embedded output tree sequence standard slendr way (note spatial sf column location POINT data type): get tree sequence converted spatial sf data format, can use standard geospatial packages use spatial data analysis methods packages provide. briefly demonstrate means, can trivially plot location recorded node: can also collect spatio-temporal ancestry information particular node (.e. times locations ancestors way root, “link” plot signifying parent-child edge somewhere along tree sequence) plot 2D surface (x y dimensions [0, 1]). plot little chaotic, hopefully conveys idea (“focal node” 0 highlighted red). essentially plot last figure paper.","code":"initialize() { setSeed(42); initializeSLiMOptions(keepPedigrees=T, dimensionality=\"xy\"); initializeTreeSeq(); initializeMutationRate(1e-7); initializeMutationType(\"m1\", 0.5, \"f\", 0.0); initializeGenomicElementType(\"g1\", m1, 1.0); initializeGenomicElement(g1, 0, 1e6); initializeRecombinationRate(1e-8); } 1 early() { sim.addSubpop(\"p1\", 500); // initial positions are random in ([0,1], [0,1]) p1.individuals.x = runif(p1.individualCount); p1.individuals.y = runif(p1.individualCount); } modifyChild() { // draw a child position near the first parent, within bounds do child.x = parent1.x + rnorm(1, 0, 0.02); while ((child.x < 0.0) | (child.x > 1.0)); do child.y = parent1.y + rnorm(1, 0, 0.02); while ((child.y < 0.0) | (child.y > 1.0)); return T; } 1: late() { sim.treeSeqRememberIndividuals(sim.subpopulations.individuals, permanent = F); } 10000 late() { sim.treeSeqOutput(\"/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T//Rtmpx99kMg/filee61c27e4c5b7\"); } ts <- ts_load(spatial_trees_file) %>% ts_simplify() data <- ts_nodes(ts) data #> Simple feature collection with 1941 features and 11 fields #> Geometry type: POINT #> Dimension: XY #> Bounding box: xmin: 0.02032986 ymin: 0.001180405 xmax: 0.9990375 ymax: 0.9979969 #> CRS: NA #> # A tibble: 1,941 × 12 #> pop node_id time time_tskit location sampled remembered #> #> 1 p1 0 0 0 (0.3158008 0.8489413) TRUE FALSE #> 2 p1 1 0 0 (0.3158008 0.8489413) TRUE FALSE #> 3 p1 2 0 0 (0.5946915 0.5792152) TRUE FALSE #> 4 p1 3 0 0 (0.5946915 0.5792152) TRUE FALSE #> 5 p1 4 0 0 (0.8320243 0.5595862) TRUE FALSE #> 6 p1 5 0 0 (0.8320243 0.5595862) TRUE FALSE #> 7 p1 6 0 0 (0.5532792 0.1833623) TRUE FALSE #> 8 p1 7 0 0 (0.5532792 0.1833623) TRUE FALSE #> 9 p1 8 0 0 (0.7333698 0.01834573) TRUE FALSE #> 10 p1 9 0 0 (0.7333698 0.01834573) TRUE FALSE #> # ℹ 1,931 more rows #> # ℹ 5 more variables: retained , alive , pedigree_id , #> # ind_id , pop_id ggplot() + geom_sf(data = data, aes(color = time), alpha = 0.5) ancestral_links <- ts_ancestors(ts, 0) ggplot() + geom_sf(data = ancestral_links, size = 0.5, aes(alpha = parent_time)) + geom_sf(data = sf::st_set_geometry(ancestral_links, \"parent_location\"), aes(color = parent_time)) + geom_sf(data = data[data$node_id == 0, ], size = 3, color = \"red\")"},{"path":"https://www.slendr.net/articles/vignette-08-nonslendr-tskit.html","id":"conclusion","dir":"Articles","previous_headings":"","what":"Conclusion","title":"Analyzing non-slendr tree sequences","text":"vignette gave brief overview using slendr’s R-tskit interface loading, processing, analyzing “pure” non-slendr tree sequences produced msprime SLiM scripts. Although touched upon basic features R-tskit interface standard tree sequences, important note far slendr concerned, matter tree sequence produced, long conforms tskit specification. means regardless source tree sequence data, able use slendr’s tskit functionality run analyses.","code":""},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"note","dir":"Articles","previous_headings":"","what":"Note","title":"Examples from the slendr paper","text":"Since publication slendr paper, new versions SLiM slendr released. Specifically, results paper based SLiM version 4.0.1 slendr version 0.5. Whenever new version SLiM released, ’s always chance aspect randomness simulation changes slightly, affects results even though random seed kept value. , figures paper (specifically figure Example 4 paper) look slightly different. However, results still relevant applicable, just presentation changed.","code":"# workaround for GitHub actions getting \"Killed\" due to out of memory issues # -- when running unit tests on GitHub, smaller amount of sequence will be # simulated if (Sys.getenv(\"RUNNER_OS\") != \"\") { scaling <- 10 # use 10X less sequence on GitHub actions } else { scaling <- 1 # but simulate normal amount of data otherwise } library(slendr) library(dplyr) #> #> Attaching package: 'dplyr' #> The following objects are masked from 'package:stats': #> #> filter, lag #> The following objects are masked from 'package:base': #> #> intersect, setdiff, setequal, union library(ggplot2) library(purrr) library(tidyr) library(cowplot) library(forcats) init_env() #> The interface to all required Python modules has been activated. SEED <- 42 set.seed(SEED) # placeholder \"figure\" where a code chunk will be pasted p_code <- ggplot() + geom_text(aes(x = 1, y = 1), label = \"code will be here\") + theme_void()"},{"path":[]},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"script-from-panel-a","dir":"Articles","previous_headings":"Example 1 (Figure 2)","what":"Script from panel A","title":"Examples from the slendr paper","text":"","code":"o <- population(\"o\", time = 1, N = 100) c <- population(\"c\", time = 2500, N = 100, parent = o) a <- population(\"a\", time = 2800, N = 100, parent = c) b <- population(\"b\", time = 3700, N = 100, parent = a) x1 <- population(\"x1\", time = 4000, N = 15000, parent = c) x2 <- population(\"x2\", time = 4300, N = 15000, parent = x1) gf <- gene_flow(from = b, to = x1, start = 5400, end = 5800, 0.1) model <- compile_model( populations = list(o, a, b, c, x1, x2), gene_flow = gf, generation_time = 1, simulation_length = 6000 ) plot_model(model, sizes = FALSE, proportions = TRUE) # panel B ts <- msprime(model, sequence_length = 100e6 / scaling, recombination_rate = 1e-8, random_seed = SEED) %>% ts_mutate(mutation_rate = 1e-8, random_seed = SEED) samples <- ts_samples(ts) %>% group_by(pop) %>% sample_n(100) # panel C divergence <- ts_divergence(ts, split(samples$name, samples$pop)) # panel D f4ratio <- ts_f4ratio( ts, X = filter(samples, pop %in% c(\"x1\", \"x2\"))$name, A = \"a_1\", B = \"b_1\", C = \"c_1\", O = \"o_1\" )"},{"path":[]},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"plotting-code","dir":"Articles","previous_headings":"Example 1 (Figure 2)","what":"Plotting code","title":"Examples from the slendr paper","text":"","code":"divergence <- divergence %>% mutate(pair = paste(x, \"-\", y)) f4ratio <- f4ratio %>% mutate(population = gsub(\"^(.*)_.*$\", \"\\\\1\", X), alpha = alpha * 100) p_ex1_divergence <- divergence %>% ggplot(aes(fct_reorder(pair, divergence), divergence)) + geom_point(size = 2.5) + xlab(\"population pair\") + ylab(\"pairwise divergence\") + theme_minimal() + theme(legend.position = \"bottom\", legend.text = element_text(size = 10), axis.text.x = element_text(hjust = 1, angle = 45, size = 8), axis.title.x = element_blank()) p_ex1_f4ratio <- f4ratio %>% ggplot(aes(population, alpha)) + geom_hline(yintercept = 0, linetype = 2) + geom_jitter(alpha = 0.5) + geom_boxplot(outlier.shape = NA, alpha = 0.7) + ylab(base::expression(italic(\"f\")[4]~\"-ratio ancestry proportion [%]\")) + theme_minimal() + coord_cartesian(ylim = c(0, 20)) + theme(legend.position = \"none\", axis.text.x = element_text(size = 11), axis.title.x = element_blank(), panel.grid.major.x = element_blank())#; p_ex3_f4ratio # let's avoid ggpubr as another dependency: # https://github.com/kassambara/ggpubr/blob/master/R/as_ggplot.R#L27 p_ex1_legend <- ggdraw() + draw_grob(grid::grobTree(get_legend(p_ex1_divergence))) p_ex1_model <- plot_model(model, sizes = FALSE, proportions = TRUE) p_ex1 <- plot_grid( p_code, plot_grid( p_ex1_model, plot_grid( p_ex1_divergence + theme(legend.position = \"none\"), p_ex1_f4ratio, ncol = 2, rel_widths = c(1, 0.8), labels = c(\"C\", \"D\") ), p_ex1_legend, nrow = 3, rel_heights = c(1, 1, 0.1), labels = \"B\" ), nrow = 1, labels = c(\"A\", \"\") ) p_ex1"},{"path":[]},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"script-from-panel-a-1","dir":"Articles","previous_headings":"Example 2 (Figure 3)","what":"Script from panel A","title":"Examples from the slendr paper","text":"","code":"map <- world(xrange = c(0, 10), yrange = c(0, 10), landscape = region(center = c(5, 5), radius = 5)) p1 <- population(\"pop1\", time = 1, N = 2000, map = map, competition = 0) p2 <- population(\"pop2\", time = 1, N = 2000, map = map, competition = 9) p3 <- population(\"pop3\", time = 1, N = 2000, map = map, competition = 6) p4 <- population(\"pop4\", time = 1, N = 2000, map = map, competition = 5) p5 <- population(\"pop5\", time = 1, N = 2000, map = map, competition = 4) p6 <- population(\"pop6\", time = 1, N = 2000, map = map, competition = 3) p7 <- population(\"pop7\", time = 1, N = 2000, map = map, competition = 2) p8 <- population(\"pop8\", time = 1, N = 2000, map = map, competition = 1) model <- compile_model( populations = list(p1, p2, p3, p4, p5, p6, p7, p8), generation_time = 1, simulation_length = 5000, resolution = 0.1, mating = 0.1, dispersal = 0.05 ) ts <- slim(model, sequence_length = 10e6 / scaling, recombination_rate = 1e-8, random_seed = SEED) %>% ts_simplify() %>% ts_mutate(mutation_rate = 1e-7, random_seed = SEED) #> Warning: Simplifying a non-recapitated tree sequence. Make sure this is what #> you really want locations <- ts_nodes(ts) %>% filter(time == max(time)) heterozygosity <- ts_samples(ts) %>% group_by(pop) %>% sample_n(100) %>% mutate(pi = ts_diversity(ts, name)$diversity)"},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"plotting-code-1","dir":"Articles","previous_headings":"Example 2 (Figure 3)","what":"Plotting code","title":"Examples from the slendr paper","text":"","code":"p_ex2_clustering <- ggplot() + geom_sf(data = map) + geom_sf(data = locations, aes(color = pop), size = 0.05, alpha = 0.25) + facet_grid(. ~ pop, switch = \"x\") + xlab(\"spatial distributions emerged in the simulation\") + theme( strip.background = element_blank(), strip.text = element_text(size = 11), panel.grid = element_blank(), axis.ticks = element_blank(), axis.text = element_blank(), panel.background = element_blank() ) + guides(color = \"none\") p_ex2_diversity <- ggplot(heterozygosity, aes(pop, pi, color = pop)) + geom_violin(color = \"black\") + geom_jitter(alpha = 0.5) + labs(y = \"individual heterozygosity\") + guides(color = \"none\") + theme_minimal() + theme(axis.title.x = element_blank(), axis.text.x = element_blank(), panel.grid.major.x = element_blank(), plot.margin = margin(t = 0.2, r = 0.2, b = -0.1, l = 0.2, \"cm\")) p_ex2 <- plot_grid( p_code, plot_grid( p_ex2_diversity, p_ex2_clustering + theme(plot.margin = margin(t = 0, r = 0.4, b = 0, l = 1.8, \"cm\")), nrow = 2, rel_heights = c(1, 0.5), labels = c(\"B\", \"C\") ), nrow = 2, labels = c(\"A\", \"\"), rel_heights = c(1.5, 1) ) p_ex2"},{"path":[]},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"script-from-panel-a-2","dir":"Articles","previous_headings":"Example 3 (Figure 4)","what":"Script from panel A","title":"Examples from the slendr paper","text":"","code":"map <- world(xrange = c(-13, 70), yrange = c(18, 65), crs = 3035) #> Reading layer `ne_110m_land' from data source #> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpdblWjc/naturalearth/ne_110m_land.shp' #> using driver `ESRI Shapefile' #> Simple feature collection with 127 features and 3 fields #> Geometry type: POLYGON #> Dimension: XY #> Bounding box: xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513 #> Geodetic CRS: WGS 84 R1 <- region( \"EHG range\", map, polygon = list(c(26, 55), c(38, 53), c(48, 53), c(60, 53), c(60, 60), c(48, 63), c(38, 63), c(26, 60)) ) R2 <- region( \"Europe\", map, polygon = list( c(-8, 35), c(-5, 36), c(10, 38), c(20, 35), c(25, 35), c(33, 45), c(20, 58), c(-5, 60), c(-15, 50) ) ) R3 <- region( \"Anatolia\", map, polygon = list(c(28, 35), c(40, 35), c(42, 40), c(30, 43), c(27, 40), c(25, 38)) ) R4 <- join(R2, R3) R5 <- region( \"YAM range\", map, polygon = list(c(26, 50), c(38, 49), c(48, 50), c(48, 56), c(38, 59), c(26, 56)) ) ooa_trajectory <- list(c(40, 30), c(50, 30), c(60, 40), c(45, 55)) map <- world(xrange = c(-13, 70), yrange = c(18, 65), crs = 3035) #> Reading layer `ne_110m_land' from data source #> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpdblWjc/naturalearth/ne_110m_land.shp' #> using driver `ESRI Shapefile' #> Simple feature collection with 127 features and 3 fields #> Geometry type: POLYGON #> Dimension: XY #> Bounding box: xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513 #> Geodetic CRS: WGS 84 ooa <- population( \"OOA\", time = 50000, N = 500, remove = 23000, map = map, center = c(33, 30), radius = 400e3 ) %>% move(trajectory = ooa_trajectory, start = 50000, end = 40000, snapshots = 30) ehg <- population( \"EHG\", time = 28000, N = 1000, parent = ooa, remove = 6000, map = map, polygon = R1 ) eur <- population( \"EUR\", time = 30000, N = 2000, parent = ooa, map = map, polygon = R2 ) %>% resize(N = 10000, time = 5000, end = 0, how = \"exponential\") ana <- population( \"ANA\", time = 25000, N = 4000, parent = ooa, remove = 3000, map = map, polygon = R3 ) %>% expand_range(by = 3e6, start = 10000, end = 7000, polygon = R4, snapshots = 15) yam <- population( \"YAM\", time = 7000, N = 600, parent = ehg, remove = 2500, map = map, polygon = R5 ) %>% move(trajectory = list(c(15, 50)), start = 5000, end = 3000, snapshots = 10) gf <- list( gene_flow(ana, to = yam, rate = 0.5, start = 6500, end = 5000), gene_flow(ana, to = eur, rate = 0.6, start = 8000, end = 6000), gene_flow(yam, to = eur, rate = 0.7, start = 3500, end = 3000) ) model <- compile_model( populations = list(ooa, ehg, eur, ana, yam), gene_flow = gf, generation_time = 30, resolution = 10e3, competition = 150e3, mating = 120e3, dispersal = 90e3 ) samples <- schedule_sampling( model, times = seq(0, 50000, by = 1000), list(ehg, 20), list(ana, 20), list(yam, 20), list(eur, 20) ) plot_model(model, sizes = FALSE) plot_map(model) ts <- slim( model, burnin = 200000, samples = samples, random_seed = SEED, sequence_length = 200000, recombination_rate = 1e-8 )"},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"plotting-code-2","dir":"Articles","previous_headings":"Example 3 (Figure 4)","what":"Plotting code","title":"Examples from the slendr paper","text":"","code":"p_map <- plot_map(model) + theme(legend.position = \"bottom\") + guides(alpha = \"none\") p_ex3 <- plot_grid( p_code, plot_grid( plot_model(model, sizes = FALSE), p_map, labels = c(\"B\", \"C\"), nrow = 2, rel_heights = c(1, 1) ), ncol = 2, labels = c(\"A\", \"\"), rel_widths = c(1, 1.2) ) p_ex3"},{"path":[]},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"script-from-panel-a-3","dir":"Articles","previous_headings":"Example 4 (Figure 5)","what":"Script from panel A","title":"Examples from the slendr paper","text":"","code":"ts_small <- ts_simplify(ts, simplify_to = c(\"EUR_578\", \"YAM_75\", \"ANA_163\", \"EHG_208\")) # tskit uses zero-based indexing tree <- ts_phylo(ts_small, i = 15 / scaling) #> Starting checking the validity of tree... #> Found number of tips: n = 8 #> Found number of nodes: m = 7 #> Done. nodes <- ts_nodes(tree) edges <- ts_edges(tree) ancestors <- ts_ancestors(ts, \"EUR_578\")"},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"plotting-code-3","dir":"Articles","previous_headings":"Example 4 (Figure 5)","what":"Plotting code","title":"Examples from the slendr paper","text":"explained top page, random number generation current SLiM slightly different version 4.0.1 available time writing paper. figure looks little different well (different random generation implies different movement individuals, different individuals sampled). record, ’s original figure used paper also originally part vignette:","code":"library(ggtree) #> ggtree v3.10.0 For help: https://yulab-smu.top/treedata-book/ #> #> If you use the ggtree package suite in published research, please cite #> the appropriate paper(s): #> #> Guangchuang Yu, David Smith, Huachen Zhu, Yi Guan, Tommy Tsan-Yuk Lam. #> ggtree: an R package for visualization and annotation of phylogenetic #> trees with their covariates and other associated data. Methods in #> Ecology and Evolution. 2017, 8(1):28-36. doi:10.1111/2041-210X.12628 #> #> Guangchuang Yu. Data Integration, Manipulation and Visualization of #> Phylogenetic Trees (1st edition). Chapman and Hall/CRC. 2022, #> doi:10.1201/9781003279242 #> #> Guangchuang Yu. Using ggtree to visualize data on tree-like structures. #> Current Protocols in Bioinformatics. 2020, 69:e96. doi:10.1002/cpbi.96 #> #> #> Attaching package: 'ggtree' #> The following object is masked from 'package:tidyr': #> #> expand # prepare annotation table for ggtree linking R phylo node ID (not tskit integer # ID!) of each node with its population name df <- as_tibble(nodes) %>% select(node = phylo_id, pop) abs_comma <- function (x, ...) { format(abs(x) / 1000, ..., scientific = FALSE, trim = TRUE) } highlight_nodes <- as_tibble(nodes) %>% dplyr::filter(name == \"EUR_578\") %>% .$phylo_id p_tree <- ggtree(tree, aes(color = pop, fill = pop)) %<+% df + geom_tiplab(align = TRUE, geom = \"label\", offset = 2000, color = \"white\", fontface = \"bold\", size = 2.7) + geom_tiplab(align = TRUE, geom = NULL, linetype = \"dotted\", size = 0) + geom_point2(aes(subset = (node %in% highlight_nodes)), color = \"black\", size = 2.7) + geom_label2(aes(label = label, subset = !isTip), color = \"black\", size = 2.7) + theme_tree2() + theme(legend.position = \"none\") + xlab(\"time before present [thousand years ago]\") + scale_x_continuous(limits = c(-80000, 31000), labels = abs_comma, breaks = -c(100, 80, 60, 40, 20, 0) * 1000) p_tree <- revts(p_tree) # nodes$label <- ifelse(is.na(nodes$name), nodes$node_id, nodes$name) nodes$label <- sapply(1:nrow(nodes), function(i) { if (is.na(nodes[i, ]$name)) nodes[i, ]$node_id else { ind <- nodes[i, ]$name paste(nodes[!is.na(nodes$name) & nodes$name == ind, ]$node_id, collapse = \"&\") } }) p_map <- ggplot() + geom_sf(data = map) + geom_sf(data = edges, aes(color = parent_pop), size = 0.5) + geom_sf_label(data = nodes[!nodes$sampled, ], aes(label = node_id, fill = pop), size = 3) + geom_sf_label(data = nodes[nodes$sampled, ], aes(label = label, fill = pop), size = 3, fontface = \"bold\", color = \"white\") + coord_sf(xlim = c(3177066.1, 7188656.9), ylim = c(757021.7, 5202983.3), expand = 0) + guides(fill = guide_legend(\"\", override.aes = aes(label = \"\"))) + guides(color = \"none\") + scale_colour_discrete(drop = FALSE) + scale_fill_discrete(drop = FALSE) + theme_bw() + theme(legend.position = \"bottom\", axis.title.x = element_blank(), axis.title.y = element_blank()) chrom_names <- stats::setNames( c(\"EUR_578 (node 6)\", \"EUR_578 (node 7)\"), unique(ancestors$node_id) ) p_ancestors <- ggplot() + geom_sf(data = map) + geom_sf(data = ancestors, size = 0.5, alpha = 0.25) + geom_sf(data = sf::st_set_geometry(ancestors, \"parent_location\"), aes(shape = parent_pop, color = parent_pop)) + geom_sf(data = filter(ts_nodes(ts), name == \"EUR_578\"), size = 3) + coord_sf(expand = 0) + labs(x = \"longitude\", y = \"latitude\") + theme_bw() + facet_grid(. ~ node_id, labeller = labeller(node_id = chrom_names)) + theme(legend.position = \"none\") p_legend <- ggdraw() + draw_grob(grid::grobTree(get_legend(p_map))) p_ex4 <- plot_grid( p_code, plot_grid(p_tree + theme(legend.position = \"none\"), p_map + theme(legend.position = \"none\"), labels = c(\"B\", \"C\"), rel_widths = c(1, 0.9)), p_ancestors, p_legend, labels = c(\"A\", \"\", \"D\", \"\"), nrow = 4, rel_heights = c(0.5, 1, 1, 0.1) ) p_ex4"},{"path":"https://www.slendr.net/articles/vignette-09-paper.html","id":"run-time-of-each-code-example-from-the-paper","dir":"Articles","previous_headings":"","what":"Run time of each code example from the paper","title":"Examples from the slendr paper","text":"following times measured 16’’ MacBook Pro Apple M1 Pro chip (2021 model), 32 GB RAM, running macOS Ventura Version 13.1. table , ex1, ex2, ex3, ex4 correspond runtimes code shown one four example figures slendr paper.","code":""},{"path":"https://www.slendr.net/articles/vignette-10-tracts.html","id":"demographic-model","dir":"Articles","previous_headings":"","what":"Demographic model","title":"Extracting true ancestry tracts","text":"Let’s imagine following demographic model Neanderthal introgression ancestors non-Africans (represented “EUR” “PAP” populations, approximating European Papuan people living today), followed Denisovan introgression ancestors Papuans:","code":"anc_all <- population(\"ancestor_all\", time = 700e3, N = 10000, remove = 640e3) afr <- population(\"AFR\", parent = anc_all, time = 650e3, N = 10000) anc_arch <- population(\"ancestor_archaics\", parent = anc_all, time = 650e3, N = 10000, remove = 390e3) nea <- population(\"NEA\", parent = anc_arch, time = 400e3, N = 2000, remove = 30e3) den <- population(\"DEN\", parent = anc_arch, time = 400e3, N = 2000, remove = 30e3) nonafr <- population(\"nonAFR\", parent = afr, time = 100e3, N = 3000, remove = 39e3) eur <- population(\"EUR\", parent = nonafr, time = 45e3, N = 5000) pap <- population(\"PAP\", parent = nonafr, time = 45e3, N = 5000) gf <- list( gene_flow(from = nea, to = nonafr, rate = 0.03, start = 55000, end = 50000), gene_flow(from = den, to = pap, rate = 0.07, start = 35000, end = 30000) ) model <- compile_model( populations = list(anc_all, afr, anc_arch, nea, den, nonafr, eur, pap), gene_flow = gf, generation_time = 30, serialize = FALSE ) plot_model( model, sizes = FALSE, order = c(\"AFR\", \"EUR\", \"nonAFR\", \"PAP\", \"ancestor_all\", \"DEN\", \"ancestor_archaics\", \"NEA\") )"},{"path":"https://www.slendr.net/articles/vignette-10-tracts.html","id":"tree-sequence-simulation","dir":"Articles","previous_headings":"","what":"Tree sequence simulation","title":"Extracting true ancestry tracts","text":"Let’s now simulate 50Mb tree sequence model, recording 50 diploid individuals EUR PAP populations:","code":"samples <- schedule_sampling(model, times = 0, list(eur, 50), list(pap, 50)) ts <- msprime(model, sequence_length = 100e6, recombination_rate = 1e-8, samples = samples, random_seed = 42)"},{"path":"https://www.slendr.net/articles/vignette-10-tracts.html","id":"extracting-ancestry-tracts","dir":"Articles","previous_headings":"","what":"Extracting ancestry tracts","title":"Extracting true ancestry tracts","text":"order extract tracts Neanderthal Denisovan ancestry, can use slendr’s new function ts_tracts() serves simplified R-friendly interface Python method tspop.get_pop_ancestry(). important piece information used function -called “census time”, records time recording “ancestral population” identity node ancestral subsegment sample set. Please see excellent vignette tspop information inner workings algorithm. case, let’s extract ancestry tracts corresponding ancestral nodes present 55 thousand years ago – time corresponds moment start archaic introgression: table ancestry tracts looks like. expect, see column indicating name individual, left right coordinates tract individual, well population name source ancestry tract:","code":"nea_tracts <- ts_tracts(ts, census = 55000) #> #> PopAncestry summary #> Number of ancestral populations: 3 #> Number of sample chromosomes: 200 #> Number of ancestors: 44052 #> Total length of genomes: 20000000000.000000 #> Ancestral coverage: 20000000000.000000 den_tracts <- ts_tracts(ts, census = 35000) #> #> PopAncestry summary #> Number of ancestral populations: 3 #> Number of sample chromosomes: 200 #> Number of ancestors: 55373 #> Total length of genomes: 20000000000.000000 #> Ancestral coverage: 20000000000.000000 tracts <- bind_rows(nea_tracts, den_tracts) tracts #> # A tibble: 17,002 × 8 #> name node_id pop source_pop left right length source_pop_id #> #> 1 EUR_1 0 EUR NEA 781887 852668 70781 3 #> 2 EUR_1 0 EUR NEA 1451389 1463837 12448 3 #> 3 EUR_1 0 EUR NEA 1596995 1601441 4446 3 #> 4 EUR_1 0 EUR NEA 1629857 1689656 59799 3 #> 5 EUR_1 0 EUR NEA 3203711 3339565 135854 3 #> 6 EUR_1 0 EUR NEA 3850629 3947923 97294 3 #> 7 EUR_1 0 EUR NEA 6190700 6205627 14927 3 #> 8 EUR_1 0 EUR NEA 10394211 10426667 32456 3 #> 9 EUR_1 0 EUR NEA 13044685 13180258 135573 3 #> 10 EUR_1 0 EUR NEA 14858956 14912068 53112 3 #> # ℹ 16,992 more rows"},{"path":"https://www.slendr.net/articles/vignette-10-tracts.html","id":"summaries-of-ancestral-proportions","dir":"Articles","previous_headings":"","what":"Summaries of ancestral proportions","title":"Extracting true ancestry tracts","text":"summarise ancestry proportions target EUR PAP populations, see EUR population carries ~3% Neanderthal ancestry also true PAP population. However, also see Papuans carry 7% Denisovan ancestry. consistent model, also expectation empirical data. Let’s visualize proportions individual level:","code":"summary <- tracts %>% group_by(name, node_id, pop, source_pop) %>% summarise(prop = sum(length) / 100e6) #> `summarise()` has grouped output by 'name', 'node_id', 'pop'. You can override #> using the `.groups` argument. summary %>% group_by(pop, source_pop) %>% summarise(mean(prop)) %>% arrange(source_pop, pop) #> `summarise()` has grouped output by 'pop'. You can override using the `.groups` #> argument. #> # A tibble: 3 × 3 #> # Groups: pop [2] #> pop source_pop `mean(prop)` #> #> 1 EUR NEA 0.0303 #> 2 PAP NEA 0.0348 #> 3 PAP DEN 0.0739 summary %>% ggplot(aes(source_pop, prop, color = source_pop, fill = source_pop)) + geom_jitter() + coord_cartesian(ylim = c(0, 0.2)) + geom_hline(yintercept = c(0.03, 0.08), linetype = 2) + ylab(\"ancestry proportion\") + facet_wrap(~ pop) + ggtitle(\"Ancestry proportions in each individual\", \"(vertical lines represent 3% and 7% baseline expectations\")"},{"path":"https://www.slendr.net/articles/vignette-10-tracts.html","id":"chromosome-painting-of-ancestry-tracts","dir":"Articles","previous_headings":"","what":"“Chromosome painting” of ancestry tracts","title":"Extracting true ancestry tracts","text":"tracts object contains coordinates every single ancestry segment simulated individuals, can “paint” chromosome two archaic human ancestries: lining NEA & DEN ancestry tracts EUR PAP populations, can see common origin Neanderthal ancestry non-African populations manifests significant overlap NEA tracts populations.","code":"tracts %>% mutate(chrom = paste(name, \" (node\", node_id, \")\")) %>% ggplot(aes(x = left, xend = right, y = chrom, yend = chrom, color = source_pop)) + geom_segment(linewidth = 3) + theme_minimal() + labs(x = \"position [bp]\", y = \"haplotype\") + ggtitle(\"True ancestry tracts along each chromosome\") + theme(axis.text.y = element_blank(), panel.grid = element_blank()) + facet_grid(pop ~ ., scales = \"free_y\")"},{"path":"https://www.slendr.net/articles/vignette-10-tracts.html","id":"average-tract-lengths","dir":"Articles","previous_headings":"","what":"Average tract lengths:","title":"Extracting true ancestry tracts","text":"Let’s compute simple summaries tract lengths simulated data, compare theoretical expectations. Theoretical expectations (Racimo Slatkin 2015, Box 1) Neanderthal tracts: Denisovan tracts: can see, simulations far theoretical expectations, giving us confidence simulations (ancestry tract extraction algorithm) working expected.","code":"tracts %>% group_by(pop, source_pop) %>% summarise(mean(length)) #> `summarise()` has grouped output by 'pop'. You can override using the `.groups` #> argument. #> # A tibble: 3 × 3 #> # Groups: pop [2] #> pop source_pop `mean(length)` #> #> 1 EUR NEA 65765. #> 2 PAP NEA 69204. #> 3 PAP DEN 100317. m <- 0.03 t <- 52500 / 30 r <- 1e-8 mean_nea <- 1 / ((1 - m) * r * (t - 1)) mean_nea #> [1] 58943.84 m <- 0.07 t <- 37500 / 30 r <- 1e-8 mean_den <- 1 / ((1 - m) * r * (t - 1)) mean_den #> [1] 86090.38"},{"path":"https://www.slendr.net/articles/vignette-10-tracts.html","id":"distribution-of-ancestry-tract-lengths","dir":"Articles","previous_headings":"","what":"Distribution of ancestry tract lengths","title":"Extracting true ancestry tracts","text":"Finally, let’s plot distributions lengths ancestry tracts. case archaic human introgression well studied ’s perhaps exciting look figures. said, less well studied species, might interesting use kinds simulations inference introgression times proportions via Approximate Bayesian Computation another method:","code":"expectation_df <- data.frame( pop = c(\"EUR\", \"PAP\", \"PAP\"), source_pop = c(\"NEA\", \"NEA\", \"DEN\"), length = c(mean_nea, mean_nea, mean_den) ) p_densities <- tracts %>% ggplot(aes(length, color = source_pop)) + geom_density() + geom_vline(data = expectation_df, aes(xintercept = length, color = source_pop), linetype = 2) + facet_wrap(~ pop) + ggtitle(\"Distribution of tract lengths per different ancestries\") cowplot::plot_grid(p_densities, p_densities + scale_x_log10(), nrow = 2)"},{"path":"https://www.slendr.net/articles/vignette-10-tracts.html","id":"pure-msprime-tree-sequence","dir":"Articles","previous_headings":"","what":"Pure msprime tree sequence","title":"Extracting true ancestry tracts","text":"Finally, sanity check, let’s use pure msprime simulation example official tspop documentation test ts_tracts() behaves expected even standard msprime tree-sequence object. First, let’s run simulation code exactly : Let’s save msprime tree sequence disk can load R (.e., approximating might want want use ts_tracts() without running slendr simulation first): Now let’s move R , load tree sequence slendr extract ancestry tracts using ts_tracts(): setting squashed = FALSE, get full, un-squashed ancestry segments, appropriate ancestral node ID: comparing two tables pandas data frames tspop documentation, can see obtained results.","code":"import msprime pop_size = 500 sequence_length = 1e7 seed = 98765 rho = 3e-8 # Make the Demography object. demography = msprime.Demography() demography.add_population(name=\"RED\", initial_size=pop_size) #> Population(initial_size=500, growth_rate=0, name='RED', description='', extra_metadata={}, default_sampling_time=None, initially_active=None, id=0) demography.add_population(name=\"BLUE\", initial_size=pop_size) #> Population(initial_size=500, growth_rate=0, name='BLUE', description='', extra_metadata={}, default_sampling_time=None, initially_active=None, id=1) demography.add_population(name=\"ADMIX\", initial_size=pop_size) #> Population(initial_size=500, growth_rate=0, name='ADMIX', description='', extra_metadata={}, default_sampling_time=None, initially_active=None, id=2) demography.add_population(name=\"ANC\", initial_size=pop_size) #> Population(initial_size=500, growth_rate=0, name='ANC', description='', extra_metadata={}, default_sampling_time=None, initially_active=None, id=3) demography.add_admixture( time=100, derived=\"ADMIX\", ancestral=[\"RED\", \"BLUE\"], proportions=[0.5, 0.5] ) #> Admixture(time=100, derived='ADMIX', ancestral=['RED', 'BLUE'], proportions=[0.5, 0.5]) demography.add_census(time=100.01) # Census is here! #> CensusEvent(time=100.01) demography.add_population_split( time=1000, derived=[\"RED\", \"BLUE\"], ancestral=\"ANC\" ) #> PopulationSplit(time=1000, derived=['RED', 'BLUE'], ancestral='ANC') # Simulate. ts = msprime.sim_ancestry( samples={\"RED\": 0, \"BLUE\": 0, \"ADMIX\" : 2}, demography=demography, random_seed=seed, sequence_length=sequence_length, recombination_rate=rho ) import tempfile path = tempfile.NamedTemporaryFile(suffix=\".trees\").name ts.dump(path) sim_ts <- ts_load(reticulate::py$path) squashed_tracts <- ts_tracts(sim_ts, census = 100.01, squashed = TRUE) #> #> PopAncestry summary #> Number of ancestral populations: 2 #> Number of sample chromosomes: 4 #> Number of ancestors: 118 #> Total length of genomes: 40000000.000000 #> Ancestral coverage: 40000000.000000 head(squashed_tracts) #> # A tibble: 6 × 4 #> sample left right population #> #> 1 0 0 419848 0 #> 2 0 419848 483009 1 #> 3 0 483009 1475765 0 #> 4 0 1475765 2427904 1 #> 5 0 2427904 3635390 0 #> 6 0 3635390 4606954 1 tail(squashed_tracts) #> # A tibble: 6 × 4 #> sample left right population #> #> 1 3 7134130 7362300 1 #> 2 3 7362300 7369409 0 #> 3 3 7369409 7596783 1 #> 4 3 7596783 8289015 0 #> 5 3 8289015 8918727 1 #> 6 3 8918727 10000000 0 full_tracts <- ts_tracts(sim_ts, census = 100.01, squashed = FALSE) #> #> PopAncestry summary #> Number of ancestral populations: 2 #> Number of sample chromosomes: 4 #> Number of ancestors: 118 #> Total length of genomes: 40000000.000000 #> Ancestral coverage: 40000000.000000 head(full_tracts) #> # A tibble: 6 × 5 #> sample left right ancestor population #> #> 1 0 0 33027 74 0 #> 2 0 33027 155453 33 0 #> 3 0 155453 290542 46 0 #> 4 0 290542 419848 18 0 #> 5 0 419848 483009 83 1 #> 6 0 483009 1475765 28 0 tail(full_tracts) #> # A tibble: 6 × 5 #> sample left right ancestor population #> #> 1 3 8477625 8672850 94 1 #> 2 3 8672850 8849756 95 1 #> 3 3 8849756 8918727 131 1 #> 4 3 8918727 9165035 44 0 #> 5 3 9165035 9176562 47 0 #> 6 3 9176562 10000000 58 0"},{"path":"https://www.slendr.net/authors.html","id":null,"dir":"","previous_headings":"","what":"Authors","title":"Authors and Citation","text":"Martin Petr. Author, maintainer.","code":""},{"path":"https://www.slendr.net/authors.html","id":"citation","dir":"","previous_headings":"","what":"Citation","title":"Authors and Citation","text":"Petr M (2024). slendr: Simulation Framework Spatiotemporal Population Genetics. R package version 0.9.0, https://github.com/bodkan/slendr.","code":"@Manual{, title = {slendr: A Simulation Framework for Spatiotemporal Population Genetics}, author = {Martin Petr}, year = {2024}, note = {R package version 0.9.0}, url = {https://github.com/bodkan/slendr}, }"},{"path":[]},{"path":"https://www.slendr.net/index.html","id":"overview-","dir":"","previous_headings":"","what":"Overview","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"slendr R package toolbox defining population genetic models simulating genomic data entirely R. originally conceived framework simulating spatially-explicit genomic data real geographic landscapes grown much . page briefly summarizes slendr’s important features. much detailed description slendr architecture extensive set practical code examples can found paper PCI journal website.","code":""},{"path":"https://www.slendr.net/index.html","id":"citing-slendr","dir":"","previous_headings":"","what":"Citing slendr","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"slendr paper now published Peer Community Journal! use slendr work, please cite : Petr, Martin; Haller, Benjamin C.; Ralph, Peter L.; Racimo, Fernando. slendr: framework spatio-temporal population genomic simulations geographic landscapes. Peer Community Journal, Volume 3 (2023), article . e121. doi : 10.24072/pcjournal.354. Citations help justify development fixing bugs! Thank ! ❤️","code":""},{"path":"https://www.slendr.net/index.html","id":"main-features","dir":"","previous_headings":"","what":"Main features","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"brief summary slendr’s important features. R package allows : Program demographic models, including population splits, population size changes, gene-flow events using extremely simple declarative language entirely R (see vignette example model-definition interface). Even complex models can written little code require bare minimum R programming knowledge (thing user needs know call R function R data frame look like). Execute slendr models using efficient, tailor-made SLiM msprime simulation scripts bundled R package. simulation engines save outputs form efficient tree-sequence data structure. SLiM msprime programming needed! Load, process, analyse tree-sequence outputs via slendr’s built-R interface tree-sequence library tskit. can compute many population genetic statistics R immediately simulation finishes directly output tree sequences, without convert files formats (VCF, EIGENSTRAT) analysis different software. Encode complex models population movements landscape (see brief example model , extended explanation tutorial). knowledge cartographic geospatial analysis concepts needed. Simulate dynamic spatial demographic models using SLiM’s continuous-space simulation capabilities directly R (, SLiM programming required). outputs simulations saved tree sequences can analysed using standard R geospatial data analysis libraries. slendr performs conversion tree sequence tables appropriate spatial R data type automatically. Specify within-population individual dispersal dynamics R interface leveraging SLiM’s individual interaction parameters implemented SLiM back-end script. Schedule sampling events specify many individuals’ genomes, populations, times (optionally, locations) recorded simulation engine (SLiM msprime) output tree-sequence files. Utilizing flexibility R wealth libraries statistics, geospatial analysis graphics, combining power population genetic simulation frameworks SLiM msprime, slendr R package makes possible write entire simulation analytic pipelines without need leave R environment.","code":""},{"path":"https://www.slendr.net/index.html","id":"testing-the-r-package-in-an-online-rstudio-session","dir":"","previous_headings":"","what":"Testing the R package in an online RStudio session","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"can open RStudio session test examples vignettes directly web browser clicking button (installation needed!): case RStudio instance appears starting slowly, please patient (Binder freely available service limited computational resources provided community). Binder crashes, try reloading web page, restart cloud session. get browser-based RStudio session, can navigate vignettes/ directory test examples !","code":""},{"path":"https://www.slendr.net/index.html","id":"installation","dir":"","previous_headings":"","what":"Installation","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"slendr now available CRAN means can install simply entering install.packages(\"slendr\") R console. like test latest features software (perhaps need bug fixes), can install devtools::install_github(\"bodkan/slendr\") (note requires R package devtools). ⚠️⚠️⚠️ Note: default slendr installation longer hard dependency geospatial R packages sf, stars, rnaturalearth. indend use slendr spatial genomic simulations data analysis, run install.packages(c(\"sf\", \"stars\", \"rnaturalearth\")) first. made change ease installation burden researchers might need slendr’s support traditional, non-spatial simulations (represent majority use-cases population genetics general). geospatial R packages imply non-negligible amount software dependencies , proven unnecessary hurdle many users might need (least first). ⚠️⚠️⚠️ software active development! like stay updated: Click “Watch” button project’s GitHub website. Follow social media posting progress updates (can find links homepage). time time, take look changelog post updates new features, breaking changes, etc.","code":""},{"path":"https://www.slendr.net/index.html","id":"example","dir":"","previous_headings":"","what":"Example","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"brief demonstration kind spatial model slendr originally designed simulate data . Please note although spatially-explicit population genetic model, slendr extensive support traditional, non-spatial simulations well. Furthermore, example shows specify simulate model R. doesn’t show analyse tree-sequence outputs compute population genetic statistics (important feature demonstrated tutorial).","code":""},{"path":"https://www.slendr.net/index.html","id":"id_1-setup-the-spatial-context","dir":"","previous_headings":"Example","what":"1. Setup the spatial context","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"Imagine wanted simulate spatio-temporal genomic data toy model history modern humans West Eurasia Africa migration. First, define spatial context simulation. represent “world” occupied populations model. can visualize defined world map using function plot_map provided package. Although example use real Earth landscape, map can completely abstract (either blank user-defined landscape features continents, islands, corridors barriers).","code":"library(slendr) # this sets up internal Python environment and needs to be ran only once! # (do not put this in your R scripts, run this command in the R console # after you (re-)install slendr) setup_env() # activate the internal Python environment needed for simulation and # tree-sequence processing init_env() map <- world( xrange = c(-13, 70), # min-max longitude yrange = c(18, 65), # min-max latitude crs = \"EPSG:3035\" # coordinate reference system (CRS) for West Eurasia ) plot_map(map)"},{"path":"https://www.slendr.net/index.html","id":"id_2-define-broader-geographic-regions","dir":"","previous_headings":"Example","what":"2. Define broader geographic regions","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"order make definitions population ranges () easier, can define smaller regions map using function region. Note coordinates slendr specified geographic coordinate system (.e., degrees longitude latitude), internally represented projected CRS (case, EPSG 3035 specified ). makes easier us define spatial features simply reading coordinates regular map internal projected CRS makes simulations accurate (distances shapes distorted can use CRS tailored region world working ). projected CRS takes care projection part world ’re interested three-dimensional Earth surface two-dimensional map. , can use generic plot_map function visualize objects, making sure specified correctly:","code":"africa <- region( \"Africa\", map, polygon = list(c(-18, 20), c(38, 20), c(30, 33), c(20, 33), c(10, 38), c(-6, 35)) ) europe <- region( \"Europe\", map, polygon = list( c(-8, 35), c(-5, 36), c(10, 38), c(20, 35), c(25, 35), c(33, 45), c(20, 58), c(-5, 60), c(-15, 50) ) ) anatolia <- region( \"Anatolia\", map, polygon = list(c(28, 35), c(40, 35), c(42, 40), c(30, 43), c(27, 40), c(25, 38)) ) plot_map(africa, europe, anatolia)"},{"path":"https://www.slendr.net/index.html","id":"id_3-define-demographic-history-and-population-boundaries","dir":"","previous_headings":"Example","what":"3. Define demographic history and population boundaries","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"important function slendr package population(), used define names, split times, sizes spatial ranges populations. , specify times years present, distances kilometers. makes sense models, times can also given forward direction. also note functions move() expand_range() designed take slendr population object schedule spatial dynamics appropriate times model simulation (happen later step). Note order make example executable reasonable time extremely old laptop, decreased sizes populations unrealistic levels. speed SLiM simulation later step. can use function plot_map get “compressed” overview spatio-temporal range dynamics encoded model far (prior simulation ).","code":"afr <- population( # African ancestral population \"AFR\", time = 52000, N = 3000, map = map, polygon = africa ) ooa <- population( # population of the first migrants out of Africa \"OOA\", parent = afr, time = 51000, N = 500, remove = 25000, center = c(33, 30), radius = 400e3 ) %>% move( trajectory = list(c(40, 30), c(50, 30), c(60, 40)), start = 50000, end = 40000, snapshots = 20 ) ehg <- population( # Eastern hunter-gatherers \"EHG\", parent = ooa, time = 28000, N = 1000, remove = 6000, polygon = list( c(26, 55), c(38, 53), c(48, 53), c(60, 53), c(60, 60), c(48, 63), c(38, 63), c(26, 60)) ) eur <- population( # European population name = \"EUR\", parent = ehg, time = 25000, N = 2000, polygon = europe ) ana <- population( # Anatolian farmers name = \"ANA\", time = 28000, N = 3000, parent = ooa, remove = 4000, center = c(34, 38), radius = 500e3, polygon = anatolia ) %>% expand_range( # expand the range by 2.500 km by = 2500e3, start = 10000, end = 7000, polygon = join(europe, anatolia), snapshots = 20 ) yam <- population( # Yamnaya steppe population name = \"YAM\", time = 7000, N = 500, parent = ehg, remove = 2500, polygon = list(c(26, 50), c(38, 49), c(48, 50), c(48, 56), c(38, 59), c(26, 56)) ) %>% move(trajectory = list(c(15, 50)), start = 5000, end = 3000, snapshots = 10) plot_map(afr, ooa, ehg, eur, ana, yam)"},{"path":"https://www.slendr.net/index.html","id":"id_4-define-gene-flow-events","dir":"","previous_headings":"Example","what":"4. Define gene-flow events","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"default, populations slendr mix even overlapping. order schedule gene-flow event two populations, can use function gene_flow. want specify multiple events , can collect events simple R list:","code":"gf <- list( gene_flow(from = ana, to = yam, rate = 0.5, start = 6500, end = 6400, overlap = FALSE), gene_flow(from = ana, to = eur, rate = 0.5, start = 8000, end = 6000), gene_flow(from = yam, to = eur, rate = 0.75, start = 4000, end = 3000) )"},{"path":"https://www.slendr.net/index.html","id":"id_5-compile-the-model-to-a-set-of-configuration-files","dir":"","previous_headings":"Example","what":"5. Compile the model to a set of configuration files","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"run simulation, compile individual model components (population objects gene-flow events) single R object, specifying additional model parameters. Additionally, performs internal consistency checks, making sure model parameters (split times, gene flow times, etc.) make sense (potentially quite computationally costly) simulation even run. Compiled model kept R object can passed different functions. example, simulate data slim() engine (also run simulation coalescent engine via msprime() function).","code":"model <- compile_model( populations = list(afr, ooa, ehg, eur, ana, yam), # populations defined above gene_flow = gf, generation_time = 30, resolution = 10e3, # resolution in meters per pixel competition = 130e3, mating = 100e3, # spatial interaction parameters dispersal = 70e3, # how far can offspring end up from their parents )"},{"path":"https://www.slendr.net/index.html","id":"id_6-visualize-the-model","dir":"","previous_headings":"Example","what":"6. Visualize the model","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"package provides R shiny-based browser app explore_model() checking model dynamics interactively visually. complex models, much better static spatial plots one showed step 2 : function two modes: Plotting (“playing”) spatial map dynamics: Displaying demographic history graph (splits gene-flow events) embedded specified model:","code":"explore_model(model)"},{"path":"https://www.slendr.net/index.html","id":"id_7-run-the-model-in-slim","dir":"","previous_headings":"Example","what":"7. Run the model in SLiM","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"Finally, can execute compiled model SLiM. run simulation batch mode, also run SLiMgui setting method = \"gui\". allow us inspect spatial simulation happens real time. slim function generates complete SLiM script tailored run spatial model defined . saves , user, tremendous amount time, don’t write new SLiM code every time design new demographic model. output simulation run slendr model always tree sequence, loaded object ts_slim. specified , slendr’s SLiM backend simulate 10 Mb sequence individual, produce tree sequence output simulation run can analysed many built-population genetic functions. default, individuals living end simulation recorded samples tree sequence. specific set samples (ancient modern) needed, can defined accordingly using dedicated function. Note although defined spatial model, just easily simulated standard, non-spatial data running model slendr’s msprime() back end without need make changes: quick overview SLiM simulation run summarised GIF animation. , please note simulation extremely simplified. simulated small number individuals population, also didn’t specify dispersal dynamics populations look clumped. point, either compute population genetic statistics interest perhaps analyse spatial features genealogies simulated model.","code":"ts_slim <- slim(model, sequence_length = 10e6, recombination_rate = 1e-8, method = \"batch\", random_seed = 314159) ts_msprime <- msprime(model, sequence_length = 10e6, recombination_rate = 1e-8) animate_model(model = model, file = locations_file, steps = 50, width = 500, height = 300)"},{"path":"https://www.slendr.net/index.html","id":"further-information","dir":"","previous_headings":"","what":"Further information","title":"A Simulation Framework for Spatiotemporal Population Genetics","text":"example provides brief incomplete overview full functionality slendr package. much slendr demonstrated . instance: can tweak parameters influencing dispersal dynamics (“clumpy” populations , far can offspring migrate parents, etc.) define change time. instance, can see animation , African population forms single “blob” really isn’t spread across entire population range. Tweaking dispersal parameters show vignette helps avoid . can use slendr program non-spatial models, means conceivable traditional, random-mating demographic model can simulated lines R code. can learn vignette (detail vignette). SLiM simulations can often quite slow compared coalescent counterparts, also provide functionality allowing simulate slendr models (without change!) using built-msprime back end script. See vignette tutorial works. can build complex spatial models still abstract (assuming real geographic location), including traditional simulations demes lattice structure. complete example shown vignette. slendr & SLiM save data tree-sequence file format, thanks R package reticulate interfacing Python code, full power tskit pyslim manipulating tree-sequence data right fingertips, within convenient environment R. extended example can found vignette. spatially explicit population models, slendr package automatically converts simulated output data format makes possible analyse many available R packages geospatial data analysis. brief description functionality can found vignette. can find complete reproducible code behind examples paper dedicated R vignette .","code":""},{"path":"https://www.slendr.net/reference/animate_model.html","id":null,"dir":"Reference","previous_headings":"","what":"Animate the simulated population dynamics — animate_model","title":"Animate the simulated population dynamics — animate_model","text":"Animate simulated population dynamics","code":""},{"path":"https://www.slendr.net/reference/animate_model.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Animate the simulated population dynamics — animate_model","text":"","code":"animate_model(model, file, steps, gif = NULL, width = 800, height = 560)"},{"path":"https://www.slendr.net/reference/animate_model.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Animate the simulated population dynamics — animate_model","text":"model Compiled slendr_model model object file Path table saved individual locations steps many frames animation ? gif Path output GIF file (animation object returned default) width, height Dimensions animation pixels","code":""},{"path":"https://www.slendr.net/reference/animate_model.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Animate the simulated population dynamics — animate_model","text":"gif = NULL, return gganimate animation object. Otherwise GIF file saved value returned.","code":""},{"path":"https://www.slendr.net/reference/area.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate the area covered by the given slendr object — area","title":"Calculate the area covered by the given slendr object — area","text":"Calculate area covered given slendr object","code":""},{"path":"https://www.slendr.net/reference/area.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate the area covered by the given slendr object — area","text":"","code":"area(x)"},{"path":"https://www.slendr.net/reference/area.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate the area covered by the given slendr object — area","text":"x Object class slendr","code":""},{"path":"https://www.slendr.net/reference/area.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate the area covered by the given slendr object — area","text":"Area covered input object. slendr_pop given, table population range area time point returned. slendr_region slendr_world object specified, total area covered object's spatial boundary returned.","code":""},{"path":"https://www.slendr.net/reference/area.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate the area covered by the given slendr object — area","text":"","code":"region_a <- region(\"A\", center = c(20, 50), radius = 20) region_b <- region(\"B\", polygon = list(c(50, 40), c(70, 40), c(70, 60), c(50, 60))) plot_map(region_a, region_b) # note that area won't be *exactly* equal to pi*r^2: # https://stackoverflow.com/a/65280376 area(region_a) #> [1] 1256.063 area(region_b) #> [1] 400"},{"path":"https://www.slendr.net/reference/as.phylo.slendr_phylo.html","id":null,"dir":"Reference","previous_headings":"","what":"Convert an annotated slendr_phylo object to a phylo object — as.phylo.slendr_phylo","title":"Convert an annotated slendr_phylo object to a phylo object — as.phylo.slendr_phylo","text":"function servers workaround around ggtree error: Error UseMethod(\".phylo\") : applicable method '.phylo' applied object class \"c('phylo', 'slendr_phylo')\"","code":""},{"path":"https://www.slendr.net/reference/as.phylo.slendr_phylo.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Convert an annotated slendr_phylo object to a phylo object — as.phylo.slendr_phylo","text":"","code":"# S3 method for slendr_phylo as.phylo(x, ...)"},{"path":"https://www.slendr.net/reference/as.phylo.slendr_phylo.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Convert an annotated slendr_phylo object to a phylo object — as.phylo.slendr_phylo","text":"x Tree object class slendr_phylo ... Additional (unused) arguments .phylo S3 method","code":""},{"path":"https://www.slendr.net/reference/as.phylo.slendr_phylo.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Convert an annotated slendr_phylo object to a phylo object — as.phylo.slendr_phylo","text":"Standard phylogenetic tree object implemented R package ape","code":""},{"path":"https://www.slendr.net/reference/check_dependencies.html","id":null,"dir":"Reference","previous_headings":"","what":"Check that the required dependencies are available for slendr to work — check_dependencies","title":"Check that the required dependencies are available for slendr to work — check_dependencies","text":"Check required dependencies available slendr work","code":""},{"path":"https://www.slendr.net/reference/check_dependencies.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Check that the required dependencies are available for slendr to work — check_dependencies","text":"","code":"check_dependencies(python = FALSE, slim = FALSE, quit = FALSE)"},{"path":"https://www.slendr.net/reference/check_dependencies.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Check that the required dependencies are available for slendr to work — check_dependencies","text":"python slendr Python environment required? slim SLiM required? quit R interpreter quit required slendr dependencies missing? option (turned default, set FALSE) used mainly avoiding running slendr man page examples machines lack dependencies. set TRUE, logical value returned.","code":""},{"path":"https://www.slendr.net/reference/check_dependencies.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Check that the required dependencies are available for slendr to work — check_dependencies","text":"quit = TRUE, values returned, quit = FALSE, scalar logical value returned indicating whether dependencies present.","code":""},{"path":"https://www.slendr.net/reference/check_env.html","id":null,"dir":"Reference","previous_headings":"","what":"Check that the active Python environment is setup for slendr — check_env","title":"Check that the active Python environment is setup for slendr — check_env","text":"function inspects Python environment activated reticulate package prints versions slendr Python dependencies console.","code":""},{"path":"https://www.slendr.net/reference/check_env.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Check that the active Python environment is setup for slendr — check_env","text":"","code":"check_env(verbose = TRUE)"},{"path":"https://www.slendr.net/reference/check_env.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Check that the active Python environment is setup for slendr — check_env","text":"verbose log message printed? FALSE, logical value returned (invisibly).","code":""},{"path":"https://www.slendr.net/reference/check_env.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Check that the active Python environment is setup for slendr — check_env","text":"Either TRUE (slendr Python environment present) FALSE (slendr Python environment present).","code":""},{"path":"https://www.slendr.net/reference/check_env.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Check that the active Python environment is setup for slendr — check_env","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. check_env() #> Summary of the currently active Python environment: #> #> Python binary: /Users/mp/Library/r-miniconda-arm64/envs/Python-3.12_msprime-1.3.0_tskit-0.5.6_pyslim-1.0.4_tspop-0.0.2/bin/python #> Python version: 3.12.1 | packaged by conda-forge | (main, Dec 23 2023, 08:01:35) [Clang 16.0.6 ] #> #> slendr requirements: #> - tskit: version 0.5.6 ✓ #> - msprime: version 1.3.0 ✓ #> - pyslim: version 1.0.4 ✓ #> - tspop: present ✓"},{"path":"https://www.slendr.net/reference/clear_env.html","id":null,"dir":"Reference","previous_headings":"","what":"Remove the automatically created slendr Python environment — clear_env","title":"Remove the automatically created slendr Python environment — clear_env","text":"Remove automatically created slendr Python environment","code":""},{"path":"https://www.slendr.net/reference/clear_env.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Remove the automatically created slendr Python environment — clear_env","text":"","code":"clear_env(force = FALSE)"},{"path":"https://www.slendr.net/reference/clear_env.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Remove the automatically created slendr Python environment — clear_env","text":"force Ask deleting environment?","code":""},{"path":"https://www.slendr.net/reference/clear_env.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Remove the automatically created slendr Python environment — clear_env","text":"return value, called side effects","code":""},{"path":"https://www.slendr.net/reference/compile_model.html","id":null,"dir":"Reference","previous_headings":"","what":"Compile a slendr demographic model — compile_model","title":"Compile a slendr demographic model — compile_model","text":"First, compiles vectorized population spatial maps series binary raster PNG files, format SLiM understands uses define population boundaries. extracts demographic model defined user (.e. population divergences gene flow events) series tables later used built-SLiM script program timing simulation events.","code":""},{"path":"https://www.slendr.net/reference/compile_model.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Compile a slendr demographic model — compile_model","text":"","code":"compile_model( populations, generation_time, path = NULL, resolution = NULL, competition = NULL, mating = NULL, dispersal = NULL, gene_flow = list(), overwrite = FALSE, force = FALSE, simulation_length = NULL, direction = NULL, serialize = TRUE, slim_script = NULL, description = \"\", sim_length = NULL )"},{"path":"https://www.slendr.net/reference/compile_model.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Compile a slendr demographic model — compile_model","text":"populations Object(s) slendr_pop class (multiple objects need specified list) generation_time Generation time (model time units) path Output directory model configuration files loaded backend SLiM script. NULL, model configuration files saved temporary directory. resolution many distance units per pixel? competition, mating Maximum spatial competition mating choice distance dispersal Standard deviation normal distribution parent-offspring distance gene_flow Gene flow events generated gene_flow function (either list data.frame objects format defined gene_flow function, single data.frame) overwrite Completely delete specified directory, case already exists, create new one? force Force deletion model directory already present? Useful non-interactive uses. interactive mode, user asked confirm deletion manually. simulation_length Total length simulation (required forward time models, optional models specified backward time units default run \"present time\") direction Intended direction time. normal circumstances parameter inferred model need set manually. serialize model files serialized disk? , R model object returned files created. speeds simulation msprime prevents using SLiM back end. slim_script Path SLiM script used executing model (default, bundled backend script used). NULL, SLiM script bundled slendr used. description Optional short description model sim_length Deprecated. Use simulation_length instead.","code":""},{"path":"https://www.slendr.net/reference/compile_model.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Compile a slendr demographic model — compile_model","text":"Compiled slendr_model model object encapsulates information specified model (populations involved, much gene flow occur, spatial resolution map, spatial dispersal mating parameters used SLiM simulation, applicable)","code":""},{"path":"https://www.slendr.net/reference/compile_model.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Compile a slendr demographic model — compile_model","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/distance.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate the distance between a pair of spatial boundaries — distance","title":"Calculate the distance between a pair of spatial boundaries — distance","text":"Calculate distance pair spatial boundaries","code":""},{"path":"https://www.slendr.net/reference/distance.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate the distance between a pair of spatial boundaries — distance","text":"","code":"distance(x, y, measure, time = NULL)"},{"path":"https://www.slendr.net/reference/distance.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate the distance between a pair of spatial boundaries — distance","text":"x, y Objects class slendr measure measure distance? can either 'border' (distance borders x y) 'center' (distance centroids). time Time closest spatial maps x y represent slendr_pop population boundaries (ignored general slendr_region objects)","code":""},{"path":"https://www.slendr.net/reference/distance.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate the distance between a pair of spatial boundaries — distance","text":"coordinate reference system specified, distance projected units (.e. meters) returned. Otherwise function returns normal Euclidean distance.","code":""},{"path":"https://www.slendr.net/reference/distance.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate the distance between a pair of spatial boundaries — distance","text":"","code":"# create two regions on a blank abstract landscape region_a <- region(\"A\", center = c(20, 50), radius = 20) region_b <- region(\"B\", center = c(80, 50), radius = 20) plot_map(region_a, region_b) # compute the distance between the centers of both population ranges distance(region_a, region_b, measure = \"center\") #> [1] 60 # compute the distance between the borders of both population ranges distance(region_a, region_b, measure = \"border\") #> [1] 20"},{"path":"https://www.slendr.net/reference/expand_range.html","id":null,"dir":"Reference","previous_headings":"","what":"Expand the population range — expand_range","title":"Expand the population range — expand_range","text":"Expands spatial population range specified distance given time-window","code":""},{"path":"https://www.slendr.net/reference/expand_range.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Expand the population range — expand_range","text":"","code":"expand_range( pop, by, end, start, overlap = 0.8, snapshots = NULL, polygon = NULL, lock = FALSE, verbose = TRUE )"},{"path":"https://www.slendr.net/reference/expand_range.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Expand the population range — expand_range","text":"pop Object class slendr_pop many units distance expand ? start, end expansion start/end? overlap Minimum overlap subsequent spatial boundaries snapshots number intermediate snapshots (overrides overlap parameter) polygon Geographic region restrict expansion lock Maintain density individuals. FALSE (default), number individuals population change. TRUE, number individuals simulated changed (increased decreased) appropriately, match new population range area. verbose Report progress generating intermediate spatial boundaries?","code":""},{"path":"https://www.slendr.net/reference/expand_range.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Expand the population range — expand_range","text":"Object class slendr_pop, contains population parameters name, time appearance simulation, parent population (), spatial parameters map spatial boundary.","code":""},{"path":"https://www.slendr.net/reference/expand_range.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Expand the population range — expand_range","text":"Note slendr models accomodate SLiM msprime back ends, population sizes times events rounded nearest integer value.","code":""},{"path":"https://www.slendr.net/reference/expand_range.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Expand the population range — expand_range","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/explore_model.html","id":null,"dir":"Reference","previous_headings":"","what":"Open an interactive browser of the spatial model — explore_model","title":"Open an interactive browser of the spatial model — explore_model","text":"Open interactive browser spatial model","code":""},{"path":"https://www.slendr.net/reference/explore_model.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Open an interactive browser of the spatial model — explore_model","text":"","code":"explore_model(model)"},{"path":"https://www.slendr.net/reference/explore_model.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Open an interactive browser of the spatial model — explore_model","text":"model Compiled slendr_model model object","code":""},{"path":"https://www.slendr.net/reference/explore_model.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Open an interactive browser of the spatial model — explore_model","text":"return value, called order start interactive browser-based interface explore dynamics slendr model","code":""},{"path":"https://www.slendr.net/reference/gene_flow.html","id":null,"dir":"Reference","previous_headings":"","what":"Define a gene-flow event between two populations — gene_flow","title":"Define a gene-flow event between two populations — gene_flow","text":"Define gene-flow event two populations","code":""},{"path":"https://www.slendr.net/reference/gene_flow.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Define a gene-flow event between two populations — gene_flow","text":"","code":"gene_flow(from, to, rate, start, end, overlap = TRUE)"},{"path":"https://www.slendr.net/reference/gene_flow.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Define a gene-flow event between two populations — gene_flow","text":", Objects class slendr_pop rate Scalar value range (0, 1] specifying proportion migration given time period start, end Start end gene-flow event overlap Require spatial overlap admixing populations? (default TRUE)","code":""},{"path":"https://www.slendr.net/reference/gene_flow.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Define a gene-flow event between two populations — gene_flow","text":"Object class data.frame containing parameters specified gene-flow event.","code":""},{"path":"https://www.slendr.net/reference/gene_flow.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Define a gene-flow event between two populations — gene_flow","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/init_env.html","id":null,"dir":"Reference","previous_headings":"","what":"Activate slendr's own dedicated Python environment — init_env","title":"Activate slendr's own dedicated Python environment — init_env","text":"function attempts activate dedicated slendr Miniconda Python environment previously set via setup_env.","code":""},{"path":"https://www.slendr.net/reference/init_env.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Activate slendr's own dedicated Python environment — init_env","text":"","code":"init_env(quiet = FALSE)"},{"path":"https://www.slendr.net/reference/init_env.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Activate slendr's own dedicated Python environment — init_env","text":"quiet informative messages printed console? Default FALSE.","code":""},{"path":"https://www.slendr.net/reference/init_env.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Activate slendr's own dedicated Python environment — init_env","text":"return value, called side effects","code":""},{"path":"https://www.slendr.net/reference/join.html","id":null,"dir":"Reference","previous_headings":"","what":"Merge two spatial slendr objects into one — join","title":"Merge two spatial slendr objects into one — join","text":"Merge two spatial slendr objects one","code":""},{"path":"https://www.slendr.net/reference/join.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Merge two spatial slendr objects into one — join","text":"","code":"join(x, y, name = NULL)"},{"path":"https://www.slendr.net/reference/join.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Merge two spatial slendr objects into one — join","text":"x Object class slendr y Object class slendr name Optional name resulting geographic region. missing, name constructed function arguments.","code":""},{"path":"https://www.slendr.net/reference/join.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Merge two spatial slendr objects into one — join","text":"Object class slendr_region encodes standard spatial object class sf several additional attributes (importantly corresponding slendr_map object, applicable).","code":""},{"path":"https://www.slendr.net/reference/join.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Merge two spatial slendr objects into one — join","text":"","code":"# create a blank abstract world 1000x1000 distance units in size blank_map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # it is possible to construct custom landscapes (islands, corridors, etc.) island1 <- region(\"island1\", polygon = list(c(10, 30), c(50, 30), c(40, 50), c(0, 40))) island2 <- region(\"island2\", polygon = list(c(60, 60), c(80, 40), c(100, 60), c(80, 80))) island3 <- region(\"island3\", center = c(20, 80), radius = 10) archipelago <- island1 %>% join(island2) %>% join(island3) custom_map <- world(xrange = c(1, 100), c(1, 100), landscape = archipelago) # real Earth landscapes can be defined using freely-available Natural Earth # project data and with the possibility to specify an appropriate Coordinate # Reference System, such as this example of a map of Europe real_map <- world(xrange = c(-15, 40), yrange = c(30, 60), crs = \"EPSG:3035\") #> Reading layer `ne_110m_land' from data source #> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpFhhY5X/naturalearth/ne_110m_land.shp' #> using driver `ESRI Shapefile' #> Simple feature collection with 127 features and 3 fields #> Geometry type: POLYGON #> Dimension: XY #> Bounding box: xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513 #> Geodetic CRS: WGS 84"},{"path":"https://www.slendr.net/reference/move.html","id":null,"dir":"Reference","previous_headings":"","what":"Move the population to a new location in a given amount of time — move","title":"Move the population to a new location in a given amount of time — move","text":"function defines displacement population along given trajectory given time frame","code":""},{"path":"https://www.slendr.net/reference/move.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Move the population to a new location in a given amount of time — move","text":"","code":"move( pop, trajectory, end, start, overlap = 0.8, snapshots = NULL, verbose = TRUE )"},{"path":"https://www.slendr.net/reference/move.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Move the population to a new location in a given amount of time — move","text":"pop Object class slendr_pop trajectory List two-dimensional vectors (longitude, latitude) specifying migration trajectory start, end Start/end points population migration overlap Minimum overlap subsequent spatial boundaries snapshots number intermediate snapshots (overrides overlap parameter) verbose Show progress searching number sufficient snapshots?","code":""},{"path":"https://www.slendr.net/reference/move.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Move the population to a new location in a given amount of time — move","text":"Object class slendr_pop, contains population parameters name, time appearance simulation, parent population (), spatial parameters map spatial boundary.","code":""},{"path":"https://www.slendr.net/reference/move.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Move the population to a new location in a given amount of time — move","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/msprime.html","id":null,"dir":"Reference","previous_headings":"","what":"Run a slendr model in msprime — msprime","title":"Run a slendr model in msprime — msprime","text":"function execute built-msprime script run compiled slendr demographic model.","code":""},{"path":"https://www.slendr.net/reference/msprime.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Run a slendr model in msprime — msprime","text":"","code":"msprime( model, sequence_length, recombination_rate, samples = NULL, output = NULL, random_seed = NULL, load = TRUE, verbose = FALSE, debug = FALSE, run = TRUE )"},{"path":"https://www.slendr.net/reference/msprime.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Run a slendr model in msprime — msprime","text":"model Model object created compile function sequence_length Total length simulated sequence (base-pairs) recombination_rate Recombination rate simulated sequence (recombinations per basepair per generation) samples data frame times given number individuals remembered tree-sequence (see schedule_sampling function can generate sampling schedule correct format). missing, individuals present end simulation recorded tree-sequence output file. output Path output tree-sequence file. NULL (default), tree sequence saved temporary file. random_seed Random seed (NULL, seed generated 0 maximum integer number available) load final tree sequence immediately loaded returned? Default TRUE. alternative (FALSE) useful tree-sequence file written custom location loaded later point. verbose Write output log console (default FALSE)? debug Write msprime's debug log console (default FALSE)? run msprime engine run? FALSE, command line msprime command printed (returned invisibly character vector) executed.","code":""},{"path":"https://www.slendr.net/reference/msprime.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Run a slendr model in msprime — msprime","text":"tree-sequence object loaded via Python-R reticulate interface function ts_load (internally represented Python object tskit.trees.TreeSequence). Optionally, depending value arguments load = run =, nothing character vector, respectively.","code":""},{"path":"https://www.slendr.net/reference/msprime.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Run a slendr model in msprime — msprime","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # afr and eur objects would normally be created before slendr model compilation, # but here we take them out of the model object already compiled for this # example (in a standard slendr simulation pipeline, this wouldn't be necessary) afr <- model$populations[[\"AFR\"]] eur <- model$populations[[\"EUR\"]] chimp <- model$populations[[\"CH\"]] # schedule the sampling of a couple of ancient and present-day individuals # given model at 20 ky, 10 ky, 5ky ago and at present-day (time 0) modern_samples <- schedule_sampling(model, times = 0, list(afr, 10), list(eur, 100), list(chimp, 1)) ancient_samples <- schedule_sampling(model, times = c(40000, 30000, 20000, 10000), list(eur, 1)) # sampling schedules are just data frames and can be merged easily samples <- rbind(modern_samples, ancient_samples) # run a simulation using the msprime back end from a compiled slendr model object ts <- msprime(model, sequence_length = 1e5, recombination_rate = 0, samples = samples) # automatic loading of a simulated output can be prevented by `load = FALSE`, which can be # useful when a custom path to a tree-sequence output is given for later downstream analyses output_file <- tempfile(fileext = \".trees\") msprime(model, sequence_length = 1e5, recombination_rate = 0, samples = samples, output = output_file, load = FALSE, random_seed = 42) # ... at a later stage: ts <- ts_load(output_file, model) summary(ts) #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 1║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 230║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 39.4 KiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤════╤═════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪═════════╪════════════╣ #> ║Edges │ 471│ 14.7 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Individuals│ 115│ 3.2 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Nodes │ 472│ 12.9 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Provenances│ 1│ 2.9 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧════╧═════════╧════════════╝ #>"},{"path":"https://www.slendr.net/reference/overlap.html","id":null,"dir":"Reference","previous_headings":"","what":"Generate the overlap of two slendr objects — overlap","title":"Generate the overlap of two slendr objects — overlap","text":"Generate overlap two slendr objects","code":""},{"path":"https://www.slendr.net/reference/overlap.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Generate the overlap of two slendr objects — overlap","text":"","code":"overlap(x, y, name = NULL)"},{"path":"https://www.slendr.net/reference/overlap.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Generate the overlap of two slendr objects — overlap","text":"x Object class slendr y Object class slendr name Optional name resulting geographic region. missing, name constructed function arguments.","code":""},{"path":"https://www.slendr.net/reference/overlap.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Generate the overlap of two slendr objects — overlap","text":"Object class slendr_region encodes standard spatial object class sf several additional attributes (importantly corresponding slendr_map object, applicable).","code":""},{"path":"https://www.slendr.net/reference/pipe.html","id":null,"dir":"Reference","previous_headings":"","what":"Pipe operator — %>%","title":"Pipe operator — %>%","text":"Pipe operator","code":""},{"path":"https://www.slendr.net/reference/pipe.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Pipe operator — %>%","text":"","code":"lhs %>% rhs"},{"path":"https://www.slendr.net/reference/pipe.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Pipe operator — %>%","text":"See magrittr::%>% details.","code":""},{"path":"https://www.slendr.net/reference/plot_map.html","id":null,"dir":"Reference","previous_headings":"","what":"Plot slendr geographic features on a map — plot_map","title":"Plot slendr geographic features on a map — plot_map","text":"Plots objects three slendr spatial classes (slendr_map, slendr_region, slendr_pop).","code":""},{"path":"https://www.slendr.net/reference/plot_map.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Plot slendr geographic features on a map — plot_map","text":"","code":"plot_map( ..., time = NULL, gene_flow = FALSE, graticules = \"original\", intersect = TRUE, show_map = TRUE, title = NULL, interpolated_maps = NULL )"},{"path":"https://www.slendr.net/reference/plot_map.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Plot slendr geographic features on a map — plot_map","text":"... Objects classes slendr_map, slendr_region, slendr_pop time Plot concrete time point gene_flow Indicate geneflow events arrow graticules Plot graticules original Coordinate Reference System (longitude-latitude), internal CRS (meters)? intersect Intersect population boundaries landscape geographic boundaries (default TRUE)? show_map Show underlying world map title Title plot interpolated_maps Interpolated spatial boundaries populations time points (used plotting using explore shiny app)","code":""},{"path":"https://www.slendr.net/reference/plot_map.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Plot slendr geographic features on a map — plot_map","text":"ggplot2 object visualized slendr map","code":""},{"path":"https://www.slendr.net/reference/plot_model.html","id":null,"dir":"Reference","previous_headings":"","what":"Plot demographic history encoded in a slendr model — plot_model","title":"Plot demographic history encoded in a slendr model — plot_model","text":"Plot demographic history encoded slendr model","code":""},{"path":"https://www.slendr.net/reference/plot_model.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Plot demographic history encoded in a slendr model — plot_model","text":"","code":"plot_model( model, sizes = TRUE, proportions = FALSE, gene_flow = TRUE, log = FALSE, order = NULL, file = NULL, ... )"},{"path":"https://www.slendr.net/reference/plot_model.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Plot demographic history encoded in a slendr model — plot_model","text":"model Compiled slendr_model model object sizes population size changes visualized? proportions gene flow proportions visualized (FALSE default prevent cluttering overplotting) gene_flow gene-flow arrows visualized (default TRUE). log y-axis plotted log scale? Useful models long time-scales. order Order populations along x-axis, given character vector population names. NULL (default), default plotting algorithm used, ordering populations ancestral recent using -order tree traversal. file Output file figure saved via ggsave ... Optional argument passed ggsave","code":""},{"path":"https://www.slendr.net/reference/plot_model.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Plot demographic history encoded in a slendr model — plot_model","text":"ggplot2 object visualized slendr model","code":""},{"path":"https://www.slendr.net/reference/plot_model.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Plot demographic history encoded in a slendr model — plot_model","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence path <- system.file(\"extdata/models/introgression\", package = \"slendr\") model <- read_model(path) plot_model(model, sizes = FALSE, log = TRUE)"},{"path":"https://www.slendr.net/reference/population.html","id":null,"dir":"Reference","previous_headings":"","what":"Define a population — population","title":"Define a population — population","text":"Defines parameters population (non-spatial spatial).","code":""},{"path":"https://www.slendr.net/reference/population.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Define a population — population","text":"","code":"population( name, time, N, parent = NULL, map = FALSE, center = NULL, radius = NULL, polygon = NULL, remove = NULL, intersect = TRUE, competition = NA, mating = NA, dispersal = NA, dispersal_fun = NULL, aquatic = FALSE )"},{"path":"https://www.slendr.net/reference/population.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Define a population — population","text":"name Name population time Time population's first appearance N Number individuals time first appearance parent Parent population object NULL (indicates population ancestor, first population \"lineage\") map Object type slendr_map defines world context (created using world function). value FALSE provided, non-spatial model run. center Two-dimensional vector specifying center circular range radius Radius circular range polygon List vector pairs, defining corners polygon range geographic region class slendr_region polygon coordinates extracted (see region() function) remove Time population removed intersect Intersect population's boundaries landscape features? competition, mating Maximum spatial competition mating choice distance dispersal Standard deviation normal distribution distance offspring disperses parent dispersal_fun Distribution function governing dispersal offspring. One \"normal\", \"uniform\", \"cauchy\", \"exponential\", \"brownian\" (vertical horizontal displacements drawn normal distribution independently). aquatic species aquatic (FALSE default, .e. terrestrial species)?","code":""},{"path":"https://www.slendr.net/reference/population.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Define a population — population","text":"Object class slendr_pop, contains population parameters name, time appearance simulation, parent population (), spatial parameters map spatial boundary.","code":""},{"path":"https://www.slendr.net/reference/population.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Define a population — population","text":"four ways specify spatial boundary: ) circular range specified using center coordinate radius, ii) polygon specified list two-dimensional vector coordinates, iii) polygon ii), defined (named) using region function, iv) just world map specified (circular polygon range parameters set default NULL value), population allowed occupy entire landscape. Note slendr models accomodate SLiM msprime back ends, population sizes split times rounded nearest integer value.","code":""},{"path":"https://www.slendr.net/reference/population.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Define a population — population","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/print.slendr_pop.html","id":null,"dir":"Reference","previous_headings":"","what":"Print a short summary of a slendr object — print.slendr_pop","title":"Print a short summary of a slendr object — print.slendr_pop","text":"spatial objects slendr package internally represented Simple Features (sf) objects. fact hidden circumstances , goal slendr package provide functionality much higher level (population boundaries, geographic regions, instead individual polygons \"low-level\" geometric objects), without users worry low-level details involved handling spatial geometries. However, full sf object representation can always printed calling x[].","code":""},{"path":"https://www.slendr.net/reference/print.slendr_pop.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Print a short summary of a slendr object — print.slendr_pop","text":"","code":"# S3 method for slendr_pop print(x, ...) # S3 method for slendr_region print(x, ...) # S3 method for slendr_map print(x, ...) # S3 method for slendr_model print(x, ...)"},{"path":"https://www.slendr.net/reference/print.slendr_pop.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Print a short summary of a slendr object — print.slendr_pop","text":"x Object class slendr (either slendr_pop, slendr_map, slendr_region, slendr_table) ... Additional arguments passed print","code":""},{"path":"https://www.slendr.net/reference/print.slendr_pop.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Print a short summary of a slendr object — print.slendr_pop","text":"return value, used printing","code":""},{"path":"https://www.slendr.net/reference/print.slendr_ts.html","id":null,"dir":"Reference","previous_headings":"","what":"Print tskit's summary table of the Python tree-sequence object — print.slendr_ts","title":"Print tskit's summary table of the Python tree-sequence object — print.slendr_ts","text":"Print tskit's summary table Python tree-sequence object","code":""},{"path":"https://www.slendr.net/reference/print.slendr_ts.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Print tskit's summary table of the Python tree-sequence object — print.slendr_ts","text":"","code":"# S3 method for slendr_ts print(x, ...)"},{"path":"https://www.slendr.net/reference/print.slendr_ts.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Print tskit's summary table of the Python tree-sequence object — print.slendr_ts","text":"x Tree object class slendr_phylo ... Additional arguments normally passed print (used case)","code":""},{"path":"https://www.slendr.net/reference/print.slendr_ts.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Print tskit's summary table of the Python tree-sequence object — print.slendr_ts","text":"return value, simply prints tskit summary table terminal","code":""},{"path":"https://www.slendr.net/reference/read_model.html","id":null,"dir":"Reference","previous_headings":"","what":"Read a previously serialized model configuration — read_model","title":"Read a previously serialized model configuration — read_model","text":"Reads configuration tables model data location previously compiled compile function.","code":""},{"path":"https://www.slendr.net/reference/read_model.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Read a previously serialized model configuration — read_model","text":"","code":"read_model(path)"},{"path":"https://www.slendr.net/reference/read_model.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Read a previously serialized model configuration — read_model","text":"path Directory required configuration files","code":""},{"path":"https://www.slendr.net/reference/read_model.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Read a previously serialized model configuration — read_model","text":"Compiled slendr_model model object encapsulates information specified model (populations involved, much gene flow occur, spatial resolution map, spatial dispersal mating parameters used SLiM simulation, applicable)","code":""},{"path":"https://www.slendr.net/reference/read_model.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Read a previously serialized model configuration — read_model","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence path <- system.file(\"extdata/models/introgression\", package = \"slendr\") model <- read_model(path) plot_model(model, sizes = FALSE, log = TRUE)"},{"path":"https://www.slendr.net/reference/region.html","id":null,"dir":"Reference","previous_headings":"","what":"Define a geographic region — region","title":"Define a geographic region — region","text":"Creates geographic region (polygon) given map gives name. can used define objects can reused multiple places slendr script (region arguments population) without repeatedly define polygon coordinates.","code":""},{"path":"https://www.slendr.net/reference/region.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Define a geographic region — region","text":"","code":"region(name = NULL, map = NULL, center = NULL, radius = NULL, polygon = NULL)"},{"path":"https://www.slendr.net/reference/region.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Define a geographic region — region","text":"name Name geographic region map Object type sf defines map center Two-dimensional vector specifying center circular range radius Radius circular range polygon List vector pairs, defining corners polygon range geographic region class slendr_region polygon coordinates extracted (see region() function)","code":""},{"path":"https://www.slendr.net/reference/region.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Define a geographic region — region","text":"Object class slendr_region encodes standard spatial object class sf several additional attributes (importantly corresponding slendr_map object, applicable).","code":""},{"path":"https://www.slendr.net/reference/region.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Define a geographic region — region","text":"","code":"# create a blank abstract world 1000x1000 distance units in size blank_map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # it is possible to construct custom landscapes (islands, corridors, etc.) island1 <- region(\"island1\", polygon = list(c(10, 30), c(50, 30), c(40, 50), c(0, 40))) island2 <- region(\"island2\", polygon = list(c(60, 60), c(80, 40), c(100, 60), c(80, 80))) island3 <- region(\"island3\", center = c(20, 80), radius = 10) archipelago <- island1 %>% join(island2) %>% join(island3) custom_map <- world(xrange = c(1, 100), c(1, 100), landscape = archipelago) # real Earth landscapes can be defined using freely-available Natural Earth # project data and with the possibility to specify an appropriate Coordinate # Reference System, such as this example of a map of Europe real_map <- world(xrange = c(-15, 40), yrange = c(30, 60), crs = \"EPSG:3035\") #> Reading layer `ne_110m_land' from data source #> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpFhhY5X/naturalearth/ne_110m_land.shp' #> using driver `ESRI Shapefile' #> Simple feature collection with 127 features and 3 fields #> Geometry type: POLYGON #> Dimension: XY #> Bounding box: xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513 #> Geodetic CRS: WGS 84"},{"path":"https://www.slendr.net/reference/reproject.html","id":null,"dir":"Reference","previous_headings":"","what":"Reproject coordinates between coordinate systems — reproject","title":"Reproject coordinates between coordinate systems — reproject","text":"Converts coordinates compiled raster map (.e. pixel units) different Geographic Coordinate Systems (CRS).","code":""},{"path":"https://www.slendr.net/reference/reproject.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Reproject coordinates between coordinate systems — reproject","text":"","code":"reproject( from, to, x = NULL, y = NULL, coords = NULL, model = NULL, add = FALSE, input_prefix = \"\", output_prefix = \"new\" )"},{"path":"https://www.slendr.net/reference/reproject.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Reproject coordinates between coordinate systems — reproject","text":", Either CRS code accepted GDAL, valid integer EPSG value, object class crs, value \"raster\" (converting /pixel coordinates), \"world\" (converting /whatever CRS set underlying map) x, y Coordinates two dimensions (missing, coordinates expected data.frame specified coords parameter columns \"x\" \"y\") coords data.frame-like object coordinates columns \"x\" \"y\" model Object class slendr_model add Add column coordinates input data.frame coords (coordinates otherwise returned separate object)? input_prefix, output_prefix Input output prefixes data frame columns spatial coordinates","code":""},{"path":"https://www.slendr.net/reference/reproject.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Reproject coordinates between coordinate systems — reproject","text":"Data.frame converted two-dimensional coordinates given input","code":""},{"path":"https://www.slendr.net/reference/reproject.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Reproject coordinates between coordinate systems — reproject","text":"","code":"lon_lat_df <- data.frame(x = c(30, 0, 15), y = c(60, 40, 10)) reproject( from = \"epsg:4326\", to = \"epsg:3035\", coords = lon_lat_df, add = TRUE # add converted [lon,lat] coordinates as a new column ) #> # A tibble: 3 × 4 #> x y newx newy #> #> 1 30 60 5422493. 4256803. #> 2 0 40 3465349. 1934879. #> 3 15 10 4907297. -1328914."},{"path":"https://www.slendr.net/reference/resize.html","id":null,"dir":"Reference","previous_headings":"","what":"Change the population size — resize","title":"Change the population size — resize","text":"Resizes population starting current value N individuals specified value","code":""},{"path":"https://www.slendr.net/reference/resize.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Change the population size — resize","text":"","code":"resize(pop, N, how, time, end = NULL)"},{"path":"https://www.slendr.net/reference/resize.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Change the population size — resize","text":"pop Object class slendr_pop N Population size change change population size (options \"step\" \"exponential\") time Time population size change end End population size change period (used exponential change events)","code":""},{"path":"https://www.slendr.net/reference/resize.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Change the population size — resize","text":"Object class slendr_pop, contains population parameters name, time appearance simulation, parent population (), spatial parameters map spatial boundary.","code":""},{"path":"https://www.slendr.net/reference/resize.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Change the population size — resize","text":"case exponential size change, final N larger current size, population exponentially growing specified time period reaches N individuals. N smaller, population shrink exponentially. Note slendr models accomodate SLiM msprime back ends, population sizes split times rounded nearest integer value.","code":""},{"path":"https://www.slendr.net/reference/resize.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Change the population size — resize","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/schedule_sampling.html","id":null,"dir":"Reference","previous_headings":"","what":"Define sampling events for a given set of populations — schedule_sampling","title":"Define sampling events for a given set of populations — schedule_sampling","text":"Schedule sampling events specified times , optionally, given set locations landscape","code":""},{"path":"https://www.slendr.net/reference/schedule_sampling.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Define sampling events for a given set of populations — schedule_sampling","text":"","code":"schedule_sampling(model, times, ..., locations = NULL, strict = FALSE)"},{"path":"https://www.slendr.net/reference/schedule_sampling.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Define sampling events for a given set of populations — schedule_sampling","text":"model Object class slendr_model times Integer vector times (model time units) schedule remembering individuals tree-sequence ... Lists two elements (slendr_pop population object- The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence path <- system.file(\"extdata/models/introgression\", package = \"slendr\") model <- read_model(path) # afr and eur objects would normally be created before slendr model compilation, # but here we take them out of the model object already compiled for this # example (in a standard slendr simulation pipeline, this wouldn't be necessary) afr <- model$populations[[\"AFR\"]] eur <- model$populations[[\"EUR\"]] # schedule the recording of 10 African and 100 European individuals from a # given model at 20 ky, 10 ky, 5ky ago and at present-day (time 0) schedule <- schedule_sampling( model, times = c(20000, 10000, 5000, 0), list(afr, 10), list(eur, 100) ) # the result of `schedule_sampling` is a simple data frame (note that the locations # of sampling locations have `NA` values because the model is non-spatial) schedule #> # A tibble: 8 × 7 #> time pop n y_orig x_orig y x #> #> 1 0 AFR 10 NA NA NA NA #> 2 0 EUR 100 NA NA NA NA #> 3 5000 AFR 10 NA NA NA NA #> 4 5000 EUR 100 NA NA NA NA #> 5 10000 AFR 10 NA NA NA NA #> 6 10000 EUR 100 NA NA NA NA #> 7 20000 AFR 10 NA NA NA NA #> 8 20000 EUR 100 NA NA NA NA"},{"path":"https://www.slendr.net/reference/set_dispersal.html","id":null,"dir":"Reference","previous_headings":"","what":"Change dispersal parameters — set_dispersal","title":"Change dispersal parameters — set_dispersal","text":"Changes either competition interactive distance, mating choice distance, dispersal offspring parent","code":""},{"path":"https://www.slendr.net/reference/set_dispersal.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Change dispersal parameters — set_dispersal","text":"","code":"set_dispersal( pop, time, competition = NA, mating = NA, dispersal = NA, dispersal_fun = NULL )"},{"path":"https://www.slendr.net/reference/set_dispersal.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Change dispersal parameters — set_dispersal","text":"pop Object class slendr_pop time Time population size change competition, mating Maximum spatial competition mating choice distance dispersal Standard deviation normal distribution distance offspring disperses parent dispersal_fun Distribution function governing dispersal offspring. One \"normal\", \"uniform\", \"cauchy\", \"exponential\", \"brownian\" (vertical horizontal displacements drawn normal distribution independently).","code":""},{"path":"https://www.slendr.net/reference/set_dispersal.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Change dispersal parameters — set_dispersal","text":"Object class slendr_pop, contains population parameters name, time appearance simulation, parent population (), spatial parameters map spatial boundary.","code":""},{"path":"https://www.slendr.net/reference/set_dispersal.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Change dispersal parameters — set_dispersal","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/set_range.html","id":null,"dir":"Reference","previous_headings":"","what":"Update the population range — set_range","title":"Update the population range — set_range","text":"function allows manual control spatial map changes addition expand move functions","code":""},{"path":"https://www.slendr.net/reference/set_range.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Update the population range — set_range","text":"","code":"set_range( pop, time, center = NULL, radius = NULL, polygon = NULL, lock = FALSE )"},{"path":"https://www.slendr.net/reference/set_range.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Update the population range — set_range","text":"pop Object class slendr_pop time Time change center Two-dimensional vector specifying center circular range radius Radius circular range polygon List vector pairs, defining corners polygon range (see also region argument) geographic region class slendr_region polygon coordinates extracted lock Maintain density individuals. FALSE (default), number individuals population change. TRUE, number individuals simulated changed (increased decreased) appropriately, match new population range area.","code":""},{"path":"https://www.slendr.net/reference/set_range.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Update the population range — set_range","text":"Object class slendr_pop, contains population parameters name, time appearance simulation, parent population (), spatial parameters map spatial boundary.","code":""},{"path":"https://www.slendr.net/reference/set_range.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Update the population range — set_range","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/setup_env.html","id":null,"dir":"Reference","previous_headings":"","what":"Setup a dedicated Python virtual environment for slendr — setup_env","title":"Setup a dedicated Python virtual environment for slendr — setup_env","text":"function automatically download Python miniconda distribution dedicated R-Python interface. also create slendr-specific Python environment required Python dependencies.","code":""},{"path":"https://www.slendr.net/reference/setup_env.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Setup a dedicated Python virtual environment for slendr — setup_env","text":"","code":"setup_env(quiet = FALSE, agree = FALSE, pip = NULL)"},{"path":"https://www.slendr.net/reference/setup_env.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Setup a dedicated Python virtual environment for slendr — setup_env","text":"quiet informative messages printed console? Default FALSE. agree Automatically agree questions? pip pip used instead conda installing slendr's Python dependencies? Note still use conda distribution install Python , change repository slendr install Python dependencies. Unless explicitly set TRUE, Python dependencies installed conda repositories default, expect case osx-arm64 Mac architecture, conda dependencies broken.","code":""},{"path":"https://www.slendr.net/reference/setup_env.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Setup a dedicated Python virtual environment for slendr — setup_env","text":"return value, called side effects","code":""},{"path":"https://www.slendr.net/reference/shrink_range.html","id":null,"dir":"Reference","previous_headings":"","what":"Shrink the population range — shrink_range","title":"Shrink the population range — shrink_range","text":"Shrinks spatial population range specified distance given time-window","code":""},{"path":"https://www.slendr.net/reference/shrink_range.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Shrink the population range — shrink_range","text":"","code":"shrink_range( pop, by, end, start, overlap = 0.8, snapshots = NULL, lock = FALSE, verbose = TRUE )"},{"path":"https://www.slendr.net/reference/shrink_range.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Shrink the population range — shrink_range","text":"pop Object class slendr_pop many units distance shrink ? start, end boundary shrinking start/end? overlap Minimum overlap subsequent spatial boundaries snapshots number intermediate snapshots (overrides overlap parameter) lock Maintain density individuals. FALSE (default), number individuals population change. TRUE, number individuals simulated changed (increased decreased) appropriately, match new population range area. verbose Report progress generating intermediate spatial boundaries?","code":""},{"path":"https://www.slendr.net/reference/shrink_range.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Shrink the population range — shrink_range","text":"Object class slendr_pop, contains population parameters name, time appearance simulation, parent population (), spatial parameters map spatial boundary.","code":""},{"path":"https://www.slendr.net/reference/shrink_range.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Shrink the population range — shrink_range","text":"Note slendr models accomodate SLiM msprime back ends, population sizes split times rounded nearest integer value.","code":""},{"path":"https://www.slendr.net/reference/shrink_range.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Shrink the population range — shrink_range","text":"","code":"# spatial definitions ----------------------------------------------------- # create a blank abstract world 1000x1000 distance units in size map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # create a circular population with the center of a population boundary at # [200, 800] and a radius of 100 distance units, 1000 individuals at time 1 # occupying a map just specified pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) # printing a population object to a console shows a brief summary pop1 #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 1 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) # create another population occupying a polygon range, splitting from pop1 # at a given time point (note that specifying a map is not necessary because # it is \"inherited\" from the parent) pop2 <- population(\"pop2\", N = 100, time = 50, parent = pop1, polygon = list(c(100, 100), c(320, 30), c(500, 200), c(500, 400), c(300, 450), c(100, 400))) pop3 <- population(\"pop3\", N = 200, time = 80, parent = pop2, center = c(800, 800), radius = 200) # move \"pop1\" to another location along a specified trajectory and saved the # resulting object to the same variable (the number of intermediate spatial # snapshots can be also determined automatically by leaving out the # `snapshots = ` argument) pop1_moved <- move(pop1, start = 100, end = 200, snapshots = 6, trajectory = list(c(600, 820), c(800, 400), c(800, 150))) pop1_moved #> slendr 'population' object #> -------------------------- #> name: pop1 #> habitat: terrestrial #> #> number of spatial maps: 10 #> map: abstract spatial landscape with custom features #> stays until the end of the simulation #> #> population history overview: #> - time 1: created as an ancestral population (N = 1000) #> - time 100-200: movement across a landscape # many slendr functions are pipe-friendly, making it possible to construct # pipelines which construct entire history of a population pop1 <- population(\"pop1\", N = 1000, time = 1, map = map, center = c(200, 800), radius = 100) %>% move(start = 100, end = 200, snapshots = 6, trajectory = list(c(400, 800), c(600, 700), c(800, 400), c(800, 150))) %>% set_range(time = 300, polygon = list( c(400, 0), c(1000, 0), c(1000, 600), c(900, 400), c(800, 250), c(600, 100), c(500, 50)) ) # population ranges can expand by a given distance in all directions pop2 <- expand_range(pop2, by = 200, start = 50, end = 150, snapshots = 3) # we can check the positions of all populations interactively by plotting their # ranges together on a single map plot_map(pop1, pop2, pop3) # gene flow events -------------------------------------------------------- # individual gene flow events can be saved to a list gf <- list( gene_flow(from = pop1, to = pop3, start = 150, end = 200, rate = 0.15), gene_flow(from = pop1, to = pop2, start = 300, end = 330, rate = 0.25) ) # compilation ------------------------------------------------------------- # compile model components in a serialized form to dist, returning a single # slendr model object (in practice, the resolution should be smaller) model <- compile_model( populations = list(pop1, pop2, pop3), generation_time = 1, resolution = 100, simulation_length = 500, competition = 5, mating = 5, dispersal = 1 )"},{"path":"https://www.slendr.net/reference/slendr.html","id":null,"dir":"Reference","previous_headings":"","what":"A Simulation Framework for Spatiotemporal Population Genetics — slendr","title":"A Simulation Framework for Spatiotemporal Population Genetics — slendr","text":"framework simulating spatially explicit genomic data leverages real cartographic information programmatic visual encoding spatiotemporal population dynamics real geographic landscapes. Population genetic models automatically executed 'SLiM' software behind scenes, using custom built-simulation 'SLiM' script. Additionally, fully abstract spatial models tied specific geographic location supported, users can also simulate data standard, non-spatial, random-mating models. can simulated either 'SLiM' built-back-end script, using efficient coalescent population genetics simulator 'msprime' custom-built 'Python' script bundled R package. Simulated genomic data saved tree-sequence format can loaded, manipulated, summarised using tree-sequence functionality via R interface 'Python' module 'tskit'. Complete model configuration, simulation analysis pipelines can therefore constructed without need leave R environment, eliminating friction disparate tools population genetic simulations data analysis.","code":""},{"path":"https://www.slendr.net/reference/slendr.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"A Simulation Framework for Spatiotemporal Population Genetics — slendr","text":"can find installation instructions, reference manual, tutorials https://www.slendr.net.","code":""},{"path":[]},{"path":"https://www.slendr.net/reference/slendr.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"A Simulation Framework for Spatiotemporal Population Genetics — slendr","text":"Maintainer: Martin Petr contact@bodkan.net (ORCID)","code":""},{"path":"https://www.slendr.net/reference/slim.html","id":null,"dir":"Reference","previous_headings":"","what":"Run a slendr model in SLiM — slim","title":"Run a slendr model in SLiM — slim","text":"function execute SLiM script generated compile function compilation slendr demographic model.","code":""},{"path":"https://www.slendr.net/reference/slim.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Run a slendr model in SLiM — slim","text":"","code":"slim( model, sequence_length, recombination_rate, samples = NULL, output = NULL, burnin = 0, max_attempts = 1, spatial = !is.null(model$world), coalescent_only = TRUE, method = c(\"batch\", \"gui\"), random_seed = NULL, run = TRUE, verbose = FALSE, load = TRUE, locations = NULL, slim_path = NULL )"},{"path":"https://www.slendr.net/reference/slim.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Run a slendr model in SLiM — slim","text":"model Model object created compile function sequence_length Total length simulated sequence (base-pairs) recombination_rate Recombination rate simulated sequence (recombinations per basepair per generation) samples data frame times given number individuals remembered tree-sequence (see schedule_sampling function can generate sampling schedule correct format). missing, individuals present end simulation recorded tree-sequence output file. output Path output tree-sequence file. NULL (default), tree sequence saved temporary file. burnin Length burnin (model's time units, .e. years) max_attempts many attempts made place offspring near one parents? Serves prevent infinite loops SLiM backend. Default value 1. spatial model executed spatial mode? default, world map specified model definition, simulation proceed spatial mode. coalescent_only initializeTreeSeq(retainCoalescentOnly = <...>) set TRUE (default) FALSE? See \"retainCoalescentOnly\" SLiM manual detail. method run script? (\"gui\" - open SLiMgui, \"batch\" - run command line) random_seed Random seed (NULL, seed generated 0 maximum integer number available) run SLiM engine run? FALSE, command line SLiM command printed (returned invisibly character vector) executed. verbose Write SLiM output log console (default FALSE)? load final tree sequence immediately loaded returned? Default TRUE. alternative (FALSE) useful tree-sequence file written custom location loaded later point. locations NULL, locations saved. Otherwise, path file locations individual throughout simulation saved (likely use animate_model). slim_path Path appropriate SLiM binary (useful slim binary $PATH). Note argument must specified function run Windows.","code":""},{"path":"https://www.slendr.net/reference/slim.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Run a slendr model in SLiM — slim","text":"tree-sequence object loaded via Python-R reticulate interface function ts_load (internally represented Python object tskit.trees.TreeSequence). Optionally, depending value arguments load = run =, nothing character vector, respectively.","code":""},{"path":"https://www.slendr.net/reference/slim.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Run a slendr model in SLiM — slim","text":"","code":"check_dependencies(python = TRUE, slim = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # afr and eur objects would normally be created before slendr model compilation, # but here we take them out of the model object already compiled for this # example (in a standard slendr simulation pipeline, this wouldn't be necessary) afr <- model$populations[[\"AFR\"]] eur <- model$populations[[\"EUR\"]] chimp <- model$populations[[\"CH\"]] # schedule the sampling of a couple of ancient and present-day individuals # given model at 20 ky, 10 ky, 5ky ago and at present-day (time 0) modern_samples <- schedule_sampling(model, times = 0, list(afr, 5), list(eur, 5), list(chimp, 1)) ancient_samples <- schedule_sampling(model, times = c(30000, 20000, 10000), list(eur, 1)) # sampling schedules are just data frames and can be merged easily samples <- rbind(modern_samples, ancient_samples) # run a simulation using the SLiM back end from a compiled slendr model object and return # a tree-sequence output ts <- slim(model, sequence_length = 1e5, recombination_rate = 0, samples = samples) # automatic loading of a simulated output can be prevented by `load = FALSE`, which can be # useful when a custom path to a tree-sequence output is given for later downstream analyses output_file <- tempfile(fileext = \".trees\") slim(model, sequence_length = 1e5, recombination_rate = 0, samples = samples, output = output_file, load = FALSE) # ... at a later stage: ts <- ts_load(output_file, model) ts #> ╔═══════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════╣ #> ║Trees │ 1║ #> ╟───────────────┼───────╢ #> ║Sequence Length│ 100000║ #> ╟───────────────┼───────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼───────╢ #> ║Sample Nodes │ 10046║ #> ╟───────────────┼───────╢ #> ║Total Size │2.6 MiB║ #> ╚═══════════════╧═══════╝ #> ╔═══════════╤═════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪═════╪═════════╪════════════╣ #> ║Edges │18361│573.8 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Individuals│12858│ 1.2 MiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Nodes │18362│682.1 KiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Populations│ 4│ 2.5 KiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Provenances│ 1│ 34.7 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧═════╧═════════╧════════════╝ #>"},{"path":"https://www.slendr.net/reference/subtract.html","id":null,"dir":"Reference","previous_headings":"","what":"Generate the difference between two slendr objects — subtract","title":"Generate the difference between two slendr objects — subtract","text":"Generate difference two slendr objects","code":""},{"path":"https://www.slendr.net/reference/subtract.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Generate the difference between two slendr objects — subtract","text":"","code":"subtract(x, y, name = NULL)"},{"path":"https://www.slendr.net/reference/subtract.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Generate the difference between two slendr objects — subtract","text":"x Object class slendr y Object class slendr name Optional name resulting geographic region. missing, name constructed function arguments.","code":""},{"path":"https://www.slendr.net/reference/subtract.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Generate the difference between two slendr objects — subtract","text":"Object class slendr_region encodes standard spatial object class sf several additional attributes (importantly corresponding slendr_map object, applicable).","code":""},{"path":"https://www.slendr.net/reference/summary.slendr_nodes.html","id":null,"dir":"Reference","previous_headings":"","what":"Summarise the contents of a ts_nodes result — summary.slendr_nodes","title":"Summarise the contents of a ts_nodes result — summary.slendr_nodes","text":"Summarise contents ts_nodes result","code":""},{"path":"https://www.slendr.net/reference/summary.slendr_nodes.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Summarise the contents of a ts_nodes result — summary.slendr_nodes","text":"","code":"# S3 method for slendr_nodes summary(object, ...)"},{"path":"https://www.slendr.net/reference/summary.slendr_nodes.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Summarise the contents of a ts_nodes result — summary.slendr_nodes","text":"object Data frame produced function ts_nodes ... Additional formal arguments summary method (unused )","code":""},{"path":"https://www.slendr.net/reference/summary.slendr_nodes.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Summarise the contents of a ts_nodes result — summary.slendr_nodes","text":"Used output terminal","code":""},{"path":"https://www.slendr.net/reference/ts_afs.html","id":null,"dir":"Reference","previous_headings":"","what":"Compute the allele frequency spectrum (AFS) — ts_afs","title":"Compute the allele frequency spectrum (AFS) — ts_afs","text":"function computes AFS respect given set individuals nodes.","code":""},{"path":"https://www.slendr.net/reference/ts_afs.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Compute the allele frequency spectrum (AFS) — ts_afs","text":"","code":"ts_afs( ts, sample_sets = NULL, mode = c(\"site\", \"branch\", \"node\"), windows = NULL, span_normalise = FALSE, polarised = TRUE )"},{"path":"https://www.slendr.net/reference/ts_afs.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Compute the allele frequency spectrum (AFS) — ts_afs","text":"ts Tree sequence object class slendr_ts sample_sets list (optionally named list) character vectors individual names (one vector per set). NULL, allele frequency spectrum individuals tree sequence computed. mode mode calculation (\"sites\" \"branch\") windows Coordinates breakpoints windows. first coordinate (0) last coordinate (equal ts$sequence_length) added automatically) span_normalise Argument passed tskit's allele_frequency_spectrum method polarised TRUE (default) allele frequency spectrum folded (.e. counts assume knowledge allele ancestral, derived, known simulation)","code":""},{"path":"https://www.slendr.net/reference/ts_afs.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Compute the allele frequency spectrum (AFS) — ts_afs","text":"Allele frequency spectrum values given sample set. Note contents first last elements AFS might surprise . Read links description detail tskit handles things.","code":""},{"path":"https://www.slendr.net/reference/ts_afs.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Compute the allele frequency spectrum (AFS) — ts_afs","text":"information format result dimensions, particular interpretation first last element AFS (complete = TRUE), please see tskit manual https://tskit.dev/tskit/docs/stable/python-api.html example section dedicated AFS https://tskit.dev/tutorials/analysing_tree_sequences.html#allele-frequency-spectra.","code":""},{"path":"https://www.slendr.net/reference/ts_afs.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Compute the allele frequency spectrum (AFS) — ts_afs","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) %>% ts_mutate(mutation_rate = 1e-8, random_seed = 42) samples <- ts_samples(ts) %>% .[.$pop %in% c(\"AFR\", \"EUR\"), ] # compute AFS for the given set of individuals ts_afs(ts, sample_sets = list(samples$name)) #> [1] 1080 73 21 8 1 4 0 0 0 0 11 0 0 0 0 #> [16] 1 0 3 5 10 935"},{"path":"https://www.slendr.net/reference/ts_ancestors.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract (spatio-)temporal ancestral history for given nodes/individuals — ts_ancestors","title":"Extract (spatio-)temporal ancestral history for given nodes/individuals — ts_ancestors","text":"Extract (spatio-)temporal ancestral history given nodes/individuals","code":""},{"path":"https://www.slendr.net/reference/ts_ancestors.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract (spatio-)temporal ancestral history for given nodes/individuals — ts_ancestors","text":"","code":"ts_ancestors(ts, x, verbose = FALSE, complete = TRUE)"},{"path":"https://www.slendr.net/reference/ts_ancestors.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract (spatio-)temporal ancestral history for given nodes/individuals — ts_ancestors","text":"ts Tree sequence object class slendr_ts x Either individual name integer node ID verbose Report progress ancestry path generation? complete every individual tree sequence need complete metadata recorded? TRUE, individuals/nodes complete metadata included reconstruction ancestral relationships. instance, nodes added coalescent recapitation phase included spatial information associated .","code":""},{"path":"https://www.slendr.net/reference/ts_ancestors.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract (spatio-)temporal ancestral history for given nodes/individuals — ts_ancestors","text":"table ancestral nodes given tree-sequence node way root tree sequence","code":""},{"path":"https://www.slendr.net/reference/ts_ancestors.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract (spatio-)temporal ancestral history for given nodes/individuals — ts_ancestors","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # find the complete ancestry information for a given individual ts_ancestors(ts, \"EUR_1\", verbose = TRUE) #> Collecting ancestors of EUR_1 [1/1]... #> #> Generating data about spatial relationships of nodes... #> # A tibble: 222 × 12 #> name pop node_id level child_id parent_id child_time parent_time child_pop #> #> 1 EUR_1 EUR 16 1 16 33 0 500 EUR #> 2 EUR_1 EUR 16 2 33 43 500 21830 EUR #> 3 EUR_1 EUR 16 2 33 47 500 28730 EUR #> 4 EUR_1 EUR 16 2 33 49 500 30380 EUR #> 5 EUR_1 EUR 16 2 33 51 500 35360 EUR #> 6 EUR_1 EUR 16 2 33 54 500 39380 EUR #> 7 EUR_1 EUR 16 2 33 57 500 41510 EUR #> 8 EUR_1 EUR 16 2 33 58 500 44810 EUR #> 9 EUR_1 EUR 16 2 33 59 500 46040 EUR #> 10 EUR_1 EUR 16 2 33 62 500 51680 EUR #> # ℹ 212 more rows #> # ℹ 3 more variables: parent_pop , left_pos , right_pos "},{"path":"https://www.slendr.net/reference/ts_coalesced.html","id":null,"dir":"Reference","previous_headings":"","what":"Check that all trees in the tree sequence are fully coalesced — ts_coalesced","title":"Check that all trees in the tree sequence are fully coalesced — ts_coalesced","text":"Check trees tree sequence fully coalesced","code":""},{"path":"https://www.slendr.net/reference/ts_coalesced.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Check that all trees in the tree sequence are fully coalesced — ts_coalesced","text":"","code":"ts_coalesced(ts, return_failed = FALSE)"},{"path":"https://www.slendr.net/reference/ts_coalesced.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Check that all trees in the tree sequence are fully coalesced — ts_coalesced","text":"ts Tree sequence object class slendr_ts return_failed Report back trees failed coalescence check?","code":""},{"path":"https://www.slendr.net/reference/ts_coalesced.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Check that all trees in the tree sequence are fully coalesced — ts_coalesced","text":"TRUE FALSE value return_failed = FALSE, otherwise vector (tskit Python 0-based) indices trees failed coalescence test","code":""},{"path":"https://www.slendr.net/reference/ts_coalesced.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Check that all trees in the tree sequence are fully coalesced — ts_coalesced","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) ts_coalesced(ts) # is the tree sequence fully coalesced? (TRUE or FALSE) #> [1] TRUE # returns a vector of tree sequence segments which are not coalesced not_coalesced <- ts_coalesced(ts, return_failed = TRUE)"},{"path":"https://www.slendr.net/reference/ts_descendants.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract all descendants of a given tree-sequence node — ts_descendants","title":"Extract all descendants of a given tree-sequence node — ts_descendants","text":"Extract descendants given tree-sequence node","code":""},{"path":"https://www.slendr.net/reference/ts_descendants.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract all descendants of a given tree-sequence node — ts_descendants","text":"","code":"ts_descendants(ts, x, verbose = FALSE, complete = TRUE)"},{"path":"https://www.slendr.net/reference/ts_descendants.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract all descendants of a given tree-sequence node — ts_descendants","text":"ts Tree sequence object class slendr_ts x integer node ID ancestral node verbose Report progress ancestry path generation? complete every individual tree sequence need complete metadata recorded? TRUE, individuals/nodes complete metadata included reconstruction ancestral relationships. instance, nodes added coalescent recapitation phase included spatial information associated .","code":""},{"path":"https://www.slendr.net/reference/ts_descendants.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract all descendants of a given tree-sequence node — ts_descendants","text":"table descendant nodes given tree-sequence node way leaves tree sequence","code":""},{"path":"https://www.slendr.net/reference/ts_descendants.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract all descendants of a given tree-sequence node — ts_descendants","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # find the complete descendancy information for a given individual ts_descendants(ts, x = 62, verbose = TRUE) #> #> Generating data about spatial relationships of nodes... #> # A tibble: 4 × 12 #> name pop node_id level child_id parent_id child_time parent_time child_pop #> #> 1 EUR_4 EUR 62 1 22 62 0 51680 EUR #> 2 NA EUR 62 1 33 62 500 51680 EUR #> 3 EUR_1 EUR 62 2 16 33 0 500 EUR #> 4 EUR_2 EUR 62 2 18 33 0 500 EUR #> # ℹ 3 more variables: parent_pop , left_pos , right_pos "},{"path":"https://www.slendr.net/reference/ts_divergence.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate pairwise divergence between sets of individuals — ts_divergence","title":"Calculate pairwise divergence between sets of individuals — ts_divergence","text":"Calculate pairwise divergence sets individuals","code":""},{"path":"https://www.slendr.net/reference/ts_divergence.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate pairwise divergence between sets of individuals — ts_divergence","text":"","code":"ts_divergence( ts, sample_sets, mode = c(\"site\", \"branch\", \"node\"), windows = NULL, span_normalise = TRUE )"},{"path":"https://www.slendr.net/reference/ts_divergence.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate pairwise divergence between sets of individuals — ts_divergence","text":"ts Tree sequence object class slendr_ts sample_sets list (optionally named list) character vectors individual names (one vector per set) mode mode calculation (\"sites\" \"branch\") windows Coordinates breakpoints windows. first coordinate (0) last coordinate (equal ts$sequence_length) specified added automatically. span_normalise Divide result span window? Default TRUE, see tskit documentation detail.","code":""},{"path":"https://www.slendr.net/reference/ts_divergence.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate pairwise divergence between sets of individuals — ts_divergence","text":"pairwise calculation, either single divergence value vector divergence values (one window)","code":""},{"path":"https://www.slendr.net/reference/ts_divergence.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate pairwise divergence between sets of individuals — ts_divergence","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) %>% ts_mutate(mutation_rate = 1e-8, random_seed = 42) # collect sampled individuals from all populations in a list sample_sets <- ts_samples(ts) %>% split(., .$pop) %>% lapply(function(pop) pop$name) # compute the divergence between individuals from each sample set (list of # individual names generated in the previous step) ts_divergence(ts, sample_sets) %>% .[order(.$divergence), ] #> # A tibble: 6 × 3 #> x y divergence #> #> 1 AFR EUR 0.0000602 #> 2 EUR NEA 0.000289 #> 3 AFR NEA 0.000305 #> 4 CH NEA 0.00397 #> 5 AFR CH 0.00398 #> 6 CH EUR 0.00398"},{"path":"https://www.slendr.net/reference/ts_diversity.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate diversity in given sets of individuals — ts_diversity","title":"Calculate diversity in given sets of individuals — ts_diversity","text":"Calculate diversity given sets individuals","code":""},{"path":"https://www.slendr.net/reference/ts_diversity.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate diversity in given sets of individuals — ts_diversity","text":"","code":"ts_diversity( ts, sample_sets, mode = c(\"site\", \"branch\", \"node\"), windows = NULL, span_normalise = TRUE )"},{"path":"https://www.slendr.net/reference/ts_diversity.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate diversity in given sets of individuals — ts_diversity","text":"ts Tree sequence object class slendr_ts sample_sets list (optionally named list) character vectors individual names (one vector per set). simple vector provided, interpreted .list(sample_sets), meaning given statistic calculated individual separately. mode mode calculation (\"sites\" \"branch\") windows Coordinates breakpoints windows. first coordinate (0) last coordinate (equal ts$sequence_length) added automatically) span_normalise Divide result span window? Default TRUE, see tskit documentation detail.","code":""},{"path":"https://www.slendr.net/reference/ts_diversity.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate diversity in given sets of individuals — ts_diversity","text":"set individuals either single diversity value vector diversity values (one window)","code":""},{"path":"https://www.slendr.net/reference/ts_diversity.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate diversity in given sets of individuals — ts_diversity","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) %>% ts_mutate(mutation_rate = 1e-8, random_seed = 42) # collect sampled individuals from all populations in a list sample_sets <- ts_samples(ts) %>% split(., .$pop) %>% lapply(function(pop) pop$name) # compute diversity in each population based on sample sets extracted # in the previous step ts_diversity(ts, sample_sets) %>% .[order(.$diversity), ] #> # A tibble: 4 × 2 #> set diversity #> #> 1 CH 0 #> 2 AFR 0.0000004 #> 3 NEA 0.00000933 #> 4 EUR 0.0000661"},{"path":"https://www.slendr.net/reference/ts_draw.html","id":null,"dir":"Reference","previous_headings":"","what":"Plot a graphical representation of a single tree — ts_draw","title":"Plot a graphical representation of a single tree — ts_draw","text":"function first obtains SVG representation tree calling draw_svg method tskit renders bitmap image R. many optional keyword arguments draw_svg method can provided automatically passed method behind scenes.","code":""},{"path":"https://www.slendr.net/reference/ts_draw.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Plot a graphical representation of a single tree — ts_draw","text":"","code":"ts_draw( x, width = 1000, height = 1000, labels = FALSE, sampled_only = TRUE, title = NULL, ... )"},{"path":"https://www.slendr.net/reference/ts_draw.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Plot a graphical representation of a single tree — ts_draw","text":"x single tree extracted ts_tree width, height Pixel dimensions rendered bitmap labels Label node individual name? sampled_only individuals explicitly sampled simplification labeled? relevant situations sampled individuals can among ancestral nodes. title Optional title figure ... Keyword arguments tskit draw_svg function.","code":""},{"path":"https://www.slendr.net/reference/ts_draw.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Plot a graphical representation of a single tree — ts_draw","text":"return value, called side effects","code":""},{"path":"https://www.slendr.net/reference/ts_draw.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Plot a graphical representation of a single tree — ts_draw","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # extract the first tree in the tree sequence and draw it tree <- ts_tree(ts, i = 1) # ts_draw accepts various optional arguments of tskit.Tree.draw_svg ts_draw(tree, time_scale = \"rank\")"},{"path":"https://www.slendr.net/reference/ts_edges.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract spatio-temporal edge annotation table from a given tree or tree\nsequence — ts_edges","title":"Extract spatio-temporal edge annotation table from a given tree or tree\nsequence — ts_edges","text":"Extract spatio-temporal edge annotation table given tree tree sequence","code":""},{"path":"https://www.slendr.net/reference/ts_edges.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract spatio-temporal edge annotation table from a given tree or tree\nsequence — ts_edges","text":"","code":"ts_edges(x)"},{"path":"https://www.slendr.net/reference/ts_edges.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract spatio-temporal edge annotation table from a given tree or tree\nsequence — ts_edges","text":"x Tree object generated ts_phylo slendr tree sequence object produced ts_load, ts_recapitate, ts_simplify, ts_mutate","code":""},{"path":"https://www.slendr.net/reference/ts_edges.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract spatio-temporal edge annotation table from a given tree or tree\nsequence — ts_edges","text":"Data frame sf type containing times nodes start-end coordinates edges across space","code":""},{"path":"https://www.slendr.net/reference/ts_edges.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract spatio-temporal edge annotation table from a given tree or tree\nsequence — ts_edges","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # extract an annotated table with (spatio-)temporal edge information ts_edges(ts) #> # A tibble: 298 × 6 #> child_node_id parent_node_id child_time parent_time child_pop parent_pop #> #> 1 0 74 70000 70040 NEA NEA #> 2 1 74 70000 70040 NEA NEA #> 3 2 55 40000 40220 NEA NEA #> 4 3 55 40000 40220 NEA NEA #> 5 4 34 0 740 AFR AFR #> 6 5 28 0 80 AFR AFR #> 7 6 26 0 20 AFR AFR #> 8 7 27 0 80 AFR AFR #> 9 8 27 0 80 AFR AFR #> 10 9 36 0 1160 AFR AFR #> # ℹ 288 more rows"},{"path":"https://www.slendr.net/reference/ts_eigenstrat.html","id":null,"dir":"Reference","previous_headings":"","what":"Convert genotypes to the EIGENSTRAT file format — ts_eigenstrat","title":"Convert genotypes to the EIGENSTRAT file format — ts_eigenstrat","text":"EIGENSTRAT data produced function can used admixr R package (https://bodkan.net/admixr/).","code":""},{"path":"https://www.slendr.net/reference/ts_eigenstrat.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Convert genotypes to the EIGENSTRAT file format — ts_eigenstrat","text":"","code":"ts_eigenstrat(ts, prefix, chrom = \"chr1\", outgroup = NULL)"},{"path":"https://www.slendr.net/reference/ts_eigenstrat.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Convert genotypes to the EIGENSTRAT file format — ts_eigenstrat","text":"ts Tree sequence object class slendr_ts prefix EIGENSTRAT trio prefix chrom name chromosome EIGENSTRAT snp file (default \"chr1\") outgroup formal, artificial outgroup added? NULL (default), outgroup added. non-NULL character name serve name outgroup ind file.","code":""},{"path":"https://www.slendr.net/reference/ts_eigenstrat.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Convert genotypes to the EIGENSTRAT file format — ts_eigenstrat","text":"Object class EIGENSTRAT created admixr package","code":""},{"path":"https://www.slendr.net/reference/ts_eigenstrat.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Convert genotypes to the EIGENSTRAT file format — ts_eigenstrat","text":"case outgroup formally specified slendr model generated tree sequence data, possible artificially create outgroup sample name specified outgroup argument, carry ancestral alleles (.e. value \"2\" geno file position snp file).","code":""},{"path":"https://www.slendr.net/reference/ts_f4ratio.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate the f2, f3, f4, and f4-ratio statistics — ts_f2","title":"Calculate the f2, f3, f4, and f4-ratio statistics — ts_f2","text":"functions present R interface corresponding f-statistics methods tskit.","code":""},{"path":"https://www.slendr.net/reference/ts_f4ratio.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate the f2, f3, f4, and f4-ratio statistics — ts_f2","text":"","code":"ts_f2( ts, A, B, mode = c(\"site\", \"branch\", \"node\"), span_normalise = TRUE, windows = NULL ) ts_f3( ts, A, B, C, mode = c(\"site\", \"branch\", \"node\"), span_normalise = TRUE, windows = NULL ) ts_f4( ts, W, X, Y, Z, mode = c(\"site\", \"branch\", \"node\"), span_normalise = TRUE, windows = NULL ) ts_f4ratio( ts, X, A, B, C, O, mode = c(\"site\", \"branch\"), span_normalise = TRUE )"},{"path":"https://www.slendr.net/reference/ts_f4ratio.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate the f2, f3, f4, and f4-ratio statistics — ts_f2","text":"ts Tree sequence object class slendr_ts mode mode calculation (\"sites\" \"branch\") span_normalise Divide result span window? Default TRUE, see tskit documentation detail. windows Coordinates breakpoints windows. first coordinate (0) last coordinate (equal ts$sequence_length) specified added automatically. W, X, Y, Z, , B, C, O Character vectors individual names (largely following nomenclature Patterson 2021, see crucial differences tskit ADMIXTOOLS Details)","code":""},{"path":"https://www.slendr.net/reference/ts_f4ratio.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate the f2, f3, f4, and f4-ratio statistics — ts_f2","text":"Data frame statistics calculated given sets individuals","code":""},{"path":"https://www.slendr.net/reference/ts_f4ratio.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Calculate the f2, f3, f4, and f4-ratio statistics — ts_f2","text":"Note order populations f3 statistic implemented tskit (https://tskit.dev/tskit/docs/stable/python-api.html#tskit.TreeSequence.f3) different might expect ADMIXTOOLS, defined Patterson 2012 (see https://academic.oup.com/genetics/article/192/3/1065/5935193 heading \"three-population test introduction f-statistics\", well ADMIXTOOLS documentation https://github.com/DReichLab/AdmixTools/blob/master/README.3PopTest#L5). Specifically, widely used notation introduced Patterson assumes population triplet f3(C; , B), C \"focal\" sample (.e., either outgroup sample tested admixture). contrast, tskit implements f3(; B, C), \"focal sample\" . Although likely confuse many ADMIXTOOLS users, slendr much choice , ts_*() functions designed broadly compatible raw tskit methods.","code":""},{"path":"https://www.slendr.net/reference/ts_f4ratio.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate the f2, f3, f4, and f4-ratio statistics — ts_f2","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk and add mutations to it ts <- ts_load(slendr_ts, model) %>% ts_mutate(mutation_rate = 1e-8, random_seed = 42) # calculate f2 for two individuals in a previously loaded tree sequence ts_f2(ts, A = \"AFR_1\", B = \"EUR_1\") #> # A tibble: 1 × 3 #> A B f2 #> #> 1 AFR_1 EUR_1 0.000024 # calculate f2 for two sets of individuals ts_f2(ts, A = c(\"AFR_1\", \"AFR_2\"), B = c(\"EUR_1\", \"EUR_3\")) #> # A tibble: 1 × 3 #> A B f2 #> #> 1 AFR_1+AFR_2 EUR_1+EUR_3 0.0000247 # calculate f3 for two individuals in a previously loaded tree sequence ts_f3(ts, A = \"EUR_1\", B = \"AFR_1\", C = \"NEA_1\") #> # A tibble: 1 × 4 #> A B C f3 #> #> 1 EUR_1 AFR_1 NEA_1 -0.000012 # calculate f3 for two sets of individuals ts_f3(ts, A = c(\"AFR_1\", \"AFR_2\", \"EUR_1\", \"EUR_2\"), B = c(\"NEA_1\", \"NEA_2\"), C = \"CH_1\") #> # A tibble: 1 × 4 #> A B C f3 #> #> 1 AFR_1+AFR_2+EUR_1+EUR_2 NEA_1+NEA_2 CH_1 0.000126 # calculate f4 for single individuals ts_f4(ts, W = \"EUR_1\", X = \"AFR_1\", Y = \"NEA_1\", Z = \"CH_1\") #> # A tibble: 1 × 5 #> W X Y Z f4 #> #> 1 EUR_1 AFR_1 NEA_1 CH_1 0.000009 # calculate f4 for sets of individuals ts_f4(ts, W = c(\"EUR_1\", \"EUR_2\"), X = c(\"AFR_1\", \"AFR_2\"), Y = \"NEA_1\", Z = \"CH_1\") #> # A tibble: 1 × 5 #> W X Y Z f4 #> #> 1 EUR_1+EUR_2 AFR_1+AFR_2 NEA_1 CH_1 0.000018 # calculate f4-ratio for a given set of target individuals X ts_f4ratio(ts, X = c(\"EUR_1\", \"EUR_2\", \"EUR_4\", \"EUR_5\"), A = \"NEA_1\", B = \"NEA_2\", C = \"AFR_1\", O = \"CH_1\") #> # A tibble: 4 × 6 #> X A B C O alpha #> #> 1 EUR_1 NEA_1 NEA_2 AFR_1 CH_1 0.0486 #> 2 EUR_2 NEA_1 NEA_2 AFR_1 CH_1 0.181 #> 3 EUR_4 NEA_1 NEA_2 AFR_1 CH_1 0.0417 #> 4 EUR_5 NEA_1 NEA_2 AFR_1 CH_1 0"},{"path":"https://www.slendr.net/reference/ts_fst.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate pairwise statistics between sets of individuals — ts_fst","title":"Calculate pairwise statistics between sets of individuals — ts_fst","text":"discussion difference \"site\", \"branch\", \"node\" options mode argument, please see tskit documentation https://tskit.dev/tskit/docs/stable/stats.html#sec-stats-mode.","code":""},{"path":"https://www.slendr.net/reference/ts_fst.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate pairwise statistics between sets of individuals — ts_fst","text":"","code":"ts_fst( ts, sample_sets, mode = c(\"site\", \"branch\", \"node\"), windows = NULL, span_normalise = TRUE )"},{"path":"https://www.slendr.net/reference/ts_fst.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate pairwise statistics between sets of individuals — ts_fst","text":"ts Tree sequence object class slendr_ts sample_sets list (optionally named list) character vectors individual names (one vector per set) mode mode calculation (\"sites\" \"branch\") windows Coordinates breakpoints windows. first coordinate (0) last coordinate (equal ts$sequence_length) specified added automatically. span_normalise Divide result span window? Default TRUE, see tskit documentation detail.","code":""},{"path":"https://www.slendr.net/reference/ts_fst.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate pairwise statistics between sets of individuals — ts_fst","text":"pairwise calculation, either single Fst value vector Fst values (one window)","code":""},{"path":"https://www.slendr.net/reference/ts_fst.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate pairwise statistics between sets of individuals — ts_fst","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) %>% ts_mutate(mutation_rate = 1e-8, random_seed = 42) # compute F_st between two sets of individuals in a given tree sequence ts ts_fst(ts, sample_sets = list(afr = c(\"AFR_1\", \"AFR_2\", \"AFR_3\"), eur = c(\"EUR_1\", \"EUR_2\"))) #> # A tibble: 1 × 3 #> x y Fst #> #> 1 afr eur 0.303"},{"path":"https://www.slendr.net/reference/ts_genotypes.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract genotype table from the tree sequence — ts_genotypes","title":"Extract genotype table from the tree sequence — ts_genotypes","text":"Extract genotype table tree sequence","code":""},{"path":"https://www.slendr.net/reference/ts_genotypes.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract genotype table from the tree sequence — ts_genotypes","text":"","code":"ts_genotypes(ts)"},{"path":"https://www.slendr.net/reference/ts_genotypes.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract genotype table from the tree sequence — ts_genotypes","text":"ts Tree sequence object class slendr_ts","code":""},{"path":"https://www.slendr.net/reference/ts_genotypes.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract genotype table from the tree sequence — ts_genotypes","text":"Data frame object class tibble containing genotypes simulated individuals columns","code":""},{"path":"https://www.slendr.net/reference/ts_genotypes.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract genotype table from the tree sequence — ts_genotypes","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk, recapitate it, simplify it, and mutate it ts <- ts_load(slendr_ts, model) %>% ts_recapitate(Ne = 10000, recombination_rate = 1e-8) %>% ts_simplify() %>% ts_mutate(mutation_rate = 1e-8) # extract the genotype matrix (this could take a long time consume lots # of memory!) gts <- ts_genotypes(ts) #> 3 multiallelic sites (0.138% out of 2173 total) detected and removed"},{"path":"https://www.slendr.net/reference/ts_ibd.html","id":null,"dir":"Reference","previous_headings":"","what":"Collect Identity-by-Descent (IBD) segments (EXPERIMENTAL) — ts_ibd","title":"Collect Identity-by-Descent (IBD) segments (EXPERIMENTAL) — ts_ibd","text":"function iterates tree sequence returns IBD tracts pairs individuals nodes","code":""},{"path":"https://www.slendr.net/reference/ts_ibd.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Collect Identity-by-Descent (IBD) segments (EXPERIMENTAL) — ts_ibd","text":"","code":"ts_ibd( ts, coordinates = FALSE, within = NULL, between = NULL, squash = FALSE, minimum_length = NULL, maximum_time = NULL, sf = TRUE )"},{"path":"https://www.slendr.net/reference/ts_ibd.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Collect Identity-by-Descent (IBD) segments (EXPERIMENTAL) — ts_ibd","text":"ts Tree sequence object class slendr_ts coordinates coordinates detected IBD tracts reported? FALSE (default), total length shared IBD segments numbers reported. TRUE, coordinates segment returned (note can massive impact memory usage). See details information. within character vector individual names integer vector node IDs indicating set nodes within look IBD segments. list lists character vectors individual names integer vectors node IDs, indicating set nodes look shared IBD segments. squash adjacent IBD segments pairs nodes squashed differ 'genealogical paths' MRCA? Default FALSE. context, see https://github.com/tskit-dev/tskit/issues/2459. option EXPERIMENTAL! minimum_length Minimum length IBD segment return results. useful reducing total amount IBD returned (see Details). maximum_time Oldest MRCA node considered IBD ancestor return IBD segment results. useful reducing total amount IBD returned. sf IBD segments spatial tree sequence analyzed, returned table spatial sf object? Default TRUE.","code":""},{"path":"https://www.slendr.net/reference/ts_ibd.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Collect Identity-by-Descent (IBD) segments (EXPERIMENTAL) — ts_ibd","text":"data frame IBD results (either coordinates IBD segment shared pair nodes, summary statistics total IBD sharing pair)","code":""},{"path":"https://www.slendr.net/reference/ts_ibd.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Collect Identity-by-Descent (IBD) segments (EXPERIMENTAL) — ts_ibd","text":"function considered experimental. full control IBD segment detection tree-sequence data, users can (perhaps, time , ) rely tskit method ibd_segments (see https://tskit.dev/tskit/docs/stable/python-api.html#tskit.TreeSequence.ibd_segments). Iternally, function leverages tskit TreeSequence method ibd_segments. However, note ts_ibd function always returns data frame IBD tracts, provide option iterate individual IBD segments shown official tskit documentation https://tskit.dev/tskit/docs/stable/ibd.html. general, R handles heavy iteration poorly, function attempt serve full wrapper ibd_segments. Unfortunately, distinction \"squashed IBD\" (many consider expected definition IBD) tskit’s IBD defined via distinct genealogical paths (see https://github.com/tskit-dev/tskit/issues/2459 discussion topic), makes meaning filtering parameter ibd_segments() method tskit minimum_length somewhat unintuitive. moment, function argument filters IBD segments tskit level, level squashed IBD segments!","code":""},{"path":"https://www.slendr.net/reference/ts_ibd.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Collect Identity-by-Descent (IBD) segments (EXPERIMENTAL) — ts_ibd","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # find IBD segments between specified Neanderthals and Europeans ts_ibd( ts, coordinates = TRUE, between = list(c(\"NEA_1\", \"NEA_2\"), c(\"EUR_1\", \"EUR_2\")), minimum_length = 40000 ) #> # A tibble: 34 × 13 #> node1 node2 length mrca node1_time node2_time tmrca left right name1 #> #> 1 0 16 52762 83 70000 0 20001 228046 280808 NEA_1 #> 2 0 16 45006 83 70000 0 20001 449167 494173 NEA_1 #> 3 0 17 52762 83 70000 0 20001 228046 280808 NEA_1 #> 4 0 18 52762 83 70000 0 20001 228046 280808 NEA_1 #> 5 0 18 45006 83 70000 0 20001 449167 494173 NEA_1 #> 6 0 19 57765 83 70000 0 20001 47447 105212 NEA_1 #> 7 0 19 47935 83 70000 0 20001 105212 153147 NEA_1 #> 8 0 19 46028 83 70000 0 20001 178539 224567 NEA_1 #> 9 0 19 58054 79 70000 0 2340 227185 285239 NEA_1 #> 10 1 16 52762 83 70000 0 20001 228046 280808 NEA_1 #> # ℹ 24 more rows #> # ℹ 3 more variables: name2 , pop1 , pop2 "},{"path":"https://www.slendr.net/reference/ts_load.html","id":null,"dir":"Reference","previous_headings":"","what":"Load a tree sequence file produced by a given model — ts_load","title":"Load a tree sequence file produced by a given model — ts_load","text":"function loads tree sequence file simulated given slendr model. Optionally, tree sequence can recapitated simplified.","code":""},{"path":"https://www.slendr.net/reference/ts_load.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Load a tree sequence file produced by a given model — ts_load","text":"","code":"ts_load(file, model = NULL)"},{"path":"https://www.slendr.net/reference/ts_load.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Load a tree sequence file produced by a given model — ts_load","text":"file path tree-sequence file (either originating slendr model standard non-slendr tree sequence). model Optional slendr_model object produced tree-sequence file. Used adding various annotation data metadata standard tskit tree-sequence object.","code":""},{"path":"https://www.slendr.net/reference/ts_load.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Load a tree sequence file produced by a given model — ts_load","text":"Tree-sequence object class slendr_ts, serves interface point Python module tskit using slendr functions ts_ prefix.","code":""},{"path":"https://www.slendr.net/reference/ts_load.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Load a tree sequence file produced by a given model — ts_load","text":"loading, recapitation simplification performed using Python module pyslim serves link tree sequences generated SLiM tskit module manipulation tree sequence data. steps modelled official pyslim tutorial documentation available : https://tskit.dev/pyslim/docs/latest/tutorial.html. recapitation simplification steps can also performed individually using functions ts_recapitate ts_simplify.","code":""},{"path":[]},{"path":"https://www.slendr.net/reference/ts_load.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Load a tree sequence file produced by a given model — ts_load","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load tree sequence generated by a given model ts <- ts_load(slendr_ts, model) # even tree sequences generated by non-slendr models can be msprime_ts <- system.file(\"extdata/models/msprime.trees\", package = \"slendr\") ts <- ts_load(msprime_ts) # load tree sequence and immediately simplify it only to sampled individuals # (note that the example tree sequence is already simplified so this operation # does not do anything in this case) ts <- ts_load(slendr_ts, model = model) %>% ts_simplify(keep_input_roots = TRUE) # load tree sequence and simplify it to a subset of sampled individuals ts_small <- ts_simplify(ts, simplify_to = c(\"CH_1\", \"NEA_1\", \"NEA_2\", \"AFR_1\", \"AFR_2\", \"EUR_1\", \"EUR_2\")) # load tree sequence, recapitate it and simplify it ts <- ts_load(slendr_ts, model) %>% ts_recapitate(recombination_rate = 1e-8, Ne = 10000, random_seed = 42) %>% ts_simplify() # load tree sequence, recapitate it, simplify it and overlay neutral mutations ts <- ts_load(slendr_ts, model) %>% ts_recapitate(recombination_rate = 1e-8, Ne = 10000, random_seed = 42) %>% ts_simplify() %>% ts_mutate(mutation_rate = 1e-8) ts #> ╔═════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═════════╣ #> ║Trees │ 70║ #> ╟───────────────┼─────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼─────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼─────────╢ #> ║Sample Nodes │ 26║ #> ╟───────────────┼─────────╢ #> ║Total Size │205.3 KiB║ #> ╚═══════════════╧═════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 297│ 9.3 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 72│ 8.8 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │2206│80.9 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 85│ 3.8 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 6│ 2.7 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 6│41.0 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Sites │2201│53.8 KiB│ No║ #> ╚═══════════╧════╧════════╧════════════╝ #>"},{"path":"https://www.slendr.net/reference/ts_metadata.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract list with tree sequence metadata saved by SLiM — ts_metadata","title":"Extract list with tree sequence metadata saved by SLiM — ts_metadata","text":"Extract list tree sequence metadata saved SLiM","code":""},{"path":"https://www.slendr.net/reference/ts_metadata.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract list with tree sequence metadata saved by SLiM — ts_metadata","text":"","code":"ts_metadata(ts)"},{"path":"https://www.slendr.net/reference/ts_metadata.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract list with tree sequence metadata saved by SLiM — ts_metadata","text":"ts Tree sequence object class slendr_ts","code":""},{"path":"https://www.slendr.net/reference/ts_metadata.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract list with tree sequence metadata saved by SLiM — ts_metadata","text":"List metadata fields extracted tree-sequence object","code":""},{"path":"https://www.slendr.net/reference/ts_metadata.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract list with tree sequence metadata saved by SLiM — ts_metadata","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # extract the list of metadata information from the tree sequence ts_metadata(ts) #> $version #> [1] \"slendr_0.8.1.9000\" #> #> $description #> [1] \"\" #> #> $sampling #> # A tibble: 13 × 3 #> name time pop #> #> 1 NEA_1 70000 NEA #> 2 NEA_2 40000 NEA #> 3 AFR_1 0 AFR #> 4 AFR_2 0 AFR #> 5 AFR_3 0 AFR #> 6 AFR_4 0 AFR #> 7 AFR_5 0 AFR #> 8 CH_1 0 CH #> 9 EUR_1 0 EUR #> 10 EUR_2 0 EUR #> 11 EUR_3 0 EUR #> 12 EUR_4 0 EUR #> 13 EUR_5 0 EUR #> #> $sample_names #> [1] \"NEA_1\" \"NEA_2\" \"AFR_1\" \"AFR_2\" \"AFR_3\" \"AFR_4\" \"AFR_5\" \"CH_1\" \"EUR_1\" #> [10] \"EUR_2\" \"EUR_3\" \"EUR_4\" \"EUR_5\" #> #> $sample_ids #> NULL #> #> $map #> NULL #> #> $arguments #> $arguments$BURNIN_LENGTH #> [1] 0 #> #> $arguments$MAX_ATTEMPTS #> [1] 1 #> #> $arguments$RECOMB_RATE #> [1] 1e-08 #> #> $arguments$SEED #> [1] 314159 #> #> $arguments$SEQUENCE_LENGTH #> [1] 500000 #> #> $arguments$SIMULATION_LENGTH #> [1] 216667 #> #>"},{"path":"https://www.slendr.net/reference/ts_mutate.html","id":null,"dir":"Reference","previous_headings":"","what":"Add mutations to the given tree sequence — ts_mutate","title":"Add mutations to the given tree sequence — ts_mutate","text":"Add mutations given tree sequence","code":""},{"path":"https://www.slendr.net/reference/ts_mutate.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Add mutations to the given tree sequence — ts_mutate","text":"","code":"ts_mutate( ts, mutation_rate, random_seed = NULL, keep_existing = TRUE, mut_type = NULL )"},{"path":"https://www.slendr.net/reference/ts_mutate.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Add mutations to the given tree sequence — ts_mutate","text":"ts Tree sequence object class slendr_ts mutation_rate Mutation rate used msprime simulate mutations random_seed Random seed passed msprime's mutate method (NULL, seed generated 0 maximum integer number available) keep_existing Keep existing mutations? mut_type Assign SLiM mutation type neutral mutations? NULL (default), special mutation type used. integer number given, mutations SLiM mutation type integer identifier created.","code":""},{"path":"https://www.slendr.net/reference/ts_mutate.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Add mutations to the given tree sequence — ts_mutate","text":"Tree-sequence object class slendr_ts, serves interface point Python module tskit using slendr functions ts_ prefix.","code":""},{"path":[]},{"path":"https://www.slendr.net/reference/ts_mutate.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Add mutations to the given tree sequence — ts_mutate","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) ts <- ts_load(slendr_ts, model) ts_mutate <- ts_mutate(ts, mutation_rate = 1e-8, random_seed = 42) ts_mutate #> ╔═════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═════════╣ #> ║Trees │ 70║ #> ╟───────────────┼─────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼─────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼─────────╢ #> ║Sample Nodes │ 26║ #> ╟───────────────┼─────────╢ #> ║Total Size │204.8 KiB║ #> ╚═══════════════╧═════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 298│ 9.3 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 73│ 8.9 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │2246│82.3 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 86│ 3.9 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 5│ 2.6 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 4│38.0 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Sites │2240│54.7 KiB│ No║ #> ╚═══════════╧════╧════════╧════════════╝ #>"},{"path":"https://www.slendr.net/reference/ts_names.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract names of individuals in a tree sequence — ts_names","title":"Extract names of individuals in a tree sequence — ts_names","text":"Extract names individuals tree sequence","code":""},{"path":"https://www.slendr.net/reference/ts_names.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract names of individuals in a tree sequence — ts_names","text":"","code":"ts_names(ts, split = NULL)"},{"path":"https://www.slendr.net/reference/ts_names.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract names of individuals in a tree sequence — ts_names","text":"ts Tree sequence object class slendr_ts split sample names tree sequence split column (population time column)? Default NULL names samples returned single character vector. set \"pop\" \"time\", list character vectors returned, one vector unique \"pop\" \"time\" grouping.","code":""},{"path":"https://www.slendr.net/reference/ts_names.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract names of individuals in a tree sequence — ts_names","text":"vector character sample names. split specified, list vectors returned, one element list per population sampling time.","code":""},{"path":"https://www.slendr.net/reference/ts_nodes.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract combined annotated table of individuals and nodes — ts_nodes","title":"Extract combined annotated table of individuals and nodes — ts_nodes","text":"function combines information table individuals table nodes single data frame can used downstream analyses.","code":""},{"path":"https://www.slendr.net/reference/ts_nodes.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract combined annotated table of individuals and nodes — ts_nodes","text":"","code":"ts_nodes(x, sf = TRUE)"},{"path":"https://www.slendr.net/reference/ts_nodes.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract combined annotated table of individuals and nodes — ts_nodes","text":"x Tree sequence object class slendr_ts phylo object extracted ts_phylo sf spatial data returned sf format? FALSE, spatial geometries returned simply x y columns, instead standard POINT data type.","code":""},{"path":"https://www.slendr.net/reference/ts_nodes.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract combined annotated table of individuals and nodes — ts_nodes","text":"Data frame processed information tree sequence object. model generated data spatial, result returned spatial object class sf.","code":""},{"path":"https://www.slendr.net/reference/ts_nodes.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Extract combined annotated table of individuals and nodes — ts_nodes","text":"source data (tables individuals nodes recorded tree sequence generated SLiM) combined single data frame. model generated data spatial, coordinates nodes (pixel-based default SLiM spatial simulations occur raster), coordinates automatically converted explicit spatial object sf class unless spatial = FALSE. See https://r-spatial.github.io/sf/ extensive introduction sf package ways spatial data can processed, analysed, visualised.","code":""},{"path":[]},{"path":"https://www.slendr.net/reference/ts_nodes.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract combined annotated table of individuals and nodes — ts_nodes","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # extract an annotated table with (spatio-)temporal node information ts_nodes(ts) #> # A tibble: 86 × 12 #> name pop node_id time time_tskit sampled remembered retained alive #> #> 1 NEA_1 NEA 0 70000 2334 TRUE TRUE TRUE FALSE #> 2 NEA_1 NEA 1 70000 2334 TRUE TRUE TRUE FALSE #> 3 NEA_2 NEA 2 40000 1334 TRUE TRUE TRUE FALSE #> 4 NEA_2 NEA 3 40000 1334 TRUE TRUE TRUE FALSE #> 5 AFR_1 AFR 4 0 0 TRUE TRUE TRUE TRUE #> 6 AFR_1 AFR 5 0 0 TRUE TRUE TRUE TRUE #> 7 AFR_2 AFR 6 0 0 TRUE TRUE TRUE TRUE #> 8 AFR_2 AFR 7 0 0 TRUE TRUE TRUE TRUE #> 9 AFR_3 AFR 8 0 0 TRUE TRUE TRUE TRUE #> 10 AFR_3 AFR 9 0 0 TRUE TRUE TRUE TRUE #> # ℹ 76 more rows #> # ℹ 3 more variables: pedigree_id , pop_id , ind_id "},{"path":"https://www.slendr.net/reference/ts_phylo.html","id":null,"dir":"Reference","previous_headings":"","what":"Convert a tree in the tree sequence to an object of the class phylo — ts_phylo","title":"Convert a tree in the tree sequence to an object of the class phylo — ts_phylo","text":"Convert tree tree sequence object class phylo","code":""},{"path":"https://www.slendr.net/reference/ts_phylo.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Convert a tree in the tree sequence to an object of the class phylo — ts_phylo","text":"","code":"ts_phylo( ts, i, mode = c(\"index\", \"position\"), labels = c(\"tskit\", \"pop\"), quiet = FALSE )"},{"path":"https://www.slendr.net/reference/ts_phylo.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Convert a tree in the tree sequence to an object of the class phylo — ts_phylo","text":"ts Tree sequence object class slendr_ts Position tree tree sequence. mode = \"index\", -th tree returned (zero-based indexing tskit), mode = \"position\", tree covering -th base simulated genome returned (, tskit's indexing). mode argument interpreted? Either \"index\" -th tree sequence genealogies, \"position\" along simulated genome. labels stored node labels final phylo object? Options either population name tskit integer node ID (different thing phylo class node integer index). quiet ape's internal phylo validity test printed ?","code":""},{"path":"https://www.slendr.net/reference/ts_phylo.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Convert a tree in the tree sequence to an object of the class phylo — ts_phylo","text":"Standard phylogenetic tree object implemented R package ape","code":""},{"path":"https://www.slendr.net/reference/ts_phylo.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Convert a tree in the tree sequence to an object of the class phylo — ts_phylo","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) %>% ts_recapitate(Ne = 10000, recombination_rate = 1e-8) %>% ts_simplify() # extract the 1st tree from a given tree sequence, return ape object tree <- ts_phylo(ts, i = 1, mode = \"index\", quiet = TRUE) tree #> #> Phylogenetic tree with 26 tips and 24 internal nodes. #> #> Tip labels: #> 25 (EUR_5), 24 (EUR_5), 23 (EUR_4), 22 (EUR_4), 21 (EUR_3), 20 (EUR_3), ... #> Node labels: #> 84, 28, 27, 30, 31, 32, ... #> #> Rooted; includes branch lengths. # extract the tree at a 42th basepair in the given tree sequence tree <- ts_phylo(ts, i = 42, mode = \"position\", quiet = TRUE) # because the tree is a standard ape phylo object, we can plot it easily plot(tree, use.edge.length = FALSE) ape::nodelabels()"},{"path":"https://www.slendr.net/reference/ts_recapitate.html","id":null,"dir":"Reference","previous_headings":"","what":"Recapitate the tree sequence — ts_recapitate","title":"Recapitate the tree sequence — ts_recapitate","text":"Recapitate tree sequence","code":""},{"path":"https://www.slendr.net/reference/ts_recapitate.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Recapitate the tree sequence — ts_recapitate","text":"","code":"ts_recapitate( ts, recombination_rate, Ne = NULL, demography = NULL, random_seed = NULL )"},{"path":"https://www.slendr.net/reference/ts_recapitate.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Recapitate the tree sequence — ts_recapitate","text":"ts Tree sequence object loaded ts_load recombination_rate constant value recombination rate Ne Effective population size recapitation process demography Ancestral demography passed internally msprime.sim_ancestry() (see msprime's documentation mode detail) random_seed Random seed passed pyslim's recapitate method (NULL, seed generated 0 maximum integer number available)","code":""},{"path":"https://www.slendr.net/reference/ts_recapitate.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Recapitate the tree sequence — ts_recapitate","text":"Tree-sequence object class slendr_ts, serves interface point Python module tskit using slendr functions ts_ prefix.","code":""},{"path":[]},{"path":"https://www.slendr.net/reference/ts_recapitate.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Recapitate the tree sequence — ts_recapitate","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) ts <- ts_load(slendr_ts, model) %>% ts_recapitate(recombination_rate = 1e-8, Ne = 10000, random_seed = 42) ts #> ╔════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤════════╣ #> ║Trees │ 70║ #> ╟───────────────┼────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼────────╢ #> ║Sample Nodes │ 26║ #> ╟───────────────┼────────╢ #> ║Total Size │70.8 KiB║ #> ╚═══════════════╧════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 298│ 9.3 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 73│ 8.9 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 86│ 3.9 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 6│ 2.7 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 4│39.8 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Sites │ 0│16 Bytes│ No║ #> ╚═══════════╧════╧════════╧════════════╝ #>"},{"path":"https://www.slendr.net/reference/ts_samples.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract names and times of individuals of interest in the current tree sequence\n(either all sampled individuals or those that the user simplified to) — ts_samples","title":"Extract names and times of individuals of interest in the current tree sequence\n(either all sampled individuals or those that the user simplified to) — ts_samples","text":"Extract names times individuals interest current tree sequence (either sampled individuals user simplified )","code":""},{"path":"https://www.slendr.net/reference/ts_samples.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract names and times of individuals of interest in the current tree sequence\n(either all sampled individuals or those that the user simplified to) — ts_samples","text":"","code":"ts_samples(ts)"},{"path":"https://www.slendr.net/reference/ts_samples.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract names and times of individuals of interest in the current tree sequence\n(either all sampled individuals or those that the user simplified to) — ts_samples","text":"ts Tree sequence object class slendr_ts","code":""},{"path":"https://www.slendr.net/reference/ts_samples.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract names and times of individuals of interest in the current tree sequence\n(either all sampled individuals or those that the user simplified to) — ts_samples","text":"Table individuals scheduled sampling across space time","code":""},{"path":"https://www.slendr.net/reference/ts_samples.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract names and times of individuals of interest in the current tree sequence\n(either all sampled individuals or those that the user simplified to) — ts_samples","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # extract the table of individuals scheduled for simulation and sampling ts_samples(ts) #> # A tibble: 13 × 3 #> name time pop #> #> 1 NEA_1 70000 NEA #> 2 NEA_2 40000 NEA #> 3 AFR_1 0 AFR #> 4 AFR_2 0 AFR #> 5 AFR_3 0 AFR #> 6 AFR_4 0 AFR #> 7 AFR_5 0 AFR #> 8 CH_1 0 CH #> 9 EUR_1 0 EUR #> 10 EUR_2 0 EUR #> 11 EUR_3 0 EUR #> 12 EUR_4 0 EUR #> 13 EUR_5 0 EUR"},{"path":"https://www.slendr.net/reference/ts_save.html","id":null,"dir":"Reference","previous_headings":"","what":"Save a tree sequence to a file — ts_save","title":"Save a tree sequence to a file — ts_save","text":"Save tree sequence file","code":""},{"path":"https://www.slendr.net/reference/ts_save.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Save a tree sequence to a file — ts_save","text":"","code":"ts_save(ts, file)"},{"path":"https://www.slendr.net/reference/ts_save.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Save a tree sequence to a file — ts_save","text":"ts Tree sequence object loaded ts_load file File tree sequence saved","code":""},{"path":"https://www.slendr.net/reference/ts_save.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Save a tree sequence to a file — ts_save","text":"return value, called side effects","code":""},{"path":"https://www.slendr.net/reference/ts_save.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Save a tree sequence to a file — ts_save","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree sequence ts <- ts_load(slendr_ts, model) # save the tree-sequence object to a different location another_file <- paste(tempfile(), \".trees\") ts_save(ts, another_file)"},{"path":"https://www.slendr.net/reference/ts_segregating.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate the density of segregating sites for the given sets of individuals — ts_segregating","title":"Calculate the density of segregating sites for the given sets of individuals — ts_segregating","text":"Calculate density segregating sites given sets individuals","code":""},{"path":"https://www.slendr.net/reference/ts_segregating.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate the density of segregating sites for the given sets of individuals — ts_segregating","text":"","code":"ts_segregating( ts, sample_sets, mode = c(\"site\", \"branch\", \"node\"), windows = NULL, span_normalise = FALSE )"},{"path":"https://www.slendr.net/reference/ts_segregating.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate the density of segregating sites for the given sets of individuals — ts_segregating","text":"ts Tree sequence object class slendr_ts sample_sets list (optionally named list) character vectors individual names (one vector per set). simple vector provided, interpreted .list(sample_sets), meaning given statistic calculated individual separately. mode mode calculation (\"sites\" \"branch\") windows Coordinates breakpoints windows. first coordinate (0) last coordinate (equal ts$sequence_length) added automatically) span_normalise Divide result span window? Default TRUE, see tskit documentation detail.","code":""},{"path":"https://www.slendr.net/reference/ts_segregating.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate the density of segregating sites for the given sets of individuals — ts_segregating","text":"set individuals either single diversity value vector diversity values (one window)","code":""},{"path":"https://www.slendr.net/reference/ts_segregating.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate the density of segregating sites for the given sets of individuals — ts_segregating","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) %>% ts_mutate(mutation_rate = 1e-8, random_seed = 42) # collect sampled individuals from all populations in a list sample_sets <- ts_samples(ts) %>% split(., .$pop) %>% lapply(function(pop) pop$name) ts_segregating(ts, sample_sets) #> # A tibble: 4 × 2 #> set segsites #> #> 1 AFR 1 #> 2 CH 0 #> 3 EUR 122 #> 4 NEA 7"},{"path":"https://www.slendr.net/reference/ts_simplify.html","id":null,"dir":"Reference","previous_headings":"","what":"Simplify the tree sequence down to a given set of individuals — ts_simplify","title":"Simplify the tree sequence down to a given set of individuals — ts_simplify","text":"function convenience wrapper around simplify method implemented tskit, designed work tree sequence data simulated SLiM using slendr R package.","code":""},{"path":"https://www.slendr.net/reference/ts_simplify.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Simplify the tree sequence down to a given set of individuals — ts_simplify","text":"","code":"ts_simplify( ts, simplify_to = NULL, keep_input_roots = FALSE, keep_unary = FALSE, keep_unary_in_individuals = FALSE, filter_nodes = TRUE )"},{"path":"https://www.slendr.net/reference/ts_simplify.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Simplify the tree sequence down to a given set of individuals — ts_simplify","text":"ts Tree sequence object class slendr_ts simplify_to character vector individual names. NULL, explicitly remembered individuals (.e. specified via schedule_sampling function left tree sequence simplification. keep_input_roots history ancestral MRCA samples retained tree sequence? Default FALSE. keep_unary unary nodes preserved simplification? Default FALSE. keep_unary_in_individuals unary nodes preserved simplification associated individual recorded table individuals? Default FALSE. set TRUE keep_unary also TRUE filter_nodes nodes reindexed simplification? Default TRUE. See tskit's documentation Python method simplify()","code":""},{"path":"https://www.slendr.net/reference/ts_simplify.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Simplify the tree sequence down to a given set of individuals — ts_simplify","text":"Tree-sequence object class slendr_ts, serves interface point Python module tskit using slendr functions ts_ prefix.","code":""},{"path":"https://www.slendr.net/reference/ts_simplify.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Simplify the tree sequence down to a given set of individuals — ts_simplify","text":"simplification process used remove redundant information tree sequence retains information necessary describe genealogical history set samples. information simplification works pyslim tskit, see official documentation https://tskit.dev/tskit/docs/stable/python-api.html#tskit.TreeSequence.simplify https://tskit.dev/pyslim/docs/latest/tutorial.html#simplification. clear description difference remembering retaining use techniques implement historical individuals (.e. ancient DNA samples) pyslim documentation https://tskit.dev/pyslim/docs/latest/tutorial.html#historical-individuals.","code":""},{"path":[]},{"path":"https://www.slendr.net/reference/ts_simplify.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Simplify the tree sequence down to a given set of individuals — ts_simplify","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) ts <- ts_load(slendr_ts, model) ts #> ╔════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤════════╣ #> ║Trees │ 70║ #> ╟───────────────┼────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼────────╢ #> ║Sample Nodes │ 26║ #> ╟───────────────┼────────╢ #> ║Total Size │68.2 KiB║ #> ╚═══════════════╧════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 298│ 9.3 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 73│ 8.9 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 86│ 3.9 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 5│ 2.6 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 3│37.3 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Sites │ 0│16 Bytes│ No║ #> ╚═══════════╧════╧════════╧════════════╝ #> # simplify tree sequence to sampled individuals ts_simplified <- ts_simplify(ts) # simplify to a subset of sampled individuals ts_small <- ts_simplify(ts, simplify_to = c(\"CH_1\", \"NEA_1\", \"NEA_2\", \"AFR_1\", \"AFR_2\", \"EUR_1\", \"EUR_2\")) ts_small #> ╔════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤════════╣ #> ║Trees │ 28║ #> ╟───────────────┼────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼────────╢ #> ║Sample Nodes │ 14║ #> ╟───────────────┼────────╢ #> ║Total Size │56.0 KiB║ #> ╚═══════════════╧════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 118│ 3.7 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 32│ 4.9 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 39│ 2.1 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 5│ 2.6 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 4│37.8 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Sites │ 0│16 Bytes│ No║ #> ╚═══════════╧════╧════════╧════════════╝ #>"},{"path":"https://www.slendr.net/reference/ts_table.html","id":null,"dir":"Reference","previous_headings":"","what":"Get the table of individuals/nodes/edges/mutations from the tree sequence — ts_table","title":"Get the table of individuals/nodes/edges/mutations from the tree sequence — ts_table","text":"function extracts data given tree sequence table. times converted model-specific time units tskit's \"generations backwards\" time direction.","code":""},{"path":"https://www.slendr.net/reference/ts_table.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Get the table of individuals/nodes/edges/mutations from the tree sequence — ts_table","text":"","code":"ts_table(ts, table = c(\"individuals\", \"edges\", \"nodes\", \"mutations\"))"},{"path":"https://www.slendr.net/reference/ts_table.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Get the table of individuals/nodes/edges/mutations from the tree sequence — ts_table","text":"ts Tree sequence object class slendr_ts table tree sequence table return","code":""},{"path":"https://www.slendr.net/reference/ts_table.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Get the table of individuals/nodes/edges/mutations from the tree sequence — ts_table","text":"Data frame information give tree-sequence table (can either table individuals, edges, nodes, mutations).","code":""},{"path":"https://www.slendr.net/reference/ts_table.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Get the table of individuals/nodes/edges/mutations from the tree sequence — ts_table","text":"processing analyses, output function ts_nodes might useful, merges information node individual tables one table annotates useful information model configuration data.","code":""},{"path":[]},{"path":"https://www.slendr.net/reference/ts_table.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Get the table of individuals/nodes/edges/mutations from the tree sequence — ts_table","text":"","code":"# load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk and add mutations to it ts <- ts_load(slendr_ts, model) %>% ts_mutate(mutation_rate = 1e-8, random_seed = 42) # get the 'raw' tskit table of individuals ts_table(ts, \"individuals\") #> # A tibble: 73 × 9 #> ind_id time pedigree_id pop_id alive remembered retained sampled time_tskit #> #> 1 0 -10 16023346 0 TRUE TRUE TRUE TRUE 0 #> 2 1 -10 16023350 1 TRUE TRUE TRUE TRUE 0 #> 3 2 -10 16023352 1 TRUE TRUE TRUE TRUE 0 #> 4 3 -10 16023353 1 TRUE TRUE TRUE TRUE 0 #> 5 4 -10 16023355 1 TRUE TRUE TRUE TRUE 0 #> 6 5 -10 16023359 1 TRUE TRUE TRUE TRUE 0 #> 7 6 -10 16024625 3 TRUE TRUE TRUE TRUE 0 #> 8 7 -10 16025081 3 TRUE TRUE TRUE TRUE 0 #> 9 8 -10 16025520 3 TRUE TRUE TRUE TRUE 0 #> 10 9 -10 16026684 3 TRUE TRUE TRUE TRUE 0 #> # ℹ 63 more rows # get the 'raw' tskit table of edges ts_table(ts, \"edges\") #> # A tibble: 298 × 5 #> id child parent left right #> #> 1 0 6 26 0 500000 #> 2 1 13 26 0 500000 #> 3 2 7 27 0 500000 #> 4 3 8 27 0 500000 #> 5 4 12 27 0 500000 #> 6 5 5 28 0 500000 #> 7 6 10 28 0 500000 #> 8 7 11 29 306056 500000 #> 9 8 26 29 306056 500000 #> 10 9 27 30 0 500000 #> # ℹ 288 more rows # get the 'raw' tskit table of nodes ts_table(ts, \"nodes\") #> # A tibble: 86 × 5 #> node_id ind_id pop_id time time_tskit #> #> 1 0 25 2 70010 2334 #> 2 1 25 2 70010 2334 #> 3 2 43 2 40010 1334 #> 4 3 43 2 40010 1334 #> 5 4 1 1 -10 0 #> 6 5 1 1 -10 0 #> 7 6 2 1 -10 0 #> 8 7 2 1 -10 0 #> 9 8 3 1 -10 0 #> 10 9 3 1 -10 0 #> # ℹ 76 more rows # get the 'raw' tskit table of mutations ts_table(ts, \"mutations\") #> # A tibble: 2,246 × 5 #> id site node time time_tskit #> #> 1 0 0 83 3626483. 120883. #> 2 1 1 83 1766659. 58889. #> 3 2 2 83 2476958. 82566. #> 4 3 3 83 4356462. 145216. #> 5 4 4 83 876159. 29206. #> 6 5 5 83 3848814. 128294. #> 7 6 6 83 2554081. 85136. #> 8 7 7 83 976093. 32537. #> 9 8 8 32 3622571. 120753. #> 10 9 9 32 104626. 3488. #> # ℹ 2,236 more rows"},{"path":"https://www.slendr.net/reference/ts_tajima.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate Tajima's D for given sets of individuals — ts_tajima","title":"Calculate Tajima's D for given sets of individuals — ts_tajima","text":"discussion difference \"site\" \"branch\" options mode argument, please see tskit documentation https://tskit.dev/tskit/docs/stable/stats.html#sec-stats-mode","code":""},{"path":"https://www.slendr.net/reference/ts_tajima.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate Tajima's D for given sets of individuals — ts_tajima","text":"","code":"ts_tajima(ts, sample_sets, mode = c(\"site\", \"branch\", \"node\"), windows = NULL)"},{"path":"https://www.slendr.net/reference/ts_tajima.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate Tajima's D for given sets of individuals — ts_tajima","text":"ts Tree sequence object class slendr_ts sample_sets list (optionally named list) character vectors individual names (one vector per set). simple vector provided, interpreted .list(sample_sets), meaning given statistic calculated individual separately. mode mode calculation (\"sites\" \"branch\") windows Coordinates breakpoints windows. first coordinate (0) last coordinate (equal ts$sequence_length) added automatically)","code":""},{"path":"https://www.slendr.net/reference/ts_tajima.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate Tajima's D for given sets of individuals — ts_tajima","text":"set individuals either single Tajima's D value vector Tajima's D values (one window)","code":""},{"path":"https://www.slendr.net/reference/ts_tajima.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate Tajima's D for given sets of individuals — ts_tajima","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) %>% ts_mutate(mutation_rate = 1e-8, random_seed = 42) # calculate Tajima's D for given sets of individuals in a tree sequence ts ts_tajima(ts, list(eur = c(\"EUR_1\", \"EUR_2\", \"EUR_3\", \"EUR_4\", \"EUR_5\"), nea = c(\"NEA_1\", \"NEA_2\"))) #> # A tibble: 2 × 2 #> set D #> #> 1 eur -1.16 #> 2 nea 2.18"},{"path":"https://www.slendr.net/reference/ts_tracts.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract ancestry tracts from a tree sequence (EXPERIMENTAL) — ts_tracts","title":"Extract ancestry tracts from a tree sequence (EXPERIMENTAL) — ts_tracts","text":"Extract data frame coordinates ancestry tracts given tree sequence.","code":""},{"path":"https://www.slendr.net/reference/ts_tracts.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract ancestry tracts from a tree sequence (EXPERIMENTAL) — ts_tracts","text":"","code":"ts_tracts(ts, census, squashed = TRUE, source = NULL, target = NULL)"},{"path":"https://www.slendr.net/reference/ts_tracts.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract ancestry tracts from a tree sequence (EXPERIMENTAL) — ts_tracts","text":"ts Tree sequence object class slendr_ts census Census time. See documentation linked Details information. slendr-specific tree sequence provided ts, census time expected given slendr model-specific time units, must correspond gene-flow event encoded model. squashed ancestry tracts squashed (.e., continuous tracts can traced different ancestral nodes merged)? Default TRUE. FALSE, effectively continuous ancestry tracts split individual segments, assigned specific ancestral node ID (recorded column ancestor_id). source source population extract tracts ? NULL (default), ancestry tracts populations contributing gene flow census time reported. Otherwise, ancestry tracts specified source populations extracted. Note option ignored non-slendr tree sequences! target Similar purpose source , except filters tracts discovered target population(s)","code":""},{"path":"https://www.slendr.net/reference/ts_tracts.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract ancestry tracts from a tree sequence (EXPERIMENTAL) — ts_tracts","text":"data frame containing coordinates ancestry tracts","code":""},{"path":"https://www.slendr.net/reference/ts_tracts.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Extract ancestry tracts from a tree sequence (EXPERIMENTAL) — ts_tracts","text":"function implements R-friendly interface algorithm extracting ancestry tracts provided Python module tspop https://tspop.readthedocs.io/en/latest/ developed Georgia Tsambos. Please make sure cite paper describes algorithm detail: https://academic.oup.com/bioinformaticsadvances/article/3/1/vbad163/7429395. technical details, see also tutorial : https://tspop.readthedocs.io/en/latest/basicusage.html. general, using function slendr-generated tree sequence, please aware output changes slightly get running pure tspop.get_pop_ancestry() Python. First, ts_tracts() populates output data frame additional metadata (names individuals populations). Additionally, slendr models, specifically designed return ancestry tracts originating ancestral population contributed ancestry gene-flow event started specific time (.e., scheduled model via gene_flow()) function. return every single ancestry tracts present tree sequence every single sample node (every single potential ancestry population) tspop.get_pop_ancestry() Python method. said, run tree sequence originate slendr simulation, behavior ts_tracts() identical underlying tspop.get_pop_ancestry(). current version slendr, ts_tracts() works slendr/msprime sequences slendr/SLiM tree sequences. Support slendr-generated SLiM tree sequences development. Tracts tree sequences originating non-slendr msprime SLiM simulations restricted way , mentioned previous paragraph, ts_tracts() situation effectively reduces standard tspop.get_pop_ancestry() call.","code":""},{"path":"https://www.slendr.net/reference/ts_tracts.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract ancestry tracts from a tree sequence (EXPERIMENTAL) — ts_tracts","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env(quiet = TRUE) # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_msprime.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(file = slendr_ts, model = model) # extract Neanderthal ancestry tracts (i.e. those corresponding to the # census event at the gene-flow time at 55000 kya as scheduled by # the simulation which produced the tree sequence) nea_tracts <- ts_tracts(ts, census = 55000, source = \"NEA\") #> #> PopAncestry summary #> Number of ancestral populations: \t4 #> Number of sample chromosomes: \t\t26 #> Number of ancestors: \t\t\t763 #> Total length of genomes: \t\t130000000.000000 #> Ancestral coverage: \t\t\t120000000.000000 #> nea_tracts #> # A tibble: 42 × 8 #> name node_id pop source_pop left right length source_pop_id #> #> 1 EUR_1 16 EUR NEA 44049 101210 57161 2 #> 2 EUR_1 16 EUR NEA 244041 280650 36609 2 #> 3 EUR_1 16 EUR NEA 4636048 4736790 100742 2 #> 4 EUR_1 16 EUR NEA 4756344 4850072 93728 2 #> 5 EUR_1 17 EUR NEA 106906 268610 161704 2 #> 6 EUR_1 17 EUR NEA 1420672 1432252 11580 2 #> 7 EUR_1 17 EUR NEA 3438894 3511366 72472 2 #> 8 EUR_1 17 EUR NEA 3624298 3682434 58136 2 #> 9 EUR_1 17 EUR NEA 4139989 4239794 99805 2 #> 10 EUR_1 17 EUR NEA 4318138 4351616 33478 2 #> # ℹ 32 more rows"},{"path":"https://www.slendr.net/reference/ts_tree.html","id":null,"dir":"Reference","previous_headings":"","what":"Get a tree from a given tree sequence — ts_tree","title":"Get a tree from a given tree sequence — ts_tree","text":"information optional keyword arguments see tskit documentation: https://tskit.dev/tskit/docs/stable/python-api.html#-treesequence-class","code":""},{"path":"https://www.slendr.net/reference/ts_tree.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Get a tree from a given tree sequence — ts_tree","text":"","code":"ts_tree(ts, i, mode = c(\"index\", \"position\"), ...)"},{"path":"https://www.slendr.net/reference/ts_tree.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Get a tree from a given tree sequence — ts_tree","text":"ts Tree sequence object class slendr_ts Position tree tree sequence. mode = \"index\", -th tree returned (zero-based indexing tskit), mode = \"position\", tree covering -th base simulated genome returned (, tskit's indexing). mode argument interpreted? Either \"index\" -th tree sequence genealogies, \"position\" along simulated genome. ... Additional keyword arguments accepted tskit.TreeSequence.tskit.TreeSequence.at_index methods","code":""},{"path":"https://www.slendr.net/reference/ts_tree.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Get a tree from a given tree sequence — ts_tree","text":"Python-reticulate-based object class tskit.trees.Tree","code":""},{"path":"https://www.slendr.net/reference/ts_tree.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Get a tree from a given tree sequence — ts_tree","text":"","code":"check_dependencies(python = TRUE, quit = TRUE) # dependencies must be present init_env() #> The interface to all required Python modules has been activated. # load an example model with an already simulated tree sequence slendr_ts <- system.file(\"extdata/models/introgression_slim.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) # load the tree-sequence object from disk ts <- ts_load(slendr_ts, model) # extract the zero-th tree in the tree sequence tree <- ts_tree(ts, i = 0) # extract the tree at a position in the tree sequence tree <- ts_tree(ts, i = 100000, mode = \"position\")"},{"path":"https://www.slendr.net/reference/ts_vcf.html","id":null,"dir":"Reference","previous_headings":"","what":"Save genotypes from the tree sequence as a VCF file — ts_vcf","title":"Save genotypes from the tree sequence as a VCF file — ts_vcf","text":"Save genotypes tree sequence VCF file","code":""},{"path":"https://www.slendr.net/reference/ts_vcf.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Save genotypes from the tree sequence as a VCF file — ts_vcf","text":"","code":"ts_vcf(ts, path, chrom = NULL, individuals = NULL)"},{"path":"https://www.slendr.net/reference/ts_vcf.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Save genotypes from the tree sequence as a VCF file — ts_vcf","text":"ts Tree sequence object class slendr_ts path Path VCF file chrom Chromosome name written CHROM column VCF individuals character vector individuals tree sequence. missing, individuals present tree sequence saved.","code":""},{"path":"https://www.slendr.net/reference/ts_vcf.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Save genotypes from the tree sequence as a VCF file — ts_vcf","text":"return value, called side effects","code":""},{"path":"https://www.slendr.net/reference/world.html","id":null,"dir":"Reference","previous_headings":"","what":"Define a world map for all spatial operations — world","title":"Define a world map for all spatial operations — world","text":"Defines either abstract geographic landscape (blank containing user-defined landscape) using real Earth cartographic data Natural Earth project (https://www.naturalearthdata.com).","code":""},{"path":"https://www.slendr.net/reference/world.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Define a world map for all spatial operations — world","text":"","code":"world( xrange, yrange, landscape = \"naturalearth\", crs = NULL, scale = c(\"small\", \"medium\", \"large\") )"},{"path":"https://www.slendr.net/reference/world.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Define a world map for all spatial operations — world","text":"xrange Two-dimensional vector specifying minimum maximum horizontal range (\"longitude\" using real Earth cartographic data) yrange Two-dimensional vector specifying minimum maximum vertical range (\"latitude\" using real Earth cartographic data) landscape Either \"blank\" (blank abstract geography), \"naturalearth\" (real Earth geography) object class sf defining abstract geographic features world crs EPSG code coordinate reference system use spatial operations. CRS assumed default (NULL), implying abstract landscape tied real-world geographic region (landscape = \"blank\" landscape custom-defined geographic landscape), implying WGS-84 (EPSG 4326) coordinate system real Earth landscape defined (landscape = \"naturalearth\"). scale Natural Earth geographic data used (.e. landscape = \"naturalearth\"), parameter determines resolution data used. value \"small\" corresponds 1:110m data provided package, values \"medium\" \"large\" correspond 1:50m 1:10m respectively downloaded internet. Default value \"small\".","code":""},{"path":"https://www.slendr.net/reference/world.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Define a world map for all spatial operations — world","text":"Object class slendr_map, encodes standard spatial object class sf additional slendr-specific attributes requested x-range y-range.","code":""},{"path":"https://www.slendr.net/reference/world.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Define a world map for all spatial operations — world","text":"","code":"# create a blank abstract world 1000x1000 distance units in size blank_map <- world(xrange = c(0, 1000), yrange = c(0, 1000), landscape = \"blank\") # it is possible to construct custom landscapes (islands, corridors, etc.) island1 <- region(\"island1\", polygon = list(c(10, 30), c(50, 30), c(40, 50), c(0, 40))) island2 <- region(\"island2\", polygon = list(c(60, 60), c(80, 40), c(100, 60), c(80, 80))) island3 <- region(\"island3\", center = c(20, 80), radius = 10) archipelago <- island1 %>% join(island2) %>% join(island3) custom_map <- world(xrange = c(1, 100), c(1, 100), landscape = archipelago) # real Earth landscapes can be defined using freely-available Natural Earth # project data and with the possibility to specify an appropriate Coordinate # Reference System, such as this example of a map of Europe real_map <- world(xrange = c(-15, 40), yrange = c(30, 60), crs = \"EPSG:3035\") #> Reading layer `ne_110m_land' from data source #> `/private/var/folders/70/b_q2zdh116b9pfg29p03sx600000gn/T/RtmpFhhY5X/naturalearth/ne_110m_land.shp' #> using driver `ESRI Shapefile' #> Simple feature collection with 127 features and 3 fields #> Geometry type: POLYGON #> Dimension: XY #> Bounding box: xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513 #> Geodetic CRS: WGS 84"},{"path":"https://www.slendr.net/news/index.html","id":"slendr-090","dir":"Changelog","previous_headings":"","what":"slendr 0.9.0","title":"slendr 0.9.0","text":"full support running SLiM msprime simulations slendr analyzing tree sequences using tskit interface implemented. Please note Windows support still rather experimental – internal slendr test suite currently assumes SLiM installed using msys2 system described section 2.3.1 SLiM manual means installing SLiM (via conda) might require additional adjustments. fallback option form slim_path= argument slim() function can used non-standard SLiM installation circumstances. convenience, please add path directory containing slim.exe binary PATH variable editing C:/Users//Documents/.Renviron file accordingly. See relevant section Windows installation slendr documentation additional information. Feedback Windows functionality bug reports highly appreciated via GitHub issues! Many thanks @GKresearch @rdinnager huge help making Windows port happen! (PR #149) trivial change made slendr’s SLiM back-end script fixing issue introduced SLiM 4.1 upgrade (see changelog version 0.8.1 ). expected lead different simulation outputs two versions slendr (0.8.2 vs 0.8.1) SLiM (4.1 vs 4.0.1) used. (PR #148) msprime internal dependency slendr updated 1.3.0, Python 3.12. result, loading slendr, users prompted re-run setup_env() make sure dedicated slendr Python environment fully updated. time, prevents failing installation (least) M1 macOS using pip. (#5ce212, #a210d4)","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-081","dir":"Changelog","previous_headings":"","what":"slendr 0.8.1","title":"slendr 0.8.1","text":"CRAN release: 2024-01-15 Fixed issue apparent contradiction time direction models range expansion scheduled within time interval together associated “locked-” changes population size time interval. (#d2a29e) introduction tspop installable via pip (see changelog previous version) caused GLIBCXX-related errors conda pip dependencies related pandas Python package. work around issue, setup_env() longer installs pandas conda regardless setting pip = TRUE|FALSE parameter. Instead, pandas installed via pip single step tspop installed. (#cbe960) WARNING: SLiM 4.1 just released includes couple backwards incompatible changes related implementation spatial maps prevent current version slendr’s slim() function working correctly. rely functionality provided slim() function, use SLiM 4.0. (Note want multiple versions SLiM system, can either use slim_path = argument slim() specify $PATH required version SLiM ~/.Renviron file just like normal circumstances). Porting slendr SLiM 4.1 worked .","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-080","dir":"Changelog","previous_headings":"","what":"slendr 0.8.0","title":"slendr 0.8.0","text":"CRAN release: 2023-12-07 order support new ts_tracts() function backed tspop module (see item ), new slendr Python environment required. , users run setup_env() get required Python dependencies now installed internal virtual environment named Python-3.11_msprime-1.2.0_tskit-0.5.6_pyslim-1.0.4_tspop-0.0.2. (#b5330c) Experimental support tspop link-ancestors algorithm detection ancestry tracts form new slendr function ts_tracts(). works slendr-generated msprime tree sequences “pure” msprime SLiM tree sequences (slendr-generated SLiM tree sequences), tested toy models. Note: tspop Python module published conda. order set new slendr Python environment, run setup_env(pip = TRUE) make sure Python dependencies installed pip instead conda. (PR #145) Updated Python dependencies (bugfix pyslim release v1.0.4 tskit v0.5.6, latter due broken jsonschema dependency tskit). (#001ee5) Experimental support manually created spatial tree sequences. (PR #144)","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-072","dir":"Changelog","previous_headings":"","what":"slendr 0.7.2","title":"slendr 0.7.2","text":"CRAN release: 2023-08-08 new function ts_names() added, avoiding need extremely frequent (, unfortunately, cumbersome) trick getting named lists individual symbolic names ts_samples(ts) %>% split(., .[[split]]) %>% lapply([[, \"name\") confusing experienced R users. (#7db6ea) Fixed broken concatenation symbolic sample names tree-sequence statistic functions, provided unnamed single-element lists character vectors. (#b3c650) plot_model() now argument file =, making possible save visualization model without actually opening plotting device. can useful particularly working remote server, order avoid often slow X11 rendering. (#e60078) plot_model() now argument order = allowing override default -order ordering populations along x-axis. (#7a10ea)","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-071","dir":"Changelog","previous_headings":"","what":"slendr 0.7.1","title":"slendr 0.7.1","text":"CRAN release: 2023-07-14 Starting release, *spatial* simulation data analysis functionality slendr conditional presence R geospatial packages sf, stars, rnaturalearth system. means users able install slendr (use non-spatial functionality) even without R packages installed. said, nothing really changes practice: spatial features slendr just one install.packages(c(\"sf\", \"stars\", \"rnaturalearth\")) away! difference slendr doesn’t try installation, users instructed (needed) package loaded. (#7a10ea) spatial dependencies present spatial slendr function called regardless (world(), move(), etc.), error message printed information install spatial dependencies via install.packages() . ? ’s true main reason slendr’s existence ability simulate spatio-temporal data realistic landscapes via SLiM. However, practice, “average” uses slendr wild (classrooms!) rely traditional, non-spatial interface, spatial features used comparatively rarely moment (except cutting-edge exploratory research). Given setting spatial dependencies can bit hurdle, decided make dependencies optional, rather force every user go process installation whether need spatial features . function check_dependencies() now exported can used check whether slendr Python environment () SLiM () present. useful software building upon slendr, normal users can freely ignore . (#6ae6ce) path file tree sequence loaded now tracked internally via attr(, \"path\") attribute. Note implemented purposes clean large-scale simulation studies (facilitated demografr) mostly internal feature, considered experimental. (#f181a2) Attempts resize population right time split (led issues simulations) now prevented. (#f181a2) Fix minor issue preventing sampling msprime population right time creation. (#aea231)","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-070","dir":"Changelog","previous_headings":"","what":"slendr 0.7.0","title":"slendr 0.7.0","text":"CRAN release: 2023-06-26 emergency upgrade match latest pyslim 1.0.3 due serious bug recapitation. See extensive discussion process identification bug eventual fix. brief summary practical consequences bug, see thread pyslim’s developer formal announcement . change require re-run setup_env() order update slendr’s Python internals creating new internal Python virtual environment. (#45539a) potential issue parent population scheduled removal daughter population splits now caught moment daughter population() call rather simulation slim() run. (#0791b5) function plot_model() new argument gene_flow= determines whether gene-flow arrows visualized . (#104aa6) possibility perform recapitation, simplification, mutation tree sequence right inside call ts_load() (providing recapitate = TRUE, simplify = TRUE, mutate = TRUE, together arguments) now removed. motivation change realization benefit things like ts_load(\"\", recapitate = TRUE, Ne = ..., recombination_rate = ...) ts_load(\"\") %>% ts_recapitate(Ne = ..., recombination_rate = ...), frequent confusion recapitate = TRUE switches forgotten user. slendr teaching material actively used research codebases know use latter, explicit, pipeline approach anyway, one example reduncancy harm good. (#ad82ee) Note: Loading library(slendr) prompt message “legacy packages maptools, rgdal, rgeos, underpinning sp package, just loaded, retire October 2023. […].” internal business packages used slendr unfortunately silenced slendr’s side. ’s reason panic, can safely ignore . Apologies unnecessary noise.","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-060","dir":"Changelog","previous_headings":"","what":"slendr 0.6.0","title":"slendr 0.6.0","text":"CRAN release: 2023-06-07 relatively large update, unfortunately released haste due retirement rgdal package – significant dependency entire spatial R ecosystem phased effort move towards modern low-level geospatial architecture. Although slendr depend rgdal, many dependencies used (won’t short term, hence push remove rgdal dependency). significant update addition IBD functionality tskit, described . However, large part functionality extensively tested considered extremely experimental stage. like use , might safer either wait later release IBD functionality stable, use underlying, battle-tested Python implementation tskit. ts_ibd() now returns ID number MRCA node pair nodes sharing given IBD segment, well TMRCA node. (#7e2825) Trivial parameter errors caught population() calls rather simulation (solving minor issues discovered via big simulation runs development demografr). (#e33373) Fix error plotting exponential resizes last “present”. (#4c49a4) ts_ibd() longer gives obscure error = provided named list individuals’ names (instead expected unnamed list). names list elements used way, error happens somewhere deeply R->Python translation layer inside reticulate ’s need users concern . (#7965e4) Population size parameters times now explicitly converted integer numbers. internal, formal change (conversion happening implicitly inside SLiM engine anyway) now explicitly stated, also documentation relevant function. (#b7e89e) Population names now restricted strings also valid Python identifiers. Although restriction needed msprime back end slendr (SLiM), makes sense keep things tidy unified. fixes msprime crashing ValueError: population name must valid Python identifier. (#4ef518) layout algorithm plot_model() improved significantly. (PR #135). new optional argument run = added slim() msprime(). set TRUE (default), engines operate usual way. set FALSE, simulation run functions simply print command-line command execute engine question (returning CLI command invisibly). (#2e5b85) following start-note longer shown upon calling library(slendr): Users call init_env() manually activate Python environment slendr (see note version 0.5.0 extended explanation). ts_simplify() now accepts optional arguments keep_unary keep_unary_in_individuals (see official tskit docs detail) (#1b2112) Fix ts_load() failing load slendr-produced tree sequences simplified smaller set sampled individuals (reported ). issue caused incompatible sizes sampling table (always form used simulation) table individuals stored tree sequence simplification (potentially containing smaller set individuals original sampling table). fix , slendr tree sequence objects now track information individuals regarded “samples” (.e. symbolic names) maintained simplification, serialization loading, used slendr’s internal machinery join operations. (PR #137) Metadata summary ts_nodes() results longer printed whenever typed R console. Instead, summary can obtained explicit call summary() ts_nodes() tables. (#01af51 ts_tree() ts_phylo() now extract trees based tskit’s zero-based indexing #554e13. ts_simplify() now accepts filter_nodes = TRUE|FALSE, behavior tskit’s method #f07ffed.","code":"NOTE: Due to Python setup issues on some systems which have been causing trouble particularly for novice users, calling library(slendr) no longer activates slendr's Python environment automatically. In order to use slendr's msprime back end or its tree-sequence functionality, users must now activate slendr's Python environment manually by executing init_env() after calling library(slendr). (This note will be removed in the next major version of slendr.)"},{"path":"https://www.slendr.net/news/index.html","id":"slendr-051","dir":"Changelog","previous_headings":"","what":"slendr 0.5.1","title":"slendr 0.5.1","text":"CRAN release: 2023-03-09 minor release implements emergency fix CRAN warning suddenly popped latest CRAN checks. (#5600a4) new function ts_ibd() added, representing R interface tskit method TreeSequence.ibd_segments(). However, note ts_ibd() returns IBD results data frame (optionally, spatially annotated sf data frame). function operate around iteration, Python counterpart tskit. next major version slendr, function considered experimental. (PR #123)","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-050","dir":"Changelog","previous_headings":"","what":"slendr 0.5.0","title":"slendr 0.5.0","text":"CRAN release: 2023-02-02 Minor breaking change! Python environments slendr longer automatically activated upon calling library(slendr)! Using coalescent msprime back end slendr’s tree-sequence functions now requires making explicit call new function init_env() library(slendr) executed. (PR #102) Motivation change: small proportion users experiencing issues broken conda environments various issues Python virtual environments general. ’s hard guess frequent , experience workshops courses suggests perhaps 1 20 users experiencing Python issues hindered ability use slendr .(Fun fact: first user-submitted GitHub issue upon releasing first version slendr R package … Python virtual environment issue). Explanation: Activating Python environments automatically upon calling library(slendr) popular feature hid away complexities R-Python interface powers slendr’s tree-sequence functionality. particularly convenient many slendr users, particularly experience Python . Unfortunately, cases Python virtual environments tskit/msprime/pyslim user’s system ended corrupted (anything else Python level got broken), automatic Python environment activation performed library(slendr) call failed slendr even loaded. Sadly, completely pulled rug slendr nothing done perspective (issue happened low-level layer embedded-Python slendr ’ve loaded R). Solving issues difficult experienced users, many slendr users experience Python , never used conda, don’t understand concept “Python virtual environments” R-Python interface works. ! , slendr R package. Splitting Python virtual environment activation step init_env() function means library(slendr) now always succeeds (regardless potential underlying Python issues user’s sytem), making much easier diagnose fix Python problems R package loaded. , recap: library(slendr) longer activates slendr’s isolated Python virtual environment. order simulate tree sequences analyse using interface tskit, necessary call init_env(). function performs Python-activation steps library(slendr) used call automagically earlier slendr versions. change scripts necessary. Related previous point: slendr now requires Python 3.11, msprime 1.2.0, tskit 0.5.4, pyslim 1.0.1, keep recent releases Python dependencies. , presents hassle user, thing required re-running setup_env(). (PR #112). named list provided sample_sets = argument oneway statistic function, names used set column resulting data frame even single samples used. (#2a6781) now possible non-spatial populations otherwise spatial model. course, plotting models map, spatial components model plotted slendr give warning. absolutely sure users intends , slendr also give warning running compile_model() models like . Please consider option experimental time-hard predict edge cases might break (unit tests documentation tests passing though). Feedback welcome. (PR #112). now possible label groups samples slendr’s tskit interface functions make data frames statistics results readable. example, running ts_f3(ts, = c(\"p1_1\", \"p1_2\", \"p1_3\"), B = c(\"p2_1\", \"p2_3\"), C = c(\"p3_1\", \"p3_2\", \"p3_\")) resulted following data-frame output: gets unwieldy rather quickly, especially dozens hundreds samples grouped together populations. new syntax allows following shortcut via customised group names leveraging standard named list functionality R: readable line tskit-interface functions slendr used functionality via sample_sets = argument (ts_divergence(), ts_diversity(), etc.). (#ac5e484) default state parent = argument population() now NULL instead \"ancestor\". prevents silly surprising clashes situation population’s name really “ancestor”. change internally populations ancestral, splits data frame element slendr model object includes population carries formal “ancestral parent population” \"__pop_is_ancestor\" instead just \"ancestor\". Note internal implementation detail something particularly involve user. Still, somehow using slendr’s internal data structures, keep mind. (#f8a39a2)","code":"> ts_f3(ts, A = c(\"p1_1\", \"p1_2\", \"p1_3\", \"p1_4\", \"p1_5\"), B = c(\"p2_1\", \"p2_2\", \"p2_3\"), C = c(\"p3_1\", \"p3_2\", \"p3_3\", \"p3_4\")) # A tibble: 1 × 4 A B C f3 1 p1_1+p1_2+p1_3+p1_4+p1_5 p2_1+p2_2+p2_3 p3_1+p3_2+p3_3+p3_4 0.000130 > ts_f3(ts, A = list(group_one = c(\"p1_1\", \"p1_2\", \"p1_3\", \"p1_4\", \"p1_5\")), B = list(group_two = c(\"p2_1\", \"p2_2\", \"p2_3\")), C = list(group_three = c(\"p3_1\", \"p3_2\", \"p3_3\", \"p3_4\"))) # A tibble: 1 × 4 A B C f3 1 group_one group_two group_three 0.000130"},{"path":"https://www.slendr.net/news/index.html","id":"slendr-040","dir":"Changelog","previous_headings":"","what":"slendr 0.4.0","title":"slendr 0.4.0","text":"CRAN release: 2022-09-30 msprime() function now makes sure given slendr model can fully coalesce single common ancestor population. Previously, multiple ancestral populations created parent = \"ancestor\" cause infinite simulation plugged msprime() backend. (#095b124) initial size population emerges split another population now printed population history summary R console. (#6525bf3) couple fixes support loading, processing, plotting “manually” created tree sequences implemented (see ). sure practically useful, ’s important able load even “pure” tree sequences simulators SLiM msprime. set unit tests added, making sure minimalist nodes & edges table can loaded, well nodes & edges & individuals, plus tables populations sites & mutations. PRs extensive unit tests bug reports tree sequences failing load appreciated! code handling cases “manually-created” tree sequences missing individual table, missing populations table, etc. seems especially brittle moment (#79adf14). -1 value missing value indicator used tskit now replaced R-like NA various tree-sequence tables (annotated slendr original tskit ) (#79adf14). Relative paths now expanded ts_save() (#382e0b7). slendr models can now optionally compiled without serialization disk. works msprime() coalescent back end much faster cases huge number simulations needs run non-serialized models, msprime() now calls back end engine directly R-Python interface (rather command line) output tree sequences saved disk, rather passed Python-R interface directly memory (PR #112). Deprecated argument sampling = functions slim() msprime() now permanently removed favour samples = argument (#0757b6e). Avoid unnecessary array type tskit results returned via reticulate. Numeric vectors (columns data frames numerical results) obtained way simple R numeric vector (#5101b39). One-way multi-way statistics results now returned simple numerical vectors. Previously, results returned type array despite “looking” vectors (values returned R reticulate-Python layer), caused unnecessary annoyances type-conversions R side things even intended (#403df3b). Computing population genetic statistics named samples present tree sequence (likely typos) now correctly caught reported error (#da7e0bb).","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-030","dir":"Changelog","previous_headings":"","what":"slendr 0.3.0","title":"slendr 0.3.0","text":"CRAN release: 2022-08-19 SLiM 4.0 now required running simulations slim() engine. want run slendr simulations SLiM (spatial non-spatial), need upgrade SLiM installation. SLiM 3.7.1 version longer supported upcoming new slendr spatial features depend SLiM 4.x maintaining two functionally identical yet syntactically different back ends feasible (PR #104). time SLiM 4.0 release, new versions Python modules msprime, tskit pyslim also released. fact, able work SLiM 4.0 tree sequences properly, Python modules must upgraded well. Next time load library(slendr), prompted setup new updated Python environment can easily running setup_env(). Experimental support running coalescent msprime simulations analysing tree-sequence data using tskit Windows platform now implemented (PR #102).","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-020","dir":"Changelog","previous_headings":"","what":"slendr 0.2.0","title":"slendr 0.2.0","text":"CRAN release: 2022-08-09 slendr now CRAN! Big changes way tree-sequence outputs handled slendr default. See comment extended description examples change. (PR #100). Briefly, simulation functions slim() msprime() now return tree-sequence object default (can switched setting load = FALSE), avoiding need always run ts <- ts_load(model) previously. time, parameter output = can now used slim() msprime() specify location tree-sequence file saved (temporary file default). slendr’s tree-sequence R interface tskit Python module generalized load, process, analyze tree sequences non-slendr models! means users can use slendr R package even analyzing tree sequences coming standard msprime SLiM scripts, including spatial capabilities available slendr tree sequences far. Please note generalization still rather experimental might corner cases tree sequence msprime SLiM script load properly leads errors. happens, please open GitHub issue script question attached. (PR #91) Removed functions function arguments originally deprecated renaming phase pre-preprint refactoring. affects compile, boundary, dispersal, expand, geneflow, plot.slendr, plot_graph, read, sampling, shrink. Similarly, deprecated dir argument compile_model now path, geneflow argument compile_model now gene_flow, _dist suffix removed competition_dist, mate_dist, dispersal_dist. get error missing function function argument code used work ancient version slendr, . (#985b451) setting isolated Python environment using setup_env(), slendr now makes decision whether install Python dependencies using pip (critical osx-arm64 conda msprime/tskit unfortunately currently broken) conda (every platform). can still influenced user using pip = argument, now change default behavior ARM64 Mac. (#54a413d) name default slendr Python environment now shortened even , redundant _pandas prefix now dropped. Users notified upon calling library(slendr) new environment created. OK, ’s bug. (#54a413d) format default slendr Python environment now msprime-_tskit-_pyslim-_pandas, dropping slendr_ prefix. paves way towards future non-slendr tskit R package, share Python environment slendr (R packages go hand hand). isn’t really user-facing change, except calling setup_env() suggests creating new Python environment library(slendr) appear slendr environment yet present. Calling setup_env() creating new Python environment scratch solve problem. (#eb05180) xrange yrange parameters world() now enforced two-dimensional numeric vectors, avoiding unnecessary issues misspecified longitude/latitude (#df95369) argument sampling = slim() msprime() now renamed samples = (#adf4e0d). automated setup_env() function creating dedicated mini Python environments slendr now installs packages using pip default. Reason: rate conda failures dependency conflicts (even trivial case installing nothing msprime + tskit + pyslim + pandas) high rely . option use conda package installations setup_env() still , users must explicitly call setup_env(pip = FALSE) get behavior. Note conda still used means install Python ! change affects way Python modules installed dedicated slendr Python environment, installation Python . (#81be1a7) name automatically created slendr-specific Python environment now composed names versions Python modules installed. makes possible naturally upgrade slendr Python dependencies case tskit / msprime / pyslim folks upgrade packages. case, slendr user upgrades slendr package (new version requires newer versions Python modules), slendr simply recommend create new Python environment without additional effort part. (#81be1a7) code setup_env() simplified bare essentials. Now serves way auto-setup dedicated, isolated Python installation slendr environment. interface install Python modules custom-defined Python environment created outside R removed functionality necessary – custom environments can easily activated calling reticulate::use_virtualenv reticulate::use_condaenv. (#30f24b9) Python users want use custom Python environments msprime, tskit, pyslim, can silence suggestion use setup_env() printed library(slendr) call setting options(slendr.custom_env = TRUE). (#30f24b9) argument sim_length = now renamed simulation_length =. accepted moment using old name simply inform user future deprecation. (#56491fb) Extensive set runnable examples including figures built-pre-compiled example model added documentation. (#395df62c)","code":""},{"path":"https://www.slendr.net/news/index.html","id":"slendr-010","dir":"Changelog","previous_headings":"","what":"slendr 0.1.0","title":"slendr 0.1.0","text":"First numbered version slendr celebrate bioRxiv preprint. 🥳 🎉","code":""}]