diff --git a/R/compilation.R b/R/compilation.R index 6d9010ce9..6f9f6816a 100644 --- a/R/compilation.R +++ b/R/compilation.R @@ -464,8 +464,8 @@ slim <- function( -d 'OUTPUT_LOCATIONS=\"%s\"' \\ -d COALESCENT_ONLY=%s \\ -d MAX_ATTEMPTS=%i \\ - %s", - binary, + %s 2>&1", + binary, # path to the SLiM binary on the command line seed, samples, path.expand(model_dir), @@ -490,7 +490,7 @@ slim <- function( # execute the command, capture all log output and decide whether to print # any of the log information to the console - log_output <- suppressWarnings(system(paste(slim_command, "2>&1"), intern = TRUE)) + log_output <- suppressWarnings(system(slim_command, intern = TRUE)) log_warnings <- grep("WARNING", log_output, value = TRUE) if (verbose) cat(log_output, sep = "\n") diff --git a/R/interface.R b/R/interface.R index 83292607f..41bee7d51 100644 --- a/R/interface.R +++ b/R/interface.R @@ -730,19 +730,18 @@ world <- function(xrange, yrange, landscape = "naturalearth", crs = NULL, ) sf::st_agr(map_raw) <- "constant" - ## transform the map (default geographic CRS) into the target CRS - map_transf <- tryCatch({ - sf::st_transform(map_raw, crs) %>% sf::st_make_valid() + # define boundary coordinates in the target CRS + crop_bounds <- define_zoom(xrange, yrange, "EPSG:4326") + + # crop the map to the boundary coordinates + map_cropped <- tryCatch({ + sf::st_crop(sf::st_make_valid(map_raw), crop_bounds) }, error = function(cond) { - sf::st_transform(map_raw, crs) + sf::st_crop(map_raw, crop_bounds) }) - ## define boundary coordinates in the target CRS - zoom_bounds <- define_zoom(xrange, yrange, "EPSG:4326") - zoom_transf <- sf::st_transform(zoom_bounds, crs) %>% sf::st_make_valid() - - ## crop the map to the boundary coordinates - map <- sf::st_crop(map_transf, zoom_transf) + # transform the map into the target CRS if needed + map <- sf::st_transform(map_cropped, crs) } else { stop("Landscape has to be either 'blank', 'naturalearth' or an object of the class 'sf'", call. = FALSE) diff --git a/README.Rmd b/README.Rmd index 10cd9928a..f045b30db 100644 --- a/README.Rmd +++ b/README.Rmd @@ -130,7 +130,7 @@ This makes it easier for us to define spatial features simply by reading the coo africa <- region( "Africa", map, polygon = list(c(-18, 20), c(38, 20), c(30, 33), - c(20, 33), c(10, 38), c(-6, 36)) + c(20, 33), c(10, 38), c(-6, 35)) ) europe <- region( "Europe", map, diff --git a/README.md b/README.md index 215973719..0cc9d7fd0 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ This makes it easier for us to define spatial features simply by reading the coo africa <- region( "Africa", map, polygon = list(c(-18, 20), c(38, 20), c(30, 33), - c(20, 33), c(10, 38), c(-6, 36)) + c(20, 33), c(10, 38), c(-6, 35)) ) europe <- region( "Europe", map, diff --git a/docs/articles/vignette-00-installation.html b/docs/articles/vignette-00-installation.html index c6216c1a0..700cdd73e 100644 --- a/docs/articles/vignette-00-installation.html +++ b/docs/articles/vignette-00-installation.html @@ -124,24 +124,24 @@

Quick installation in your R console.

If you want (or need) to get its development version, you can install it directly from GitHub by executing -devtools::install_github("bodkan/slendr")** via the R -package devtools ( install.packages("devtools")). -In fact, if you decide to try slendr, please make sure to -update it regularly and keep an eye on the changelog on a regular -basis!

+devtools::install_github("bodkan/slendr") via the R package +devtools (you can gen devtools by running +install.packages("devtools")). In fact, if you decide to +try slendr, please make sure to update it regularly and keep an +eye on the changelog on a regular +basis! This is where you can find information about latest bugfixes and +potential breaking changes.

Once you install slendr, calling library(slendr) will check that all software dependencies are available. If they are not, the R package will provide a brief helpful guide on how to resolve potential issues. The rest of this vignette talks about the necessary software dependencies in a bit more detail.

-

Please note that slendr is only supported on macOS -and Linux at the moment. However, because slendr’s -software dependencies are already available on Windows, I hope to make -the R package fully portable as soon as I get access to a Windows -machine to do proper testing on. If you are a Windows user and would -like to help, please get in -touch!

+

Please note that slendr is fully supported only on +macOS and Linux at the moment. That said, there is an +experimental support for running coalescent simulation via +slendr’s Python backend msprime() and for +analyzing tree-sequence outputs using its tskit interface.

Software dependencies @@ -163,7 +163,7 @@

Software dependenciesNote that depending on your use case, not all three sets of dependencies will be necessarily needed. If you’re not going to be running forward spatial simulations, you don’t need SLiM. If you -don’t want to analyze tree sequences in R, you won’t need +don’t want to analyze tree sequences in R, you won’t necesarily need slendr’s Python dependencies.

In this vignette, I will briefly explain how to get all slendr’s software dependencies installed. That said, note that @@ -253,15 +253,12 @@

Python isolated from other Python configurations that are already present on the user’s system, avoiding potential conflicts with the versions of Python and Python modules required by slendr.

-

Not only that, after this dedicated Python environment is created, -calling library(slendr) at any later point will -activate this environment automatically. Therefore, despite -using Python for internal handling of tree-sequence data and coalescent -simulation, no interaction with Python is necessary for working with -slendr in R.

-

You only have to call setup_env() once! -After that, everything will be taken care of by -library(slendr) automatically.

+

Next time you call library(slendr), you will +need to activate this environment automatically by calling +init_env(). If you’re not comfortable with Python +you don’t need to worry beyond calling setup_env() and +init_env(), no interaction with Python is necessary for +working with slendr in R.

Information for Python experts

diff --git a/docs/articles/vignette-01-tutorial.html b/docs/articles/vignette-01-tutorial.html index f6181bc82..cabc29b4e 100644 --- a/docs/articles/vignette-01-tutorial.html +++ b/docs/articles/vignette-01-tutorial.html @@ -319,7 +319,7 @@

Defining smaller 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, 36)) + c(20, 33), c(10, 38), c(-6, 35)) ) europe <- region( "Europe", map, @@ -604,15 +604,13 @@

Defining gene flow events
 gf <- gene_flow(from = eur, to = afr, rate = 0.1, start = 20000, end = 15000)
-
Not a sufficient overlap between population ranges of EUR and AFR
-at time 20000. The required overlap is 0.20 but the current overlap is
-0.000000.
+
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 geneflow without spatial overlap
-between populations.
+ 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.

The error message instructs us to visually verify that this is the case, which can be done by slendr’s plot_map() function and the optional parameter pop_facets = F (which @@ -791,7 +789,7 @@

Running the simulation#> ╔═══════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════╣ -#> ║Trees │ 113║ +#> ║Trees │ 129║ #> ╟───────────────┼───────╢ #> ║Sequence Length│ 100000║ #> ╟───────────────┼───────╢ @@ -804,15 +802,15 @@

Running the simulation#> ╔═══════════╤═════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪═════╪═════════╪════════════╣ -#> ║Edges │18632│582.3 KiB│ No║ +#> ║Edges │18692│584.1 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ -#> ║Individuals│12813│ 1.2 MiB│ Yes║ +#> ║Individuals│12814│ 1.2 MiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ -#> ║Nodes │18324│680.7 KiB│ Yes║ +#> ║Nodes │18348│681.6 KiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Populations│ 6│ 2.6 KiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ diff --git a/docs/articles/vignette-01-tutorial_files/figure-html/plot_afr-1.png b/docs/articles/vignette-01-tutorial_files/figure-html/plot_afr-1.png index 656c6e69b..4097d8625 100644 Binary files a/docs/articles/vignette-01-tutorial_files/figure-html/plot_afr-1.png and b/docs/articles/vignette-01-tutorial_files/figure-html/plot_afr-1.png differ diff --git a/docs/articles/vignette-01-tutorial_files/figure-html/plot_ana-1.png b/docs/articles/vignette-01-tutorial_files/figure-html/plot_ana-1.png index da22d12a3..eea56bc66 100644 Binary files a/docs/articles/vignette-01-tutorial_files/figure-html/plot_ana-1.png and b/docs/articles/vignette-01-tutorial_files/figure-html/plot_ana-1.png differ diff --git a/docs/articles/vignette-01-tutorial_files/figure-html/plot_europe_anatolia-1.png b/docs/articles/vignette-01-tutorial_files/figure-html/plot_europe_anatolia-1.png index 80647a07b..e2ae1684b 100644 Binary files a/docs/articles/vignette-01-tutorial_files/figure-html/plot_europe_anatolia-1.png and b/docs/articles/vignette-01-tutorial_files/figure-html/plot_europe_anatolia-1.png differ diff --git a/docs/articles/vignette-01-tutorial_files/figure-html/plot_maps-1.png b/docs/articles/vignette-01-tutorial_files/figure-html/plot_maps-1.png index ed2bb188e..7e7a47cf6 100644 Binary files a/docs/articles/vignette-01-tutorial_files/figure-html/plot_maps-1.png and b/docs/articles/vignette-01-tutorial_files/figure-html/plot_maps-1.png differ diff --git a/docs/articles/vignette-01-tutorial_files/figure-html/plot_ooa-1.png b/docs/articles/vignette-01-tutorial_files/figure-html/plot_ooa-1.png index a879dfcf2..1c99131d6 100644 Binary files a/docs/articles/vignette-01-tutorial_files/figure-html/plot_ooa-1.png and b/docs/articles/vignette-01-tutorial_files/figure-html/plot_ooa-1.png differ diff --git a/docs/articles/vignette-01-tutorial_files/figure-html/plot_ooa_migration-1.png b/docs/articles/vignette-01-tutorial_files/figure-html/plot_ooa_migration-1.png index 294e03fb3..287f8e744 100644 Binary files a/docs/articles/vignette-01-tutorial_files/figure-html/plot_ooa_migration-1.png and b/docs/articles/vignette-01-tutorial_files/figure-html/plot_ooa_migration-1.png differ diff --git a/docs/articles/vignette-01-tutorial_files/figure-html/plot_yam_migr-1.png b/docs/articles/vignette-01-tutorial_files/figure-html/plot_yam_migr-1.png index 9d05eca2f..78e5ee3e6 100644 Binary files a/docs/articles/vignette-01-tutorial_files/figure-html/plot_yam_migr-1.png and b/docs/articles/vignette-01-tutorial_files/figure-html/plot_yam_migr-1.png differ diff --git a/docs/articles/vignette-02-grid-model.html b/docs/articles/vignette-02-grid-model.html index f8bf7f059..3de1a8cf9 100644 --- a/docs/articles/vignette-02-grid-model.html +++ b/docs/articles/vignette-02-grid-model.html @@ -296,15 +296,15 @@

Simple two-dimensional grid model#> ╔═══════════╤════╤═════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪═════════╪════════════╣ -#> ║Edges │9028│282.1 KiB│ No║ +#> ║Edges │9051│282.9 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ -#> ║Individuals│6293│616.2 KiB│ Yes║ +#> ║Individuals│6295│616.3 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ -#> ║Nodes │9053│336.6 KiB│ Yes║ +#> ║Nodes │9076│337.5 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Populations│ 25│ 5.7 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ diff --git a/docs/articles/vignette-05-tree-sequences.html b/docs/articles/vignette-05-tree-sequences.html index 1c638bd9d..1d611590d 100644 --- a/docs/articles/vignette-05-tree-sequences.html +++ b/docs/articles/vignette-05-tree-sequences.html @@ -351,11 +351,11 @@

Scheduling of sampling events#> -------------------------------------------------- #> msprime command to be executed: #> -#> /Users/mp/Library/r-miniconda-arm64/envs/msprime-1.2.0_tskit-0.5.2_pyslim-1.0/bin/python /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpGU7cGf/file8365758d35e6_introgression/script.py --seed 314159 --model /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpGU7cGf/file8365758d35e6_introgression --output /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpGU7cGf/file8365638bc83a.trees --sequence-length 100000000 --recombination-rate 1e-08 --sampling-schedule /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpGU7cGf/file83657a10c749 --verbose +#> /Users/mp/Library/r-miniconda-arm64/envs/msprime-1.2.0_tskit-0.5.2_pyslim-1.0/bin/python /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpnB8Ity/file4538f484005_introgression/script.py --seed 314159 --model /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpnB8Ity/file4538f484005_introgression --output /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpnB8Ity/file453830c8956d.trees --sequence-length 100000000 --recombination-rate 1e-08 --sampling-schedule /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpnB8Ity/file45385749d718 --verbose #> -------------------------------------------------- #> #> Tree sequence was saved to: -#> /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpGU7cGf/file8365638bc83a.trees +#> /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpnB8Ity/file453830c8956d.trees #> Loading the tree-sequence file...
 ts
@@ -442,7 +442,7 @@

Loading and processin ) output_file

-
#> [1] "/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpGU7cGf/file83656f88b72a"
+
#> [1] "/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpnB8Ity/file45381e38161b"

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-06-locations.html b/docs/articles/vignette-06-locations.html index df341cb77..a2458a19e 100644 --- a/docs/articles/vignette-06-locations.html +++ b/docs/articles/vignette-06-locations.html @@ -168,7 +168,7 @@

Model specificationafrica <- region( "Africa", map, polygon = list(c(-18, 20), c(38, 20), c(30, 33), - c(20, 33), c(10, 38), c(-6, 36)) + c(20, 33), c(10, 38), c(-6, 35)) ) europe <- region( "Europe", map, @@ -242,7 +242,7 @@

Model specification= list(afr, ooa, ehg, eur, ana, yam), gene_flow = gf, generation_time = 30, resolution = 10e3, - competition = 130e3, mating = 100e3, dispersal = 70e3 + competition = 150e3, mating = 120e3, dispersal = 90e3 )

As a sanity check that we defined the demography correctly, you can plot a graph summarizing population divergences and geneflow events by @@ -266,7 +266,7 @@

Scheduling sampling events an
 # one ancient individual every two thousand years
 ancient <- schedule_sampling(model,
-                    times = seq(40000, 1, by = -1000),
+                    times = seq(40000, 1, by = -500),
                     list(ooa, 1), list(ehg, 1), list(eur, 1),
                     list(ana, 1), list(yam, 1))
 
@@ -288,28 +288,28 @@ 

Scheduling sampling events an
#> ╔═════════════════════════╗
 #> ║TreeSequence             ║
 #> ╠═══════════════╤═════════╣
-#> ║Trees          │       68║
+#> ║Trees          │       93║
 #> ╟───────────────┼─────────╢
 #> ║Sequence Length│   100000║
 #> ╟───────────────┼─────────╢
 #> ║Time Units     │    ticks║
 #> ╟───────────────┼─────────╢
-#> ║Sample Nodes   │      250║
+#> ║Sample Nodes   │      432║
 #> ╟───────────────┼─────────╢
-#> ║Total Size     │141.6 KiB║
+#> ║Total Size     │205.9 KiB║
 #> ╚═══════════════╧═════════╝
 #> ╔═══════════╤════╤════════╤════════════╗
 #> ║Table      │Rows│Size    │Has Metadata║
 #> ╠═══════════╪════╪════════╪════════════╣
-#> ║Edges      │ 753│23.5 KiB│          No║
+#> ║Edges      │1213│37.9 KiB│          No║
 #> ╟───────────┼────┼────────┼────────────╢
-#> ║Individuals│ 432│44.0 KiB│         Yes║
+#> ║Individuals│ 724│72.5 KiB│         Yes║
 #> ╟───────────┼────┼────────┼────────────╢
 #> ║Migrations │   0│ 8 Bytes│          No║
 #> ╟───────────┼────┼────────┼────────────╢
 #> ║Mutations  │   0│ 1.2 KiB│          No║
 #> ╟───────────┼────┼────────┼────────────╢
-#> ║Nodes      │ 559│21.4 KiB│         Yes║
+#> ║Nodes      │ 944│35.7 KiB│         Yes║
 #> ╟───────────┼────┼────────┼────────────╢
 #> ║Populations│   7│ 2.7 KiB│         Yes║
 #> ╟───────────┼────┼────────┼────────────╢
@@ -360,40 +360,40 @@ 

Extracting spatial tree se #> #> summary of the table data contents: #> AFR - 5 'sampled', 5 'remembered', 5 'retained', 5 'alive' individuals -#> EUR - 54 'sampled', 54 'remembered', 30 'retained', 30 'alive' individuals -#> OOA - 16 'sampled', 16 'remembered', NA 'retained', 0 'alive' individuals -#> EHG - 22 'sampled', 22 'remembered', NA 'retained', 0 'alive' individuals -#> ANA - 24 'sampled', 24 'remembered', NA 'retained', 0 'alive' individuals -#> YAM - 4 'sampled', 4 'remembered', NA 'retained', 0 'alive' individuals +#> EUR - 79 'sampled', 79 'remembered', 30 'retained', 30 'alive' individuals +#> OOA - 31 'sampled', 31 'remembered', NA 'retained', 0 'alive' individuals +#> ANA - 48 'sampled', 48 'remembered', NA 'retained', 0 'alive' individuals +#> EHG - 44 'sampled', 44 'remembered', NA 'retained', 0 'alive' individuals +#> YAM - 9 'sampled', 9 'remembered', NA 'retained', 0 'alive' individuals #> #> total: -#> - 125 'sampled' individuals -#> - 125 'remembered' individuals -#> - 307 'retained' individuals +#> - 216 'sampled' individuals +#> - 216 'remembered' individuals +#> - 508 'retained' individuals #> - 35 'alive' individuals #> --------------------- #> oldest sampled individual: 40000 time units 'before present' #> youngest sampled individual: 0 time units 'before present' #> -#> oldest node: 252034.5 time units 'before present' +#> oldest node: 252014.9 time units 'before present' #> youngest node: 0 time units 'before present' #> --------------------- #> overview of the underlying sf object: #> -#> # A tibble: 559 × 13 +#> # A tibble: 944 × 13 #> name pop node_id time time_ts…¹ location sampled remembered #> <chr> <fct> <int> <dbl> <dbl[1d]> <POINT [m]> <lgl> <lgl> -#> 1 AFR_1 AFR 180 0 0 (4108201 1075606) TRUE TRUE -#> 2 AFR_1 AFR 181 0 0 (4108201 1075606) TRUE TRUE -#> 3 AFR_2 AFR 182 0 0 (3065555 920380.9) TRUE TRUE -#> 4 AFR_2 AFR 183 0 0 (3065555 920380.9) TRUE TRUE -#> 5 AFR_3 AFR 184 0 0 (3130774 1302346) TRUE TRUE -#> 6 AFR_3 AFR 185 0 0 (3130774 1302346) TRUE TRUE -#> 7 AFR_4 AFR 186 0 0 (4260418 721906.3) TRUE TRUE -#> 8 AFR_4 AFR 187 0 0 (4260418 721906.3) TRUE TRUE -#> 9 AFR_5 AFR 188 0 0 (3660948 677070.9) TRUE TRUE -#> 10 AFR_5 AFR 189 0 0 (3660948 677070.9) TRUE TRUE -#> # … with 549 more rows, 5 more variables: retained <lgl>, alive <lgl>, +#> 1 AFR_1 AFR 362 0 0 (3072714 315424) TRUE TRUE +#> 2 AFR_1 AFR 363 0 0 (3072714 315424) TRUE TRUE +#> 3 AFR_2 AFR 364 0 0 (2898146 1202818) TRUE TRUE +#> 4 AFR_2 AFR 365 0 0 (2898146 1202818) TRUE TRUE +#> 5 AFR_3 AFR 366 0 0 (3466565 1087738) TRUE TRUE +#> 6 AFR_3 AFR 367 0 0 (3466565 1087738) TRUE TRUE +#> 7 AFR_4 AFR 368 0 0 (3030706 587947.3) TRUE TRUE +#> 8 AFR_4 AFR 369 0 0 (3030706 587947.3) TRUE TRUE +#> 9 AFR_5 AFR 370 0 0 (4464229 538126) TRUE TRUE +#> 10 AFR_5 AFR 371 0 0 (4464229 538126) TRUE TRUE +#> # … with 934 more rows, 5 more variables: retained <lgl>, alive <lgl>, #> # pedigree_id <dbl>, ind_id <dbl>, pop_id <int>, and abbreviated variable #> # name ¹​time_tskit

In the first part of the summary, we see how many individuals @@ -519,10 +519,10 @@

Extracting spatio-te sequence (it is possible to recover ancestral relationships for multiple samples at once too):

-ind <- "EUR_42"
+ind <- "EUR_67"
 
 lineages <- ts_ancestors(ts, ind, verbose = TRUE)
-
#> Collecting ancestors of EUR_42 [1/1]...
+
#> Collecting ancestors of EUR_67 [1/1]...
#> 
 #> Generating data about spatial relationships of nodes...

The function starts at a given node (or, if a name of a sampled @@ -536,26 +536,26 @@

Extracting spatio-te node or individual (in our example, "EUR_25"):

 lineages
-
#> Simple feature collection with 98 features and 12 fields
+
#> Simple feature collection with 154 features and 12 fields
 #> Active geometry column: connection
 #> Geometry type: LINESTRING
 #> Dimension:     XY
-#> Bounding box:  xmin: 3018749 ymin: 363440.4 xmax: 8484441 ymax: 4192932
+#> Bounding box:  xmin: 2721964 ymin: 546923.8 xmax: 8458020 ymax: 4686009
 #> Projected CRS: ETRS89-extended / LAEA Europe
-#> # A tibble: 98 × 15
+#> # A tibble: 154 × 15
 #>    name   pop   node_id level child_id parent_id child…¹ paren…² child…³ paren…⁴
 #>  * <chr>  <fct>   <int> <fct>    <int>     <int>   <dbl>   <dbl> <fct>   <fct>  
-#>  1 EUR_42 EUR       224 1          224       264       0    1030 EUR     EUR    
-#>  2 EUR_42 EUR       224 2          264       273    1030    1630 EUR     EUR    
-#>  3 EUR_42 EUR       224 3          273       286    1630    3400 EUR     EUR    
-#>  4 EUR_42 EUR       224 4          286       305    3400    7750 EUR     ANA    
-#>  5 EUR_42 EUR       224 5          305       309    7750    8110 ANA     ANA    
-#>  6 EUR_42 EUR       224 6          309       312    8110    8350 ANA     ANA    
-#>  7 EUR_42 EUR       224 7          312       457    8350   27340 ANA     ANA    
-#>  8 EUR_42 EUR       224 7          312       462    8350   27790 ANA     ANA    
-#>  9 EUR_42 EUR       224 8          457       480   27340   28600 ANA     OOA    
-#> 10 EUR_42 EUR       224 8          462       490   27790   29110 ANA     OOA    
-#> # … with 88 more rows, 5 more variables: child_location <POINT [m]>,
+#>  1 EUR_67 EUR       406 1          406       450       0    1810 EUR     EUR    
+#>  2 EUR_67 EUR       406 1          406       525       0    8770 EUR     ANA    
+#>  3 EUR_67 EUR       406 2          450       525    1810    8770 EUR     ANA    
+#>  4 EUR_67 EUR       406 2          525       543    8770    9760 ANA     ANA    
+#>  5 EUR_67 EUR       406 3          543       715    9760   24130 ANA     ANA    
+#>  6 EUR_67 EUR       406 4          715       769   24130   26830 ANA     ANA    
+#>  7 EUR_67 EUR       406 4          715       774   24130   26950 ANA     ANA    
+#>  8 EUR_67 EUR       406 4          715       787   24130   27760 ANA     ANA    
+#>  9 EUR_67 EUR       406 5          769       787   26830   27760 ANA     ANA    
+#> 10 EUR_67 EUR       406 5          774       811   26950   28240 ANA     OOA    
+#> # … with 144 more rows, 5 more variables: child_location <POINT [m]>,
 #> #   parent_location <POINT [m]>, connection <LINESTRING [m]>, left_pos <dbl>,
 #> #   right_pos <dbl>, and abbreviated variable names ¹​child_time, ²​parent_time,
 #> #   ³​child_pop, ⁴​parent_pop
@@ -580,17 +580,18 @@

Extracting spatio-te filter function from the R package dplyr:

 filter(lineages, level == 1)
-
#> Simple feature collection with 2 features and 12 fields
+
#> Simple feature collection with 3 features and 12 fields
 #> Active geometry column: connection
 #> Geometry type: LINESTRING
 #> Dimension:     XY
-#> Bounding box:  xmin: 4739575 ymin: 2748103 xmax: 5689236 ymax: 3187720
+#> Bounding box:  xmin: 5202360 ymin: 2284049 xmax: 5564577 ymax: 2754068
 #> Projected CRS: ETRS89-extended / LAEA Europe
-#> # A tibble: 2 × 15
+#> # A tibble: 3 × 15
 #>   name   pop   node_id level child_id parent_id child_…¹ paren…² child…³ paren…⁴
 #> * <chr>  <fct>   <int> <fct>    <int>     <int>    <dbl>   <dbl> <fct>   <fct>  
-#> 1 EUR_42 EUR       224 1          224       264        0    1030 EUR     EUR    
-#> 2 EUR_42 EUR       225 1          225       279        0    2200 EUR     EUR    
+#> 1 EUR_67 EUR       406 1          406       450        0    1810 EUR     EUR    
+#> 2 EUR_67 EUR       406 1          406       525        0    8770 EUR     ANA    
+#> 3 EUR_67 EUR       407 1          407       449        0    1810 EUR     EUR    
 #> # … with 5 more variables: child_location <POINT [m]>,
 #> #   parent_location <POINT [m]>, connection <LINESTRING [m]>, left_pos <dbl>,
 #> #   right_pos <dbl>, and abbreviated variable names ¹​child_time, ²​parent_time,
@@ -604,20 +605,35 @@ 

Extracting spatio-te connection). We can plot all three spatial features (two points and a line) individually on a map:

-level1_branches <- ts_ancestors(ts, "EUR_3") %>% filter(level == 1)
+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[, ]$parent_location, shape = 20, color = level1_branches[, ]$node_id) +
   geom_sf(data = level1_branches[, ]$connection, linetype = 3) +
+  geom_sf(data = level1_branches[, ]$parent_location, shape = 20, color = "blue") +
   theme_bw() +
-  scale_color_manual(values = c("darkblue", "lightblue")) +
   ggtitle("Parent nodes (blue) of a focal individual (red)")

In the figure above we can see the red focal node and its immediate parents in the tree sequence genealogy (in the coalescent sense, not -immediate parents of that individual!).

+immediate parents of that individual!). In case you’re surprised to see +more than two parents, recall that recombination events make the history +encoded by a sample more complicated as it can involve more ancestors as +we “move up” a tree from a sample, not just two ancestors. Looking at +our example in more detail, we can see that one node (chromosome) of the +individual “EUR_67” has two ancestors, each covering a portion of that +individuals chromosome, with the other chromosome being covered by a +single ancestor (columns left_pos and +right_pos):

+
+as_tibble(level1_branches)[, c("name", "node_id", "child_id", "parent_id", "left_pos", "right_pos")]
+
#> # A tibble: 3 × 6
+#>   name   node_id child_id parent_id left_pos right_pos
+#>   <chr>    <int>    <int>     <int>    <dbl>     <dbl>
+#> 1 EUR_67     406      406       450        0      7084
+#> 2 EUR_67     406      406       525     7084    100000
+#> 3 EUR_67     407      407       449        0    100000

A more convenient way to do this analysis is a companion function to ts_ancestors() called plot_ancestors(). This function accepts an sf object with the spatial branching @@ -630,17 +646,18 @@

Extracting spatio-te -
+
 ggplot() +
   geom_sf(data = map) +
-  geom_sf(data = lineages, size = 0.5, aes(alpha = parent_time)) +
+  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)
+ facet_grid(. ~ node_id) + + ggtitle("Ancestry encoded by two nodes (chromosomes) of EUR_67")

You can compare this result to the animation which recapitulates the simulation, presented in the first @@ -668,40 +685,41 @@

Extracting spatio-te Anatolians split from the ancestral population of Eurasians in Anatolia and then expanded in a wave to Europe. We have sampled the following individuals:

-
+
 ts_samples(ts) %>% filter(pop == "ANA")
-
#> # A tibble: 24 × 3
+
#> # A tibble: 48 × 3
 #>    name    time pop  
 #>    <chr>  <int> <chr>
-#>  1 ANA_1  27000 ANA  
-#>  2 ANA_2  26000 ANA  
-#>  3 ANA_3  25000 ANA  
-#>  4 ANA_4  24000 ANA  
-#>  5 ANA_5  23000 ANA  
-#>  6 ANA_6  22000 ANA  
-#>  7 ANA_7  21000 ANA  
-#>  8 ANA_8  20000 ANA  
-#>  9 ANA_9  19000 ANA  
-#> 10 ANA_10 18000 ANA  
-#> # … with 14 more rows
+#> 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 +#> # … with 38 more rows

Can we see a hint of the spatial dynamics of Anatolians in the spatio-temporal distribution of ancestral node locations of one of the sampled individuals? Let’s pick the last individual and immediately plot its spatial ancestry tidyverse-style using the pipe operator %>%:

-
-lineages <- ts_ancestors(ts, "ANA_24")
+
+lineages <- ts_ancestors(ts, "ANA_45")
 
 ggplot() +
   geom_sf(data = map) +
-  geom_sf(data = lineages, size = 0.5, aes(alpha = parent_time)) +
+  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_24"), size = 3) +
+  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)
+ facet_grid(. ~ node_id) + + ggtitle("Ancestry encoded by two nodes (chromosomes) of ANA_45")

As we might expect given the late age of the sample, its position in the map above (red crossed circle) is not in Anatolia but in Europe @@ -720,39 +738,39 @@

Calcula

Lets take one more look at the sf object with the locations and times of ancestral nodes of sampled individuals, focusing on the following subset of columns:

-
+
 lineages <-
   ts_samples(ts) %>%
   pull(name) %>%
   ts_ancestors(ts, x = .)
 
 select(lineages, connection, child_time, parent_time)
-
#> Simple feature collection with 9804 features and 2 fields
+
#> Simple feature collection with 23425 features and 2 fields
 #> Geometry type: LINESTRING
 #> Dimension:     XY
-#> Bounding box:  xmin: 2617353 ymin: 363440.4 xmax: 8621288 ymax: 4904200
+#> Bounding box:  xmin: 2721964 ymin: 315424 xmax: 8598650 ymax: 4914514
 #> Projected CRS: ETRS89-extended / LAEA Europe
-#> # A tibble: 9,804 × 3
-#>                              connection child_time parent_time
-#>                        <LINESTRING [m]>      <dbl>       <dbl>
-#>  1   (8173271 3201987, 8085004 3422948)      40000       40240
-#>  2   (8085004 3422948, 8188064 3167335)      40240       40690
-#>  3   (8188064 3167335, 8224089 2883400)      40690       41020
-#>  4   (8224089 2883400, 8256321 2822963)      41020       41110
-#>  5   (8256321 2822963, 7805879 1633736)      41110       45520
-#>  6  (7805879 1633736, 3510351 681724.1)      45520       56950
-#>  7  (7805879 1633736, 3839546 378635.3)      45520       59410
-#>  8  (7805879 1633736, 3143416 598468.7)      45520       87010
-#>  9 (3510351 681724.1, 3839546 378635.3)      56950       59410
-#> 10 (3839546 378635.3, 4530812 668950.4)      59410       95980
-#> # … with 9,794 more rows
+#> # A tibble: 23,425 × 3 +#> connection child_time parent_time +#> <LINESTRING [m]> <dbl> <dbl> +#> 1 (8103641 3334456, 7956278 3180199) 40000 40330 +#> 2 (7956278 3180199, 8036310 1911729) 40330 43900 +#> 3 (7956278 3180199, 8031610 2059804) 40330 44020 +#> 4 (8036310 1911729, 8031610 2059804) 43900 44020 +#> 5 (8031610 2059804, 7687313 1689532) 44020 45970 +#> 6 (7687313 1689532, 7175192 1476174) 45970 47740 +#> 7 (7687313 1689532, 6867500 1338048) 45970 48730 +#> 8 (7175192 1476174, 6867500 1338048) 47740 48730 +#> 9 (6867500 1338048, 6754277 1091742) 48730 49810 +#> 10 (6754277 1091742, 3520987 724306) 49810 52900 +#> # … with 23,415 more rows

We can use standard dplyr table manipulation functions to compute the distances between connected notes and the times that separate them (i.e. branch lengths in the traditional phylogenetic sense). We can then use those two quantities to compute how fast (if any at all) was the movement between ancestral individuals in different time periods of the history of a sample:

-
+
 distances <- lineages %>%
   mutate(branch_length = abs(parent_time - child_time) / model$generation_time,
          distance = sf::st_length(connection) %>% units::set_units(km) %>% as.numeric(),
@@ -763,7 +781,7 @@ 

Calcula

Let’s also convert the data (absolute distances or distance per generation – i.e., the “speed”) into a long format for easier plotting side by side:

-
+
 distances_long <- distances %>%
   filter(child_time < 60000) %>%
   filter(!pop %in% c("AFR", "OOA")) %>%
@@ -776,9 +794,8 @@ 

Calcula

Let’s try to summarise the information about distances “traveled” by nodes in different time period by fitting a spline (rather than plotting the raw data with individual nodes):

-
+
 distances_long %>%
-  dplyr::filter(child_pop != "AFR") %>%
   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) +
diff --git a/docs/articles/vignette-06-locations_files/figure-html/level1_branches-1.png b/docs/articles/vignette-06-locations_files/figure-html/level1_branches-1.png
index 13b02885d..db4ba2e87 100644
Binary files a/docs/articles/vignette-06-locations_files/figure-html/level1_branches-1.png and b/docs/articles/vignette-06-locations_files/figure-html/level1_branches-1.png differ
diff --git a/docs/articles/vignette-06-locations_files/figure-html/map_epochs-1.png b/docs/articles/vignette-06-locations_files/figure-html/map_epochs-1.png
index abc3850df..d089076b3 100644
Binary files a/docs/articles/vignette-06-locations_files/figure-html/map_epochs-1.png and b/docs/articles/vignette-06-locations_files/figure-html/map_epochs-1.png differ
diff --git a/docs/articles/vignette-06-locations_files/figure-html/plot_ancestors_levels_ana-1.png b/docs/articles/vignette-06-locations_files/figure-html/plot_ancestors_levels_ana-1.png
index e84d32a1f..8e713132e 100644
Binary files a/docs/articles/vignette-06-locations_files/figure-html/plot_ancestors_levels_ana-1.png and b/docs/articles/vignette-06-locations_files/figure-html/plot_ancestors_levels_ana-1.png differ
diff --git a/docs/articles/vignette-06-locations_files/figure-html/plot_ancestors_time-1.png b/docs/articles/vignette-06-locations_files/figure-html/plot_ancestors_time-1.png
index 59c338102..e92bb4d22 100644
Binary files a/docs/articles/vignette-06-locations_files/figure-html/plot_ancestors_time-1.png and b/docs/articles/vignette-06-locations_files/figure-html/plot_ancestors_time-1.png differ
diff --git a/docs/articles/vignette-06-locations_files/figure-html/slendr_map_ts-1.png b/docs/articles/vignette-06-locations_files/figure-html/slendr_map_ts-1.png
index 06d7865d8..a5fd57a02 100644
Binary files a/docs/articles/vignette-06-locations_files/figure-html/slendr_map_ts-1.png and b/docs/articles/vignette-06-locations_files/figure-html/slendr_map_ts-1.png differ
diff --git a/docs/articles/vignette-06-locations_files/figure-html/smooth_distance_fits-1.png b/docs/articles/vignette-06-locations_files/figure-html/smooth_distance_fits-1.png
index ecca26813..5d2fd0458 100644
Binary files a/docs/articles/vignette-06-locations_files/figure-html/smooth_distance_fits-1.png and b/docs/articles/vignette-06-locations_files/figure-html/smooth_distance_fits-1.png differ
diff --git a/docs/articles/vignette-06-locations_files/figure-html/spatial_maps-1.png b/docs/articles/vignette-06-locations_files/figure-html/spatial_maps-1.png
index 92c98e91f..509b55c2c 100644
Binary files a/docs/articles/vignette-06-locations_files/figure-html/spatial_maps-1.png and b/docs/articles/vignette-06-locations_files/figure-html/spatial_maps-1.png differ
diff --git a/docs/articles/vignette-08-nonslendr-tskit.html b/docs/articles/vignette-08-nonslendr-tskit.html
index 50e0bb624..d4313bbbc 100644
--- a/docs/articles/vignette-08-nonslendr-tskit.html
+++ b/docs/articles/vignette-08-nonslendr-tskit.html
@@ -188,7 +188,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 @@ -423,7 +423,7 @@

Spatial SLiM (non-slendr) tree s } 10000 late() { - sim.treeSeqOutput("/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpYMHeKD/file88514d3eba6d"); + sim.treeSeqOutput("/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//Rtmp3Qwj6j/file4ac535ddfbfa"); }

We can then load and simplify the output tree sequence in just as we did above in this vignette (or anywhere in the slendr diff --git a/docs/articles/vignette-09-paper.html b/docs/articles/vignette-09-paper.html index 1609928ab..b96a7db53 100644 --- a/docs/articles/vignette-09-paper.html +++ b/docs/articles/vignette-09-paper.html @@ -355,9 +355,9 @@

Example 3 (Figure 4)Script from panel A

-map <- world(xrange = c(-15, 60), yrange = c(20, 65), crs = 3035)
+map <- world(xrange = c(-13, 70), yrange = c(18, 65), crs = 3035)
 #> OGR data source with driver: ESRI Shapefile 
-#> Source: "/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpgCqaBQ/naturalearth", layer: "ne_110m_land"
+#> Source: "/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpUidrxk/naturalearth", layer: "ne_110m_land"
 #> with 127 features
 #> It has 3 fields
 
@@ -387,9 +387,9 @@ 

Script from panel Aooa_trajectory <- list(c(40, 30), c(50, 30), c(60, 40), c(45, 55))

-map <- world(xrange = c(-15, 60), yrange = c(20, 65), crs = 3035)
+map <- world(xrange = c(-13, 70), yrange = c(18, 65), crs = 3035)
 #> OGR data source with driver: ESRI Shapefile 
-#> Source: "/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpgCqaBQ/naturalearth", layer: "ne_110m_land"
+#> Source: "/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpUidrxk/naturalearth", layer: "ne_110m_land"
 #> with 127 features
 #> It has 3 fields
 
@@ -431,8 +431,7 @@ 

Script from panel Amodel <- compile_model( populations = list(ooa, ehg, eur, ana, yam), gene_flow = gf, generation_time = 30, resolution = 10e3, - competition = 130e3, mating = 100e3, - dispersal = 70e3, + competition = 150e3, mating = 120e3, dispersal = 90e3 ) samples <- schedule_sampling( @@ -468,45 +467,6 @@

Plotting code p_ex3

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

@@ -516,18 +476,17 @@

Example 4 (Figure 5)Script from panel A

-ts_small <- ts_simplify(ts, c("EUR_581", "ANA_120", "EHG_440",
-                              "EUR_597", "YAM_59"))
+ts_small <- ts_simplify(ts, simplify_to = c("EUR_578", "YAM_75", "ANA_163", "EHG_208"))
 
-tree <- ts_phylo(ts_small, i = 10)
+tree <- ts_phylo(ts_small, i = 20)
 #> Starting checking the validity of tree...
-#> Found number of tips: n = 10 
-#> Found number of nodes: m = 9 
+#> 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_581")
+ancestors <- ts_ancestors(ts, "EUR_578")

Plotting code @@ -565,7 +524,7 @@

Plotting code format(abs(x) / 1000, ..., scientific = FALSE, trim = TRUE) } -highlight_nodes <- as_tibble(nodes) %>% dplyr::filter(name == "EUR_581") %>% .$phylo_id +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, @@ -577,8 +536,8 @@

Plotting code theme_tree2() + theme(legend.position = "none") + xlab("time before present [thousand years ago]") + - scale_x_continuous(limits = c(-120000, 31000), labels = abs_comma, - breaks = -c(120, 100, 80, 60, 40, 20, 0) * 1000) + 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) @@ -594,8 +553,6 @@

Plotting codep_map <- ggplot() + geom_sf(data = map) + geom_sf(data = edges, aes(color = parent_pop), size = 0.5) + - geom_sf(data = filter(nodes, is.na(name)), - aes(color = pop, shape = pop), size = 5) + geom_sf_label(data = nodes[!nodes$sampled, ], aes(label = node_id, fill = pop), size = 3) + geom_sf_label(data = nodes[nodes$sampled, ], @@ -604,23 +561,25 @@

Plotting code 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", shape = "none") + + 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_581 (node 10)", "EUR_581 (node 11)"), + 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, aes(alpha = parent_time)) + + 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_581"), size = 3) + + geom_sf(data = filter(ts_nodes(ts), name == "EUR_578"), size = 3) + coord_sf(expand = 0) + labs(x = "longitude", y = "latitude") + theme_bw() + @@ -641,7 +600,7 @@

Plotting code) p_ex4

-

+

diff --git a/docs/reference/region.html b/docs/reference/region.html index ffaca1be0..c359366d2 100644 --- a/docs/reference/region.html +++ b/docs/reference/region.html @@ -155,7 +155,7 @@

Examples real_map <- world(xrange = c(-15, 40), yrange = c(30, 60), crs = "EPSG:3035") #> OGR data source with driver: ESRI Shapefile -#> Source: "/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpdZ3DXs/naturalearth", layer: "ne_110m_land" +#> Source: "/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpW5oB0n/naturalearth", layer: "ne_110m_land" #> with 127 features #> It has 3 fields diff --git a/docs/reference/slim.html b/docs/reference/slim.html index 4697d28da..d9bbba000 100644 --- a/docs/reference/slim.html +++ b/docs/reference/slim.html @@ -248,20 +248,20 @@

Examples#> ╟───────────────┼─────────╢ #> ║Sample Nodes │ 1046║ #> ╟───────────────┼─────────╢ -#> ║Total Size │317.6 KiB║ +#> ║Total Size │319.5 KiB║ #> ╚═══════════════╧═════════╝ #> ╔═══════════╤════╤═════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪═════════╪════════════╣ -#> ║Edges │1907│ 59.6 KiB│ No║ +#> ║Edges │1914│ 59.8 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ -#> ║Individuals│1330│131.7 KiB│ Yes║ +#> ║Individuals│1344│133.0 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ -#> ║Nodes │1908│ 71.5 KiB│ Yes║ +#> ║Nodes │1915│ 71.7 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Populations│ 4│ 2.5 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ diff --git a/docs/reference/world.html b/docs/reference/world.html index 98d0c67cd..0a8eda558 100644 --- a/docs/reference/world.html +++ b/docs/reference/world.html @@ -166,7 +166,7 @@

Examples real_map <- world(xrange = c(-15, 40), yrange = c(30, 60), crs = "EPSG:3035") #> OGR data source with driver: ESRI Shapefile -#> Source: "/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpdZ3DXs/naturalearth", layer: "ne_110m_land" +#> Source: "/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpW5oB0n/naturalearth", layer: "ne_110m_land" #> with 127 features #> It has 3 fields diff --git a/docs/search.json b/docs/search.json index bca9e80d1..73d58a18a 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 ( install.packages(\"devtools\")). fact, decide try slendr, please make sure update regularly keep eye changelog regular basis! 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 supported macOS Linux moment. However, slendr’s software dependencies already available Windows, hope make R package fully portable soon get access Windows machine proper testing . Windows user like help, please get touch!","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). 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. don’t want analyze tree sequences R, won’t need slendr’s Python dependencies. 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","dir":"Articles","previous_headings":"Software dependencies","what":"sf","title":"Installation instructions","text":"R package sf heart geospatial data analysis R. available CRAN can installed major platforms executing install.packages(\"sf\") R session. install slendr (see top page), installation procedure automatically install sf . normal circumstances, worry sf . 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 trouble installing slendr R session, ’s worth testing whether can run install.packages(\"sf\") successfully load library(sf). nearly 100% cases test cases, slendr installation failed, due problem missing dependency sf. ’re problems, look help .","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"macos","dir":"Articles","previous_headings":"Software dependencies > sf","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":"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 . 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. 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, truly. 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. , dedicated Python environment created, calling library(slendr) later point activate environment automatically. Therefore, despite using Python internal handling tree-sequence data coalescent simulation, interaction Python necessary working slendr R. call setup_env() ! , everything taken care library(slendr) automatically.","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 hack simply call Python command-line background, implemented using R package reticulate. embeds Python session within 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 R package finally lands official CRAN repository. 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-00-installation.html","id":"renv","dir":"Articles","previous_headings":"","what":"renv","title":"Installation instructions","text":"TODO: Advertise renv solution managing reproducible environments R packages.","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) #> ======================================================================= #> NOTE: Due to frequent issues with some user's Python setups, slendr no #> longer activates its Python environment automatically upon calling #> library(slendr). #> #> In order to use slendr's msprime back end or its tree-sequence #> functionality, users now must activate slendr's Python environments #> manually by calling init_env(). #> #> This inconvenience is a compromise in order to help novice users avoid #> having to debug very technical, low-level Python-specific issues. This #> note will be removed in a future version of 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, 36)) ) 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\", parent = \"ancestor\", 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) Not a sufficient overlap between population ranges of EUR and AFR at time 20000. The required overlap is 0.20 but the current overlap is 0.000000. 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 geneflow 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 pop_id #> 1 AFR ancestor 3000 1 52000 -1 -1 0 #> 2 OOA AFR 500 34 51000 901 25000 1 #> 3 EHG OOA 1000 801 28000 1534 6000 2 #> 4 ANA OOA 3000 801 28000 1601 4000 3 #> 5 EUR EHG 2000 901 25000 -1 -1 4 #> 6 YAM EHG 500 1501 7000 1651 2500 5 #> parent_id #> 1 -1 #> 2 0 #> 3 1 #> 4 1 #> 5 2 #> 6 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)"},{"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. Graph demographic history (sometimes called “admixture graph”) Interactive explorer spatial dynamics","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 │ 113║ #> ╟───────────────┼───────╢ #> ║Sequence Length│ 100000║ #> ╟───────────────┼───────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼───────╢ #> ║Sample Nodes │ 10000║ #> ╟───────────────┼───────╢ #> ║Total Size │2.6 MiB║ #> ╚═══════════════╧═══════╝ #> ╔═══════════╤═════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪═════╪═════════╪════════════╣ #> ║Edges │18632│582.3 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Individuals│12813│ 1.2 MiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Nodes │18324│680.7 KiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Populations│ 6│ 2.6 KiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Provenances│ 1│ 33.6 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) #> ======================================================================= #> NOTE: Due to frequent issues with some user's Python setups, slendr no #> longer activates its Python environment automatically upon calling #> library(slendr). #> #> In order to use slendr's msprime back end or its tree-sequence #> functionality, users now must activate slendr's Python environments #> manually by calling init_env(). #> #> This inconvenience is a compromise in order to help novice users avoid #> having to debug very technical, low-level Python-specific issues. This #> note will be removed in a future version of 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 │9028│282.1 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Individuals│6293│616.2 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Nodes │9053│336.6 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Populations│ 25│ 5.7 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Provenances│ 1│ 33.5 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-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/msprime-1.2.0_tskit-0.5.2_pyslim-1.0/bin/python #> Python version: 3.8.15 | packaged by conda-forge | (default, Nov 22 2022, 08:49:06) [Clang 14.0.6 ] #> #> slendr requirements: #> - tskit: version 0.5.2 ✓ #> - msprime: version 1.2.0 ✓ #> - pyslim: version 1.0 ✓"},{"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 10319 EUR 1 NA NA NA NA #> 2 11187 EUR 1 NA NA NA NA #> 3 11395 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 14774 EUR 1 NA NA NA NA #> 10 16361 EUR 1 NA NA NA NA #> # … with 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 to be executed: #> #> /Users/mp/Library/r-miniconda-arm64/envs/msprime-1.2.0_tskit-0.5.2_pyslim-1.0/bin/python /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpGU7cGf/file8365758d35e6_introgression/script.py --seed 314159 --model /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpGU7cGf/file8365758d35e6_introgression --output /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpGU7cGf/file8365638bc83a.trees --sequence-length 100000000 --recombination-rate 1e-08 --sampling-schedule /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpGU7cGf/file83657a10c749 --verbose #> -------------------------------------------------- #> #> Tree sequence was saved to: #> /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpGU7cGf/file8365638bc83a.trees #> Loading the tree-sequence file... ts #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 237352║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 116║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 36.4 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │858165│ 26.2 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 58│ 1.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │138217│ 3.7 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. Still, dealing SLiM tree sequence, case vignetted, one go, specifying recapitate = TRUE call ts_load() specifying couple additional arguments required recapitation (see pyslim documentation recapitation section detail). 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/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpGU7cGf/file83656f88b72a\" ts <- ts_load(output_file, model) ts #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 237352║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 116║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 36.4 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │858165│ 26.2 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 58│ 1.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │138217│ 3.7 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 1│ 7.0 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧══════╧═════════╧════════════╝ ts_simplify(ts) #> Warning: If you want to simplify an msprime tree sequence, you must specify #> the names of individuals to simplify to via the `simplify_to = ` #> function argument. #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 237352║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 116║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 36.4 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │858165│ 26.2 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 58│ 1.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │138217│ 3.7 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 1│ 7.0 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 │ 131740║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 14║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 18.8 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │436892│ 13.3 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 7│220 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │ 78560│ 2.1 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 2│ 7.5 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 │ 237352║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 116║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 73.3 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │858165│ 26.2 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 58│ 1.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │623549│ 22.0 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │138217│ 3.7 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 2│ 7.7 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │621652│ 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) #> 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: #> 76943, 70, 1667, 3512, 7999, 11522, ... #> #> Rooted; includes branch lengths. library(ggtree) #> ggtree v3.6.2 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\" \"coiterate\" #> [11] \"count_topologies\" \"decapitate\" #> [13] \"delete_intervals\" \"delete_sites\" #> [15] \"diffs\" \"discrete_genome\" #> [17] \"discrete_time\" \"divergence\" #> [19] \"diversity\" \"draw_svg\" #> [21] \"draw_text\" \"dump\" #> [23] \"dump_tables\" \"dump_text\" #> [25] \"edge\" \"edge_diffs\" #> [27] \"edges\" \"edges_child\" #> [29] \"edges_left\" \"edges_parent\" #> [31] \"edges_right\" \"edgesets\" #> [33] \"equals\" \"f2\" #> [35] \"f3\" \"f4\" #> [37] \"file_uuid\" \"first\" #> [39] \"Fst\" \"genealogical_nearest_neighbours\" #> [41] \"general_stat\" \"genetic_relatedness\" #> [43] \"genotype_matrix\" \"get_ll_tree_sequence\" #> [45] \"get_num_mutations\" \"get_num_nodes\" #> [47] \"get_num_records\" \"get_num_sites\" #> [49] \"get_num_trees\" \"get_pairwise_diversity\" #> [51] \"get_population\" \"get_sample_size\" #> [53] \"get_samples\" \"get_sequence_length\" #> [55] \"get_time\" \"haplotypes\" #> [57] \"has_reference_sequence\" \"ibd_segments\" #> [59] \"indexes_edge_insertion_order\" \"indexes_edge_removal_order\" #> [61] \"individual\" \"individual_locations\" #> [63] \"individual_populations\" \"individual_times\" #> [65] \"individuals\" \"individuals_flags\" #> [67] \"individuals_location\" \"individuals_population\" #> [69] \"individuals_time\" \"kc_distance\" #> [71] \"keep_intervals\" \"last\" #> [73] \"ll_tree_sequence\" \"load\" #> [75] \"load_tables\" \"ltrim\" #> [77] \"max_root_time\" \"mean_descendants\" #> [79] \"metadata\" \"metadata_schema\" #> [81] \"migration\" \"migrations\" #> [83] \"migrations_dest\" \"migrations_left\" #> [85] \"migrations_node\" \"migrations_right\" #> [87] \"migrations_source\" \"migrations_time\" #> [89] \"mutation\" \"mutations\" #> [91] \"mutations_node\" \"mutations_parent\" #> [93] \"mutations_site\" \"mutations_time\" #> [95] \"nbytes\" \"newick_trees\" #> [97] \"node\" \"nodes\" #> [99] \"nodes_flags\" \"nodes_individual\" #> [101] \"nodes_population\" \"nodes_time\" #> [103] \"num_edges\" \"num_individuals\" #> [105] \"num_migrations\" \"num_mutations\" #> [107] \"num_nodes\" \"num_populations\" #> [109] \"num_provenances\" \"num_samples\" #> [111] \"num_sites\" \"num_trees\" #> [113] \"pairwise_diversity\" \"parse_windows\" #> [115] \"population\" \"populations\" #> [117] \"provenance\" \"provenances\" #> [119] \"records\" \"reference_sequence\" #> [121] \"rtrim\" \"sample_count_stat\" #> [123] \"sample_size\" \"samples\" #> [125] \"segregating_sites\" \"sequence_length\" #> [127] \"simplify\" \"site\" #> [129] \"sites\" \"sites_position\" #> [131] \"split_edges\" \"subset\" #> [133] \"table_metadata_schemas\" \"tables\" #> [135] \"tables_dict\" \"Tajimas_D\" #> [137] \"time_units\" \"to_macs\" #> [139] \"to_nexus\" \"trait_correlation\" #> [141] \"trait_covariance\" \"trait_linear_model\" #> [143] \"trait_regression\" \"trees\" #> [145] \"trim\" \"union\" #> [147] \"variants\" \"write_fasta\" #> [149] \"write_nexus\" \"write_vcf\" #> [151] \"Y1\" \"Y2\" #> [153] \"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.0000572 # 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.0000218 # 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 -120. # 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 -686. ts_samples(ts) #> # A tibble: 58 × 3 #> name time pop #> #> 1 NEA_1 70000 NEA #> 2 NEA_2 40000 NEA #> 3 EUR_1 39170 EUR #> 4 EUR_2 39134 EUR #> 5 EUR_3 37738 EUR #> 6 EUR_4 36530 EUR #> 7 EUR_5 36362 EUR #> 8 EUR_6 35944 EUR #> 9 EUR_7 33900 EUR #> 10 EUR_8 33853 EUR #> # … with 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\")) #> 1295 multiallelic sites (0.208% out of 621652 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.0202 0.00664 3.05 #> 2 NEA_1 NEA_2 EUR_2 AFR_1 CH_1 0.0180 0.00617 2.92 #> 3 NEA_1 NEA_2 AFR_2 AFR_1 CH_1 0.00618 0.00262 2.36 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.0548 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.0548 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.0548 #> 2 afr nea 0.554 #> 3 eur nea 0.547 # 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.07196316 0.03738926 0.05256038 0.03671481 0.06204939 0.03626783 #> [7] 0.07445082 0.07191628 0.04078492 0.02880674 0.08310961 0.06680257 #> [13] 0.05513232 0.05122444 0.05378418 0.04748802 0.07068459 0.05085781 #> [19] 0.05397786 0.05445323"},{"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.0200 #> 2 eur -0.0000693 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.0000439 #> 2 NEA 0.0000482 #> 3 EUR 0.000394 #> 4 AFR 0.000396"},{"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.000448 #> 2 EUR NEA 0.000752 #> 3 AFR NEA 0.000774 #> 4 CH NEA 0.00402 #> 5 CH EUR 0.00403 #> 6 AFR CH 0.00404"},{"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, 36)) ) 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\", parent = \"ancestor\", 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 = 130e3, mating = 100e3, dispersal = 70e3 ) 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 = -1000), 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 │ 68║ #> ╟───────────────┼─────────╢ #> ║Sequence Length│ 100000║ #> ╟───────────────┼─────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼─────────╢ #> ║Sample Nodes │ 250║ #> ╟───────────────┼─────────╢ #> ║Total Size │141.6 KiB║ #> ╚═══════════════╧═════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 753│23.5 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 432│44.0 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 559│21.4 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 7│ 2.7 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 3│36.7 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 #> slendr 'nodes' object #> --------------------- #> times are expressed in a backward time direction #> #> summary of the table data contents: #> AFR - 5 'sampled', 5 'remembered', 5 'retained', 5 'alive' individuals #> EUR - 54 'sampled', 54 'remembered', 30 'retained', 30 'alive' individuals #> OOA - 16 'sampled', 16 'remembered', NA 'retained', 0 'alive' individuals #> EHG - 22 'sampled', 22 'remembered', NA 'retained', 0 'alive' individuals #> ANA - 24 'sampled', 24 'remembered', NA 'retained', 0 'alive' individuals #> YAM - 4 'sampled', 4 'remembered', NA 'retained', 0 'alive' individuals #> #> total: #> - 125 'sampled' individuals #> - 125 'remembered' individuals #> - 307 'retained' individuals #> - 35 'alive' individuals #> --------------------- #> oldest sampled individual: 40000 time units 'before present' #> youngest sampled individual: 0 time units 'before present' #> #> oldest node: 252034.5 time units 'before present' #> youngest node: 0 time units 'before present' #> --------------------- #> overview of the underlying sf object: #> #> # A tibble: 559 × 13 #> name pop node_id time time_ts…¹ location sampled remembered #> #> 1 AFR_1 AFR 180 0 0 (4108201 1075606) TRUE TRUE #> 2 AFR_1 AFR 181 0 0 (4108201 1075606) TRUE TRUE #> 3 AFR_2 AFR 182 0 0 (3065555 920380.9) TRUE TRUE #> 4 AFR_2 AFR 183 0 0 (3065555 920380.9) TRUE TRUE #> 5 AFR_3 AFR 184 0 0 (3130774 1302346) TRUE TRUE #> 6 AFR_3 AFR 185 0 0 (3130774 1302346) TRUE TRUE #> 7 AFR_4 AFR 186 0 0 (4260418 721906.3) TRUE TRUE #> 8 AFR_4 AFR 187 0 0 (4260418 721906.3) TRUE TRUE #> 9 AFR_5 AFR 188 0 0 (3660948 677070.9) TRUE TRUE #> 10 AFR_5 AFR 189 0 0 (3660948 677070.9) TRUE TRUE #> # … with 549 more rows, 5 more variables: retained , alive , #> # pedigree_id , ind_id , pop_id , and abbreviated variable #> # name ¹​time_tskit 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!). 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_42\" lineages <- ts_ancestors(ts, ind, verbose = TRUE) #> Collecting ancestors of EUR_42 [1/1]... #> #> Generating data about spatial relationships of nodes... lineages #> Simple feature collection with 98 features and 12 fields #> Active geometry column: connection #> Geometry type: LINESTRING #> Dimension: XY #> Bounding box: xmin: 3018749 ymin: 363440.4 xmax: 8484441 ymax: 4192932 #> Projected CRS: ETRS89-extended / LAEA Europe #> # A tibble: 98 × 15 #> name pop node_id level child_id parent_id child…¹ paren…² child…³ paren…⁴ #> * #> 1 EUR_42 EUR 224 1 224 264 0 1030 EUR EUR #> 2 EUR_42 EUR 224 2 264 273 1030 1630 EUR EUR #> 3 EUR_42 EUR 224 3 273 286 1630 3400 EUR EUR #> 4 EUR_42 EUR 224 4 286 305 3400 7750 EUR ANA #> 5 EUR_42 EUR 224 5 305 309 7750 8110 ANA ANA #> 6 EUR_42 EUR 224 6 309 312 8110 8350 ANA ANA #> 7 EUR_42 EUR 224 7 312 457 8350 27340 ANA ANA #> 8 EUR_42 EUR 224 7 312 462 8350 27790 ANA ANA #> 9 EUR_42 EUR 224 8 457 480 27340 28600 ANA OOA #> 10 EUR_42 EUR 224 8 462 490 27790 29110 ANA OOA #> # … with 88 more rows, 5 more variables: child_location , #> # parent_location , connection , left_pos , #> # right_pos , and abbreviated variable names ¹​child_time, ²​parent_time, #> # ³​child_pop, ⁴​parent_pop 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: 4739575 ymin: 2748103 xmax: 5689236 ymax: 3187720 #> Projected CRS: ETRS89-extended / LAEA Europe #> # A tibble: 2 × 15 #> name pop node_id level child_id parent_id child_…¹ paren…² child…³ paren…⁴ #> * #> 1 EUR_42 EUR 224 1 224 264 0 1030 EUR EUR #> 2 EUR_42 EUR 225 1 225 279 0 2200 EUR EUR #> # … with 5 more variables: child_location , #> # parent_location , connection , left_pos , #> # right_pos , and abbreviated variable names ¹​child_time, ²​parent_time, #> # ³​child_pop, ⁴​parent_pop level1_branches <- ts_ancestors(ts, \"EUR_3\") %>% 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[, ]$parent_location, shape = 20, color = level1_branches[, ]$node_id) + geom_sf(data = level1_branches[, ]$connection, linetype = 3) + theme_bw() + scale_color_manual(values = c(\"darkblue\", \"lightblue\")) + ggtitle(\"Parent nodes (blue) of a focal individual (red)\") ggplot() + geom_sf(data = map) + geom_sf(data = lineages, size = 0.5, aes(alpha = parent_time)) + 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) ts_samples(ts) %>% filter(pop == \"ANA\") #> # A tibble: 24 × 3 #> name time pop #> #> 1 ANA_1 27000 ANA #> 2 ANA_2 26000 ANA #> 3 ANA_3 25000 ANA #> 4 ANA_4 24000 ANA #> 5 ANA_5 23000 ANA #> 6 ANA_6 22000 ANA #> 7 ANA_7 21000 ANA #> 8 ANA_8 20000 ANA #> 9 ANA_9 19000 ANA #> 10 ANA_10 18000 ANA #> # … with 14 more rows lineages <- ts_ancestors(ts, \"ANA_24\") ggplot() + geom_sf(data = map) + geom_sf(data = lineages, size = 0.5, aes(alpha = parent_time)) + 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_24\"), size = 3) + guides(alpha = \"none\") + coord_sf(expand = 0) + labs(x = \"longitude\", y = \"latitude\") + facet_grid(. ~ node_id)"},{"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 9804 features and 2 fields #> Geometry type: LINESTRING #> Dimension: XY #> Bounding box: xmin: 2617353 ymin: 363440.4 xmax: 8621288 ymax: 4904200 #> Projected CRS: ETRS89-extended / LAEA Europe #> # A tibble: 9,804 × 3 #> connection child_time parent_time #> #> 1 (8173271 3201987, 8085004 3422948) 40000 40240 #> 2 (8085004 3422948, 8188064 3167335) 40240 40690 #> 3 (8188064 3167335, 8224089 2883400) 40690 41020 #> 4 (8224089 2883400, 8256321 2822963) 41020 41110 #> 5 (8256321 2822963, 7805879 1633736) 41110 45520 #> 6 (7805879 1633736, 3510351 681724.1) 45520 56950 #> 7 (7805879 1633736, 3839546 378635.3) 45520 59410 #> 8 (7805879 1633736, 3143416 598468.7) 45520 87010 #> 9 (3510351 681724.1, 3839546 378635.3) 56950 59410 #> 10 (3839546 378635.3, 4530812 668950.4) 59410 95980 #> # … with 9,794 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 %>% dplyr::filter(child_pop != \"AFR\") %>% 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│36.8 KiB│ No║ #> ╟───────────┼──────┼────────┼────────────╢ #> ║Sites │257040│ 6.1 MiB│ No║ #> ╚═══════════╧══════╧════════╧════════════╝ msprime_nogf #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 62562║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 208║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 14.4 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │246660│ 7.5 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 104│ 2.9 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 69284│ 2.4 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │ 32645│892.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 6│414 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 2│ 3.8 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │ 69263│ 1.7 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) slim_afs <- ts_afs(ts_slim, polarised = TRUE) 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/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpYMHeKD/file8851124cb78c\"); } 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 #> slendr 'nodes' object #> --------------------- #> times are expressed in a forward time direction #> #> summary of the table data contents: #> p1 - 10 'sampled', 0 'remembered', 0 'retained', 10 'alive' individuals #> p2 - 500 'sampled', 0 'remembered', 0 'retained', 500 'alive' individuals #> p3 - 2500 'sampled', 0 'remembered', 0 'retained', 2500 'alive' individuals #> p4 - 10000 'sampled', 0 'remembered', 0 'retained', 10000 'alive' individuals #> #> total: #> - 13010 'sampled' individuals #> - 0 'remembered' individuals #> - 0 'retained' individuals #> - 13010 'alive' individuals #> --------------------- #> oldest sampled individual: 0 time units 'before present' #> youngest sampled individual: 0 time units 'before present' #> #> oldest node: 0 time units 'before present' #> youngest node: 0 time units 'before present' #> --------------------- #> overview of the underlying table object: #> #> # A tibble: 26,020 × 11 #> pop node_id time time_tskit sampled remembe…¹ retai…² alive pedig…³ ind_id #> #> 1 p1 0 0 0 TRUE FALSE FALSE TRUE 2.01e7 0 #> 2 p1 1 0 0 TRUE FALSE FALSE TRUE 2.01e7 0 #> 3 p1 2 0 0 TRUE FALSE FALSE TRUE 2.01e7 1 #> 4 p1 3 0 0 TRUE FALSE FALSE TRUE 2.01e7 1 #> 5 p1 4 0 0 TRUE FALSE FALSE TRUE 2.01e7 2 #> 6 p1 5 0 0 TRUE FALSE FALSE TRUE 2.01e7 2 #> 7 p1 6 0 0 TRUE FALSE FALSE TRUE 2.01e7 3 #> 8 p1 7 0 0 TRUE FALSE FALSE TRUE 2.01e7 3 #> 9 p1 8 0 0 TRUE FALSE FALSE TRUE 2.01e7 4 #> 10 p1 9 0 0 TRUE FALSE FALSE TRUE 2.01e7 4 #> # … with 26,010 more rows, 1 more variable: pop_id , and abbreviated #> # variable names ¹​remembered, ²​retained, ³​pedigree_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) #> 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.6.2 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) #> slendr 'nodes' object #> --------------------- #> times are expressed in a backward time direction #> --------------------- #> overview of the underlying table object: #> #> # 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 #> # … with 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/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpYMHeKD/file88514d3eba6d\"); } ts <- ts_load(spatial_trees_file) %>% ts_simplify() data <- ts_nodes(ts) data #> slendr 'nodes' object #> --------------------- #> times are expressed in a forward time direction #> #> summary of the table data contents: #> p1 - 500 'sampled', 0 'remembered', 500 'retained', 500 'alive' individuals #> #> total: #> - 500 'sampled' individuals #> - 0 'remembered' individuals #> - 895 'retained' individuals #> - 500 'alive' individuals #> --------------------- #> oldest sampled individual: 0 time units 'before present' #> youngest sampled individual: 0 time units 'before present' #> #> oldest node: 8463 time units 'before present' #> youngest node: 0 time units 'before present' #> --------------------- #> overview of the underlying sf object: #> #> # A tibble: 1,955 × 12 #> pop node_id time time_…¹ location sampled remembered retai…² #> #> 1 p1 0 0 0 (0.904485 0.0777489) TRUE FALSE TRUE #> 2 p1 1 0 0 (0.904485 0.0777489) TRUE FALSE TRUE #> 3 p1 2 0 0 (0.668828 0.5246381) TRUE FALSE TRUE #> 4 p1 3 0 0 (0.668828 0.5246381) TRUE FALSE TRUE #> 5 p1 4 0 0 (0.7707701 0.1518462) TRUE FALSE TRUE #> 6 p1 5 0 0 (0.7707701 0.1518462) TRUE FALSE TRUE #> 7 p1 6 0 0 (0.7617792 0.2616453) TRUE FALSE TRUE #> 8 p1 7 0 0 (0.7617792 0.2616453) TRUE FALSE TRUE #> 9 p1 8 0 0 (0.9807475 0.04223008) TRUE FALSE TRUE #> 10 p1 9 0 0 (0.9807475 0.04223008) TRUE FALSE TRUE #> # … with 1,945 more rows, 4 more variables: alive , pedigree_id , #> # ind_id , pop_id , and abbreviated variable names ¹​time_tskit, #> # ²​retained 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":[]},{"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(-15, 60), yrange = c(20, 65), crs = 3035) #> OGR data source with driver: ESRI Shapefile #> Source: \"/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpgCqaBQ/naturalearth\", layer: \"ne_110m_land\" #> with 127 features #> It has 3 fields 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(-15, 60), yrange = c(20, 65), crs = 3035) #> OGR data source with driver: ESRI Shapefile #> Source: \"/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpgCqaBQ/naturalearth\", layer: \"ne_110m_land\" #> with 127 features #> It has 3 fields 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 = m, 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 = 130e3, mating = 100e3, dispersal = 70e3, ) 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, c(\"EUR_581\", \"ANA_120\", \"EHG_440\", \"EUR_597\", \"YAM_59\")) tree <- ts_phylo(ts_small, i = 10) #> Starting checking the validity of tree... #> Found number of tips: n = 10 #> Found number of nodes: m = 9 #> Done. nodes <- ts_nodes(tree) edges <- ts_edges(tree) ancestors <- ts_ancestors(ts, \"EUR_581\")"},{"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":"","code":"library(ggtree) #> ggtree v3.6.2 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_581\") %>% .$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(-120000, 31000), labels = abs_comma, breaks = -c(120, 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(data = filter(nodes, is.na(name)), aes(color = pop, shape = pop), size = 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\", shape = \"none\") + theme_bw() + theme(legend.position = \"bottom\", axis.title.x = element_blank(), axis.title.y = element_blank()) chrom_names <- stats::setNames( c(\"EUR_581 (node 10)\", \"EUR_581 (node 11)\"), unique(ancestors$node_id) ) p_ancestors <- ggplot() + geom_sf(data = map) + geom_sf(data = ancestors, size = 0.5, aes(alpha = parent_time)) + 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_581\"), 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/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 (2023). slendr: Simulation Framework Spatiotemporal Population Genetics. R package version 0.4.0.9000, https://github.com/bodkan/slendr.","code":"@Manual{, title = {slendr: A Simulation Framework for Spatiotemporal Population Genetics}, author = {Martin Petr}, year = {2023}, note = {R package version 0.4.0.9000}, 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 preprint bioRxiv website.","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). software active development! like stay updated: Click “Watch” button project’s GitHub website. Follow Twitter posting progress updates. 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) # 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, 36)) ) 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\", parent = \"ancestor\", 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 preprint 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","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 all dependencies are available for slendr examples — check_dependencies","title":"Check that all dependencies are available for slendr examples — check_dependencies","text":"Check dependencies available slendr examples","code":""},{"path":"https://www.slendr.net/reference/check_dependencies.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Check that all dependencies are available for slendr examples — check_dependencies","text":"","code":"check_dependencies(python = FALSE, slim = FALSE)"},{"path":"https://www.slendr.net/reference/check_dependencies.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Check that all dependencies are available for slendr examples — check_dependencies","text":"python slendr Python environment required? slim SLiM required?","code":""},{"path":"https://www.slendr.net/reference/check_dependencies.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Check that all dependencies are available for slendr examples — check_dependencies","text":"return value. Called result error message particular software dependency missing example run.","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) # make sure dependencies are 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/msprime-1.2.0_tskit-0.5.2_pyslim-1.0/bin/python #> Python version: 3.8.15 | packaged by conda-forge | (default, Nov 22 2022, 08:49:06) [Clang 14.0.6 ] #> #> slendr requirements: #> - tskit: version 0.5.2 ✓ #> - msprime: version 1.2.0 ✓ #> - pyslim: version 1.0 ✓"},{"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":"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\") #> OGR data source with driver: ESRI Shapefile #> Source: \"/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpdZ3DXs/naturalearth\", layer: \"ne_110m_land\" #> with 127 features #> It has 3 fields"},{"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 )"},{"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 (missing, SLiM's seed used) 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)?","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)","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) # make sure dependencies are 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 │ 37.4 KiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤════╤═════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪═════════╪════════════╣ #> ║Edges │ 458│ 14.3 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Individuals│ 115│ 3.2 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Nodes │ 459│ 12.6 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, log = FALSE)"},{"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) log y-axis plotted log scale? Useful models long time-scales.","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) # make sure dependencies are 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 = \"ancestor\", 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 \"ancestor\" (indicating 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.","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, ...) # S3 method for slendr_nodes 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) # make sure dependencies are 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\") #> OGR data source with driver: ESRI Shapefile #> Source: \"/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpdZ3DXs/naturalearth\", layer: \"ne_110m_land\" #> with 127 features #> It has 3 fields"},{"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.","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":"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, 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 (missing, SLiM's seed used) 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 Optional way specify path appropriate SLiM binary (useful slim binary $PATH).","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)","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) # make sure dependencies are 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 │ 1046║ #> ╟───────────────┼─────────╢ #> ║Total Size │317.6 KiB║ #> ╚═══════════════╧═════════╝ #> ╔═══════════╤════╤═════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪═════════╪════════════╣ #> ║Edges │1907│ 59.6 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Individuals│1330│131.7 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Nodes │1908│ 71.5 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Populations│ 4│ 2.5 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Provenances│ 1│ 33.6 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/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","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 = FALSE )"},{"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 FALSE (default) allele frequency spectrum folded (.e. counts depend knowing allele ancestral)","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","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, please see tskit manual https://tskit.dev/tskit/docs/stable/python-api.html","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) # make sure dependencies are 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.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, mutate = TRUE, 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] 4 2 0 0 1 0 0 1 0 20 0 0 0 0 0 0 0 0 0 0"},{"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) # make sure dependencies are 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.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, simplify = TRUE) # 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: 93 × 12 #> name pop node_id level child_id parent_id child_…¹ paren…² child…³ paren…⁴ #> #> 1 EUR_1 EUR 16 1 16 37 0 2690 EUR EUR #> 2 EUR_1 EUR 16 1 16 38 0 2930 EUR EUR #> 3 EUR_1 EUR 16 1 16 40 0 4250 EUR EUR #> 4 EUR_1 EUR 16 2 37 38 2690 2930 EUR EUR #> 5 EUR_1 EUR 16 2 38 42 2930 6440 EUR EUR #> 6 EUR_1 EUR 16 2 38 47 2930 7730 EUR EUR #> 7 EUR_1 EUR 16 2 38 48 2930 8210 EUR EUR #> 8 EUR_1 EUR 16 2 38 49 2930 8300 EUR EUR #> 9 EUR_1 EUR 16 2 38 52 2930 10280 EUR EUR #> 10 EUR_1 EUR 16 2 40 42 4250 6440 EUR EUR #> # … with 83 more rows, 2 more variables: left_pos , right_pos , and #> # abbreviated variable names ¹​child_time, ²​parent_time, ³​child_pop, #> # ⁴​parent_pop"},{"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) # make sure dependencies are 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.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, simplify = TRUE) 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) # make sure dependencies are 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.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, simplify = TRUE) # 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: 2 × 12 #> name pop node_id level child_id parent_id child_t…¹ paren…² child…³ paren…⁴ #> #> 1 NEA_1 NEA 62 1 0 62 70000 70040 NEA NEA #> 2 NEA_1 NEA 62 1 1 62 70000 70040 NEA NEA #> # … with 2 more variables: left_pos , right_pos , and abbreviated #> # variable names ¹​child_time, ²​parent_time, ³​child_pop, ⁴​parent_pop"},{"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) # make sure dependencies are 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.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, mutate = TRUE, 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.0000442 #> 2 AFR NEA 0.000383 #> 3 EUR NEA 0.000387 #> 4 CH NEA 0.00412 #> 5 AFR CH 0.00415 #> 6 CH EUR 0.00416"},{"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) # make sure dependencies are 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.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, mutate = TRUE, 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 AFR 0 #> 2 CH 0 #> 3 NEA 0.000004 #> 4 EUR 0.00000484"},{"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 = 1500, height = 500, labels = FALSE, sampled_only = TRUE, ... )"},{"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. ... 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) # make sure dependencies are 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.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, simplify = TRUE) # 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\") #> Error in ts_draw(tree, time_scale = \"rank\"): For plotting trees using the native SVG tskit capabilities, please #> install the R package rsvg by calling `install.packages(\"rsvg\")"},{"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) # make sure dependencies are 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.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, simplify = TRUE) # extract an annotated table with (spatio-)temporal edge information ts_edges(ts) #> # A tibble: 133 × 6 #> child_node_id parent_node_id child_time parent_time child_pop parent_pop #> #> 1 14 26 0 20 CH CH #> 2 15 26 0 20 CH CH #> 3 4 36 0 1430 AFR AFR #> 4 5 30 0 80 AFR AFR #> 5 6 27 0 20 AFR AFR #> 6 7 28 0 20 AFR AFR #> 7 8 28 0 20 AFR AFR #> 8 9 31 0 110 AFR AFR #> 9 10 32 0 140 AFR AFR #> 10 11 29 0 50 AFR AFR #> # … with 123 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://www.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":"Calculate f2, f3, f4, f4-ratio statistics","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 (following nomenclature Patterson et al. 2021)","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":"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) # make sure dependencies are 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.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, mutate = TRUE, 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.000042 # 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.0000427 # 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.000022 # 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.000199 # 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 # 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 # 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 #> 2 EUR_2 NEA_1 NEA_2 AFR_1 CH_1 0 #> 3 EUR_4 NEA_1 NEA_2 AFR_1 CH_1 0 #> 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) # make sure dependencies are 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.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, mutate = TRUE, 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.933"},{"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) # make sure dependencies are 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.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, simplify = TRUE, mutate = TRUE, mutation_rate = 1e-8, random_seed = 42) # extract the genotype matrix (this could take a long time consume lots # of memory!) gts <- ts_genotypes(ts) #> 2 multiallelic sites (0.092% out of 2184 total) detected and removed"},{"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, recapitate = FALSE, simplify = FALSE, mutate = FALSE, recombination_rate = NULL, mutation_rate = NULL, Ne = NULL, random_seed = NULL, simplify_to = NULL, keep_input_roots = FALSE, demography = 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. recapitate tree sequence recapitated? simplify tree sequence simplified set sampled individuals (explicitly recorded)? mutate tree sequence mutated? recombination_rate, Ne Arguments passed ts_recapitate mutation_rate Mutation rate passed ts_mutate random_seed Random seed passed pyslim's recapitate method simplify_to character vector individual names. NULL, remembered individuals retained. used simplify = TRUE. keep_input_roots history ancestral MRCA samples retained tree sequence? Default FALSE. demography Ancestral demography passed internally msprime.sim_ancestry() (see msprime's documentation mode detail)","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) # make sure dependencies are 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.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, simplify = 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, recapitate = TRUE, simplify = TRUE, recombination_rate = 1e-8, Ne = 10000, random_seed = 42) # load tree sequence, recapitate it, simplify it and overlay neutral mutations ts <- ts_load(slendr_ts, model, recapitate = TRUE, simplify = TRUE, random_seed = 42, recombination_rate = 1e-8, Ne = 10000, mutation_rate = 1e-8) ts #> ╔════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤════════╣ #> ║Trees │ 24║ #> ╟───────────────┼────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼────────╢ #> ║Sample Nodes │ 26║ #> ╟───────────────┼────────╢ #> ║Total Size │58.6 KiB║ #> ╚═══════════════╧════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 133│ 4.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 55│ 7.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 68│ 3.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 5│ 2.6 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 4│36.6 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Sites │ 0│16 Bytes│ 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) # make sure dependencies are 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.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.3.0.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 #> #> $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 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) # make sure dependencies are 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.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 │ 24║ #> ╟───────────────┼─────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼─────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼─────────╢ #> ║Sample Nodes │ 26║ #> ╟───────────────┼─────────╢ #> ║Total Size │188.9 KiB║ #> ╚═══════════════╧═════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 133│ 4.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 55│ 7.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │2187│80.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 68│ 3.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 4│ 2.5 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 3│34.7 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Sites │2184│53.3 KiB│ No║ #> ╚═══════════╧════╧════════╧════════════╝ #>"},{"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) # make sure dependencies are 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.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, simplify = TRUE) # extract an annotated table with (spatio-)temporal node information ts_nodes(ts) #> slendr 'nodes' object #> --------------------- #> times are expressed in a backward time direction #> #> summary of the table data contents: #> CH - 1 'sampled', 1 'remembered', 1 'retained', 1 'alive' individuals #> AFR - 5 'sampled', 5 'remembered', 5 'retained', 5 'alive' individuals #> EUR - 5 'sampled', 5 'remembered', 5 'retained', 5 'alive' individuals #> NEA - 2 'sampled', 2 'remembered', NA 'retained', 0 'alive' individuals #> #> total: #> - 13 'sampled' individuals #> - 13 'remembered' individuals #> - 42 'retained' individuals #> - 11 'alive' individuals #> --------------------- #> oldest sampled individual: 70000 time units 'before present' #> youngest sampled individual: 0 time units 'before present' #> #> oldest node: 6000170 time units 'before present' #> youngest node: 0 time units 'before present' #> --------------------- #> overview of the underlying table object: #> #> # A tibble: 68 × 12 #> name pop node_id time time_tskit sampled remembered retai…¹ alive pedig…² #> #> 1 CH_1 CH 14 0 0 TRUE TRUE TRUE TRUE 5520343 #> 2 CH_1 CH 15 0 0 TRUE TRUE TRUE TRUE 5520343 #> 3 AFR_1 AFR 4 0 0 TRUE TRUE TRUE TRUE 5520350 #> 4 AFR_1 AFR 5 0 0 TRUE TRUE TRUE TRUE 5520350 #> 5 AFR_2 AFR 6 0 0 TRUE TRUE TRUE TRUE 5520351 #> 6 AFR_2 AFR 7 0 0 TRUE TRUE TRUE TRUE 5520351 #> 7 AFR_3 AFR 8 0 0 TRUE TRUE TRUE TRUE 5520352 #> 8 AFR_3 AFR 9 0 0 TRUE TRUE TRUE TRUE 5520352 #> 9 AFR_4 AFR 10 0 0 TRUE TRUE TRUE TRUE 5520357 #> 10 AFR_4 AFR 11 0 0 TRUE TRUE TRUE TRUE 5520357 #> # … with 58 more rows, 2 more variables: ind_id , pop_id , and #> # abbreviated variable names ¹​retained, ²​pedigree_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 (one-based indexing), mode = \"position\", tree covering -th base simulated genome returned. 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) # make sure dependencies are 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.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, simplify = TRUE) # 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 25 internal nodes. #> #> Tip labels: #> 25 (EUR_5), 24 (EUR_5), 23 (EUR_4), 22 (EUR_4), 21 (EUR_3), 20 (EUR_3), ... #> Node labels: #> 67, 27, 26, 29, 30, 31, ... #> #> 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","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) # make sure dependencies are 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.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 │ 24║ #> ╟───────────────┼────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼────────╢ #> ║Sample Nodes │ 26║ #> ╟───────────────┼────────╢ #> ║Total Size │58.1 KiB║ #> ╚═══════════════╧════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 133│ 4.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 55│ 7.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 68│ 3.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 5│ 2.6 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 3│36.1 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) # make sure dependencies are 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.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, simplify = TRUE) # 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) # make sure dependencies are 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.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) # make sure dependencies are 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.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, mutate = TRUE, 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 0 #> 2 CH 0 #> 3 EUR 8 #> 4 NEA 3"},{"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)"},{"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.","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) # make sure dependencies are 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.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) ts <- ts_load(slendr_ts, model) ts #> ╔════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤════════╣ #> ║Trees │ 24║ #> ╟───────────────┼────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼────────╢ #> ║Sample Nodes │ 26║ #> ╟───────────────┼────────╢ #> ║Total Size │55.8 KiB║ #> ╚═══════════════╧════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 133│ 4.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 55│ 7.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 68│ 3.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 4│ 2.5 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 2│34.0 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 │ 13║ #> ╟───────────────┼────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼────────╢ #> ║Sample Nodes │ 14║ #> ╟───────────────┼────────╢ #> ║Total Size │50.1 KiB║ #> ╚═══════════════╧════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 68│ 2.1 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 29│ 4.6 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 36│ 2.0 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 4│ 2.5 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 3│34.5 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.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, simplify = TRUE, mutate = TRUE, mutation_rate = 1e-8, random_seed = 42) # get the 'raw' tskit table of individuals ts_table(ts, \"individuals\") #> # A tibble: 55 × 11 #> ind_id time pedigree_id raste…¹ raste…² pop_id alive remem…³ retai…⁴ sampled #> #> 1 0 -10 5520343 0 0 0 TRUE TRUE TRUE TRUE #> 2 1 -10 5520350 0 0 1 TRUE TRUE TRUE TRUE #> 3 2 -10 5520351 0 0 1 TRUE TRUE TRUE TRUE #> 4 3 -10 5520352 0 0 1 TRUE TRUE TRUE TRUE #> 5 4 -10 5520357 0 0 1 TRUE TRUE TRUE TRUE #> 6 5 -10 5520358 0 0 1 TRUE TRUE TRUE TRUE #> 7 6 -10 5520506 0 0 3 TRUE TRUE TRUE TRUE #> 8 7 -10 5520601 0 0 3 TRUE TRUE TRUE TRUE #> 9 8 -10 5520655 0 0 3 TRUE TRUE TRUE TRUE #> 10 9 -10 5520773 0 0 3 TRUE TRUE TRUE TRUE #> # … with 45 more rows, 1 more variable: time_tskit , and abbreviated #> # variable names ¹​raster_x, ²​raster_y, ³​remembered, ⁴​retained # get the 'raw' tskit table of edges ts_table(ts, \"edges\") #> # A tibble: 133 × 5 #> id child parent left right #> #> 1 0 14 26 0 500000 #> 2 1 15 26 0 500000 #> 3 2 6 27 0 500000 #> 4 3 13 27 0 500000 #> 5 4 7 28 0 500000 #> 6 5 8 28 0 500000 #> 7 6 11 29 0 500000 #> 8 7 12 29 0 500000 #> 9 8 5 30 0 500000 #> 10 9 29 30 0 500000 #> # … with 123 more rows # get the 'raw' tskit table of nodes ts_table(ts, \"nodes\") #> # A tibble: 68 × 5 #> node_id ind_id pop_id time time_tskit #> #> 1 0 18 2 70010 2334 #> 2 1 18 2 70010 2334 #> 3 2 20 2 40010 1334 #> 4 3 20 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 #> # … with 58 more rows # get the 'raw' tskit table of mutations ts_table(ts, \"mutations\") #> # A tibble: 2,187 × 5 #> id site node time time_tskit #> #> 1 0 0 66 757010. 25234. #> 2 1 1 64 575160. 19172. #> 3 2 2 26 3622440. 120748. #> 4 3 3 66 693873. 23129. #> 5 4 4 63 220620. 7354. #> 6 5 5 66 5179605. 172654. #> 7 6 6 66 5212483. 173750. #> 8 7 7 66 2373328. 79111. #> 9 8 8 64 477414. 15914. #> 10 9 9 26 1158846. 38629. #> # … with 2,177 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) # make sure dependencies are 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.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, mutate = TRUE, 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 -0.619 #> 2 nea 2.01"},{"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 (one-based indexing), mode = \"position\", tree covering -th base simulated genome returned. 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) # make sure dependencies are 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.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, simplify = TRUE) # extract the first tree in the tree sequence tree <- ts_tree(ts, i = 1) # extract the tree at a position 100000bp 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\") #> OGR data source with driver: ESRI Shapefile #> Source: \"/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpdZ3DXs/naturalearth\", layer: \"ne_110m_land\" #> with 127 features #> It has 3 fields"},{"path":"https://www.slendr.net/news/index.html","id":"slendr-development-version","dir":"Changelog","previous_headings":"","what":"slendr (development version)","title":"slendr (development version)","text":"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. named list provided sample_sets = argument oneway statistic function, names used set column resulting data frame even single samples used. (#2a6781) 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)","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 ( install.packages(\"devtools\")). fact, decide try slendr, please make sure update regularly keep eye changelog regular basis! 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 supported macOS Linux moment. However, slendr’s software dependencies already available Windows, hope make R package fully portable soon get access Windows machine proper testing . Windows user like help, please get touch!","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). 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. don’t want analyze tree sequences R, won’t need slendr’s Python dependencies. 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","dir":"Articles","previous_headings":"Software dependencies","what":"sf","title":"Installation instructions","text":"R package sf heart geospatial data analysis R. available CRAN can installed major platforms executing install.packages(\"sf\") R session. install slendr (see top page), installation procedure automatically install sf . normal circumstances, worry sf . 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 trouble installing slendr R session, ’s worth testing whether can run install.packages(\"sf\") successfully load library(sf). nearly 100% cases test cases, slendr installation failed, due problem missing dependency sf. ’re problems, look help .","code":""},{"path":"https://www.slendr.net/articles/vignette-00-installation.html","id":"macos","dir":"Articles","previous_headings":"Software dependencies > sf","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":"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 . 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. 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, truly. 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. , dedicated Python environment created, calling library(slendr) later point activate environment automatically. Therefore, despite using Python internal handling tree-sequence data coalescent simulation, interaction Python necessary working slendr R. call setup_env() ! , everything taken care library(slendr) automatically.","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 hack simply call Python command-line background, implemented using R package reticulate. embeds Python session within 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 R package finally lands official CRAN repository. 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-00-installation.html","id":"renv","dir":"Articles","previous_headings":"","what":"renv","title":"Installation instructions","text":"TODO: Advertise renv solution managing reproducible environments R packages.","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) #> ======================================================================= #> NOTE: Due to frequent issues with some user's Python setups, slendr no #> longer activates its Python environment automatically upon calling #> library(slendr). #> #> In order to use slendr's msprime back end or its tree-sequence #> functionality, users now must activate slendr's Python environments #> manually by calling init_env(). #> #> This inconvenience is a compromise in order to help novice users avoid #> having to debug very technical, low-level Python-specific issues. This #> note will be removed in a future version of 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\", parent = \"ancestor\", 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 pop_id #> 1 AFR ancestor 3000 1 52000 -1 -1 0 #> 2 OOA AFR 500 34 51000 901 25000 1 #> 3 EHG OOA 1000 801 28000 1534 6000 2 #> 4 ANA OOA 3000 801 28000 1601 4000 3 #> 5 EUR EHG 2000 901 25000 -1 -1 4 #> 6 YAM EHG 500 1501 7000 1651 2500 5 #> parent_id #> 1 -1 #> 2 0 #> 3 1 #> 4 1 #> 5 2 #> 6 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)"},{"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. Graph demographic history (sometimes called “admixture graph”) Interactive explorer spatial dynamics","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 │ 129║ #> ╟───────────────┼───────╢ #> ║Sequence Length│ 100000║ #> ╟───────────────┼───────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼───────╢ #> ║Sample Nodes │ 10000║ #> ╟───────────────┼───────╢ #> ║Total Size │2.6 MiB║ #> ╚═══════════════╧═══════╝ #> ╔═══════════╤═════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪═════╪═════════╪════════════╣ #> ║Edges │18692│584.1 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Individuals│12814│ 1.2 MiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Nodes │18348│681.6 KiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Populations│ 6│ 2.6 KiB│ Yes║ #> ╟───────────┼─────┼─────────┼────────────╢ #> ║Provenances│ 1│ 33.6 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) #> ======================================================================= #> NOTE: Due to frequent issues with some user's Python setups, slendr no #> longer activates its Python environment automatically upon calling #> library(slendr). #> #> In order to use slendr's msprime back end or its tree-sequence #> functionality, users now must activate slendr's Python environments #> manually by calling init_env(). #> #> This inconvenience is a compromise in order to help novice users avoid #> having to debug very technical, low-level Python-specific issues. This #> note will be removed in a future version of 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 │9051│282.9 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Individuals│6295│616.3 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Nodes │9076│337.5 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Populations│ 25│ 5.7 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Provenances│ 1│ 33.5 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-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/msprime-1.2.0_tskit-0.5.2_pyslim-1.0/bin/python #> Python version: 3.8.15 | packaged by conda-forge | (default, Nov 22 2022, 08:49:06) [Clang 14.0.6 ] #> #> slendr requirements: #> - tskit: version 0.5.2 ✓ #> - msprime: version 1.2.0 ✓ #> - pyslim: version 1.0 ✓"},{"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 10319 EUR 1 NA NA NA NA #> 2 11187 EUR 1 NA NA NA NA #> 3 11395 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 14774 EUR 1 NA NA NA NA #> 10 16361 EUR 1 NA NA NA NA #> # … with 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 to be executed: #> #> /Users/mp/Library/r-miniconda-arm64/envs/msprime-1.2.0_tskit-0.5.2_pyslim-1.0/bin/python /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpnB8Ity/file4538f484005_introgression/script.py --seed 314159 --model /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpnB8Ity/file4538f484005_introgression --output /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpnB8Ity/file453830c8956d.trees --sequence-length 100000000 --recombination-rate 1e-08 --sampling-schedule /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpnB8Ity/file45385749d718 --verbose #> -------------------------------------------------- #> #> Tree sequence was saved to: #> /var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpnB8Ity/file453830c8956d.trees #> Loading the tree-sequence file... ts #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 237352║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 116║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 36.4 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │858165│ 26.2 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 58│ 1.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │138217│ 3.7 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. Still, dealing SLiM tree sequence, case vignetted, one go, specifying recapitate = TRUE call ts_load() specifying couple additional arguments required recapitation (see pyslim documentation recapitation section detail). 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/d_/hblb15pd3b94rg0v35920wd80000gn/T//RtmpnB8Ity/file45381e38161b\" ts <- ts_load(output_file, model) ts #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 237352║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 116║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 36.4 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │858165│ 26.2 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 58│ 1.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │138217│ 3.7 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 1│ 7.0 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │ 0│ 16 Bytes│ No║ #> ╚═══════════╧══════╧═════════╧════════════╝ ts_simplify(ts) #> Warning: If you want to simplify an msprime tree sequence, you must specify #> the names of individuals to simplify to via the `simplify_to = ` #> function argument. #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 237352║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 116║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 36.4 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │858165│ 26.2 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 58│ 1.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │138217│ 3.7 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 1│ 7.0 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 │ 131740║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 14║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 18.8 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │436892│ 13.3 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 7│220 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │ 78560│ 2.1 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 2│ 7.5 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 │ 237352║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 116║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 73.3 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │858165│ 26.2 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 58│ 1.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │623549│ 22.0 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │138217│ 3.7 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 4│338 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 2│ 7.7 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │621652│ 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) #> 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: #> 76943, 70, 1667, 3512, 7999, 11522, ... #> #> Rooted; includes branch lengths. library(ggtree) #> ggtree v3.6.2 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\" \"coiterate\" #> [11] \"count_topologies\" \"decapitate\" #> [13] \"delete_intervals\" \"delete_sites\" #> [15] \"diffs\" \"discrete_genome\" #> [17] \"discrete_time\" \"divergence\" #> [19] \"diversity\" \"draw_svg\" #> [21] \"draw_text\" \"dump\" #> [23] \"dump_tables\" \"dump_text\" #> [25] \"edge\" \"edge_diffs\" #> [27] \"edges\" \"edges_child\" #> [29] \"edges_left\" \"edges_parent\" #> [31] \"edges_right\" \"edgesets\" #> [33] \"equals\" \"f2\" #> [35] \"f3\" \"f4\" #> [37] \"file_uuid\" \"first\" #> [39] \"Fst\" \"genealogical_nearest_neighbours\" #> [41] \"general_stat\" \"genetic_relatedness\" #> [43] \"genotype_matrix\" \"get_ll_tree_sequence\" #> [45] \"get_num_mutations\" \"get_num_nodes\" #> [47] \"get_num_records\" \"get_num_sites\" #> [49] \"get_num_trees\" \"get_pairwise_diversity\" #> [51] \"get_population\" \"get_sample_size\" #> [53] \"get_samples\" \"get_sequence_length\" #> [55] \"get_time\" \"haplotypes\" #> [57] \"has_reference_sequence\" \"ibd_segments\" #> [59] \"indexes_edge_insertion_order\" \"indexes_edge_removal_order\" #> [61] \"individual\" \"individual_locations\" #> [63] \"individual_populations\" \"individual_times\" #> [65] \"individuals\" \"individuals_flags\" #> [67] \"individuals_location\" \"individuals_population\" #> [69] \"individuals_time\" \"kc_distance\" #> [71] \"keep_intervals\" \"last\" #> [73] \"ll_tree_sequence\" \"load\" #> [75] \"load_tables\" \"ltrim\" #> [77] \"max_root_time\" \"mean_descendants\" #> [79] \"metadata\" \"metadata_schema\" #> [81] \"migration\" \"migrations\" #> [83] \"migrations_dest\" \"migrations_left\" #> [85] \"migrations_node\" \"migrations_right\" #> [87] \"migrations_source\" \"migrations_time\" #> [89] \"mutation\" \"mutations\" #> [91] \"mutations_node\" \"mutations_parent\" #> [93] \"mutations_site\" \"mutations_time\" #> [95] \"nbytes\" \"newick_trees\" #> [97] \"node\" \"nodes\" #> [99] \"nodes_flags\" \"nodes_individual\" #> [101] \"nodes_population\" \"nodes_time\" #> [103] \"num_edges\" \"num_individuals\" #> [105] \"num_migrations\" \"num_mutations\" #> [107] \"num_nodes\" \"num_populations\" #> [109] \"num_provenances\" \"num_samples\" #> [111] \"num_sites\" \"num_trees\" #> [113] \"pairwise_diversity\" \"parse_windows\" #> [115] \"population\" \"populations\" #> [117] \"provenance\" \"provenances\" #> [119] \"records\" \"reference_sequence\" #> [121] \"rtrim\" \"sample_count_stat\" #> [123] \"sample_size\" \"samples\" #> [125] \"segregating_sites\" \"sequence_length\" #> [127] \"simplify\" \"site\" #> [129] \"sites\" \"sites_position\" #> [131] \"split_edges\" \"subset\" #> [133] \"table_metadata_schemas\" \"tables\" #> [135] \"tables_dict\" \"Tajimas_D\" #> [137] \"time_units\" \"to_macs\" #> [139] \"to_nexus\" \"trait_correlation\" #> [141] \"trait_covariance\" \"trait_linear_model\" #> [143] \"trait_regression\" \"trees\" #> [145] \"trim\" \"union\" #> [147] \"variants\" \"write_fasta\" #> [149] \"write_nexus\" \"write_vcf\" #> [151] \"Y1\" \"Y2\" #> [153] \"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.0000572 # 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.0000218 # 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 -120. # 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 -686. ts_samples(ts) #> # A tibble: 58 × 3 #> name time pop #> #> 1 NEA_1 70000 NEA #> 2 NEA_2 40000 NEA #> 3 EUR_1 39170 EUR #> 4 EUR_2 39134 EUR #> 5 EUR_3 37738 EUR #> 6 EUR_4 36530 EUR #> 7 EUR_5 36362 EUR #> 8 EUR_6 35944 EUR #> 9 EUR_7 33900 EUR #> 10 EUR_8 33853 EUR #> # … with 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\")) #> 1295 multiallelic sites (0.208% out of 621652 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.0202 0.00664 3.05 #> 2 NEA_1 NEA_2 EUR_2 AFR_1 CH_1 0.0180 0.00617 2.92 #> 3 NEA_1 NEA_2 AFR_2 AFR_1 CH_1 0.00618 0.00262 2.36 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.0548 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.0548 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.0548 #> 2 afr nea 0.554 #> 3 eur nea 0.547 # 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.07196316 0.03738926 0.05256038 0.03671481 0.06204939 0.03626783 #> [7] 0.07445082 0.07191628 0.04078492 0.02880674 0.08310961 0.06680257 #> [13] 0.05513232 0.05122444 0.05378418 0.04748802 0.07068459 0.05085781 #> [19] 0.05397786 0.05445323"},{"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.0200 #> 2 eur -0.0000693 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.0000439 #> 2 NEA 0.0000482 #> 3 EUR 0.000394 #> 4 AFR 0.000396"},{"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.000448 #> 2 EUR NEA 0.000752 #> 3 AFR NEA 0.000774 #> 4 CH NEA 0.00402 #> 5 CH EUR 0.00403 #> 6 AFR CH 0.00404"},{"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\", parent = \"ancestor\", 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 │ 93║ #> ╟───────────────┼─────────╢ #> ║Sequence Length│ 100000║ #> ╟───────────────┼─────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼─────────╢ #> ║Sample Nodes │ 432║ #> ╟───────────────┼─────────╢ #> ║Total Size │205.9 KiB║ #> ╚═══════════════╧═════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │1213│37.9 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 724│72.5 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 944│35.7 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 7│ 2.7 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 3│36.7 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 #> slendr 'nodes' object #> --------------------- #> times are expressed in a backward time direction #> #> summary of the table data contents: #> AFR - 5 'sampled', 5 'remembered', 5 'retained', 5 'alive' individuals #> EUR - 79 'sampled', 79 'remembered', 30 'retained', 30 'alive' individuals #> OOA - 31 'sampled', 31 'remembered', NA 'retained', 0 'alive' individuals #> ANA - 48 'sampled', 48 'remembered', NA 'retained', 0 'alive' individuals #> EHG - 44 'sampled', 44 'remembered', NA 'retained', 0 'alive' individuals #> YAM - 9 'sampled', 9 'remembered', NA 'retained', 0 'alive' individuals #> #> total: #> - 216 'sampled' individuals #> - 216 'remembered' individuals #> - 508 'retained' individuals #> - 35 'alive' individuals #> --------------------- #> oldest sampled individual: 40000 time units 'before present' #> youngest sampled individual: 0 time units 'before present' #> #> oldest node: 252014.9 time units 'before present' #> youngest node: 0 time units 'before present' #> --------------------- #> overview of the underlying sf object: #> #> # A tibble: 944 × 13 #> name pop node_id time time_ts…¹ location sampled remembered #> #> 1 AFR_1 AFR 362 0 0 (3072714 315424) TRUE TRUE #> 2 AFR_1 AFR 363 0 0 (3072714 315424) TRUE TRUE #> 3 AFR_2 AFR 364 0 0 (2898146 1202818) TRUE TRUE #> 4 AFR_2 AFR 365 0 0 (2898146 1202818) TRUE TRUE #> 5 AFR_3 AFR 366 0 0 (3466565 1087738) TRUE TRUE #> 6 AFR_3 AFR 367 0 0 (3466565 1087738) TRUE TRUE #> 7 AFR_4 AFR 368 0 0 (3030706 587947.3) TRUE TRUE #> 8 AFR_4 AFR 369 0 0 (3030706 587947.3) TRUE TRUE #> 9 AFR_5 AFR 370 0 0 (4464229 538126) TRUE TRUE #> 10 AFR_5 AFR 371 0 0 (4464229 538126) TRUE TRUE #> # … with 934 more rows, 5 more variables: retained , alive , #> # pedigree_id , ind_id , pop_id , and abbreviated variable #> # name ¹​time_tskit 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 154 features and 12 fields #> Active geometry column: connection #> Geometry type: LINESTRING #> Dimension: XY #> Bounding box: xmin: 2721964 ymin: 546923.8 xmax: 8458020 ymax: 4686009 #> Projected CRS: ETRS89-extended / LAEA Europe #> # A tibble: 154 × 15 #> name pop node_id level child_id parent_id child…¹ paren…² child…³ paren…⁴ #> * #> 1 EUR_67 EUR 406 1 406 450 0 1810 EUR EUR #> 2 EUR_67 EUR 406 1 406 525 0 8770 EUR ANA #> 3 EUR_67 EUR 406 2 450 525 1810 8770 EUR ANA #> 4 EUR_67 EUR 406 2 525 543 8770 9760 ANA ANA #> 5 EUR_67 EUR 406 3 543 715 9760 24130 ANA ANA #> 6 EUR_67 EUR 406 4 715 769 24130 26830 ANA ANA #> 7 EUR_67 EUR 406 4 715 774 24130 26950 ANA ANA #> 8 EUR_67 EUR 406 4 715 787 24130 27760 ANA ANA #> 9 EUR_67 EUR 406 5 769 787 26830 27760 ANA ANA #> 10 EUR_67 EUR 406 5 774 811 26950 28240 ANA OOA #> # … with 144 more rows, 5 more variables: child_location , #> # parent_location , connection , left_pos , #> # right_pos , and abbreviated variable names ¹​child_time, ²​parent_time, #> # ³​child_pop, ⁴​parent_pop filter(lineages, level == 1) #> Simple feature collection with 3 features and 12 fields #> Active geometry column: connection #> Geometry type: LINESTRING #> Dimension: XY #> Bounding box: xmin: 5202360 ymin: 2284049 xmax: 5564577 ymax: 2754068 #> Projected CRS: ETRS89-extended / LAEA Europe #> # A tibble: 3 × 15 #> name pop node_id level child_id parent_id child_…¹ paren…² child…³ paren…⁴ #> * #> 1 EUR_67 EUR 406 1 406 450 0 1810 EUR EUR #> 2 EUR_67 EUR 406 1 406 525 0 8770 EUR ANA #> 3 EUR_67 EUR 407 1 407 449 0 1810 EUR EUR #> # … with 5 more variables: child_location , #> # parent_location , connection , left_pos , #> # right_pos , and abbreviated variable names ¹​child_time, ²​parent_time, #> # ³​child_pop, ⁴​parent_pop 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: 3 × 6 #> name node_id child_id parent_id left_pos right_pos #> #> 1 EUR_67 406 406 450 0 7084 #> 2 EUR_67 406 406 525 7084 100000 #> 3 EUR_67 407 407 449 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 #> # … with 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 23425 features and 2 fields #> Geometry type: LINESTRING #> Dimension: XY #> Bounding box: xmin: 2721964 ymin: 315424 xmax: 8598650 ymax: 4914514 #> Projected CRS: ETRS89-extended / LAEA Europe #> # A tibble: 23,425 × 3 #> connection child_time parent_time #> #> 1 (8103641 3334456, 7956278 3180199) 40000 40330 #> 2 (7956278 3180199, 8036310 1911729) 40330 43900 #> 3 (7956278 3180199, 8031610 2059804) 40330 44020 #> 4 (8036310 1911729, 8031610 2059804) 43900 44020 #> 5 (8031610 2059804, 7687313 1689532) 44020 45970 #> 6 (7687313 1689532, 7175192 1476174) 45970 47740 #> 7 (7687313 1689532, 6867500 1338048) 45970 48730 #> 8 (7175192 1476174, 6867500 1338048) 47740 48730 #> 9 (6867500 1338048, 6754277 1091742) 48730 49810 #> 10 (6754277 1091742, 3520987 724306) 49810 52900 #> # … with 23,415 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│36.8 KiB│ No║ #> ╟───────────┼──────┼────────┼────────────╢ #> ║Sites │257040│ 6.1 MiB│ No║ #> ╚═══════════╧══════╧════════╧════════════╝ msprime_nogf #> ╔═══════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤═══════════╣ #> ║Trees │ 62562║ #> ╟───────────────┼───────────╢ #> ║Sequence Length│ 100000000║ #> ╟───────────────┼───────────╢ #> ║Time Units │generations║ #> ╟───────────────┼───────────╢ #> ║Sample Nodes │ 208║ #> ╟───────────────┼───────────╢ #> ║Total Size │ 14.4 MiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤══════╤═════════╤════════════╗ #> ║Table │Rows │Size │Has Metadata║ #> ╠═══════════╪══════╪═════════╪════════════╣ #> ║Edges │246660│ 7.5 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Individuals│ 104│ 2.9 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Mutations │ 69284│ 2.4 MiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Nodes │ 32645│892.6 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Populations│ 6│414 Bytes│ Yes║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Provenances│ 2│ 3.8 KiB│ No║ #> ╟───────────┼──────┼─────────┼────────────╢ #> ║Sites │ 69263│ 1.7 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) slim_afs <- ts_afs(ts_slim, polarised = TRUE) 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/d_/hblb15pd3b94rg0v35920wd80000gn/T//Rtmp3Qwj6j/file4ac560e7c643\"); } 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 #> slendr 'nodes' object #> --------------------- #> times are expressed in a forward time direction #> #> summary of the table data contents: #> p1 - 10 'sampled', 0 'remembered', 0 'retained', 10 'alive' individuals #> p2 - 500 'sampled', 0 'remembered', 0 'retained', 500 'alive' individuals #> p3 - 2500 'sampled', 0 'remembered', 0 'retained', 2500 'alive' individuals #> p4 - 10000 'sampled', 0 'remembered', 0 'retained', 10000 'alive' individuals #> #> total: #> - 13010 'sampled' individuals #> - 0 'remembered' individuals #> - 0 'retained' individuals #> - 13010 'alive' individuals #> --------------------- #> oldest sampled individual: 0 time units 'before present' #> youngest sampled individual: 0 time units 'before present' #> #> oldest node: 0 time units 'before present' #> youngest node: 0 time units 'before present' #> --------------------- #> overview of the underlying table object: #> #> # A tibble: 26,020 × 11 #> pop node_id time time_tskit sampled remembe…¹ retai…² alive pedig…³ ind_id #> #> 1 p1 0 0 0 TRUE FALSE FALSE TRUE 2.01e7 0 #> 2 p1 1 0 0 TRUE FALSE FALSE TRUE 2.01e7 0 #> 3 p1 2 0 0 TRUE FALSE FALSE TRUE 2.01e7 1 #> 4 p1 3 0 0 TRUE FALSE FALSE TRUE 2.01e7 1 #> 5 p1 4 0 0 TRUE FALSE FALSE TRUE 2.01e7 2 #> 6 p1 5 0 0 TRUE FALSE FALSE TRUE 2.01e7 2 #> 7 p1 6 0 0 TRUE FALSE FALSE TRUE 2.01e7 3 #> 8 p1 7 0 0 TRUE FALSE FALSE TRUE 2.01e7 3 #> 9 p1 8 0 0 TRUE FALSE FALSE TRUE 2.01e7 4 #> 10 p1 9 0 0 TRUE FALSE FALSE TRUE 2.01e7 4 #> # … with 26,010 more rows, 1 more variable: pop_id , and abbreviated #> # variable names ¹​remembered, ²​retained, ³​pedigree_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) #> 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.6.2 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) #> slendr 'nodes' object #> --------------------- #> times are expressed in a backward time direction #> --------------------- #> overview of the underlying table object: #> #> # 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 #> # … with 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/d_/hblb15pd3b94rg0v35920wd80000gn/T//Rtmp3Qwj6j/file4ac535ddfbfa\"); } ts <- ts_load(spatial_trees_file) %>% ts_simplify() data <- ts_nodes(ts) data #> slendr 'nodes' object #> --------------------- #> times are expressed in a forward time direction #> #> summary of the table data contents: #> p1 - 500 'sampled', 0 'remembered', 500 'retained', 500 'alive' individuals #> #> total: #> - 500 'sampled' individuals #> - 0 'remembered' individuals #> - 895 'retained' individuals #> - 500 'alive' individuals #> --------------------- #> oldest sampled individual: 0 time units 'before present' #> youngest sampled individual: 0 time units 'before present' #> #> oldest node: 8463 time units 'before present' #> youngest node: 0 time units 'before present' #> --------------------- #> overview of the underlying sf object: #> #> # A tibble: 1,955 × 12 #> pop node_id time time_…¹ location sampled remembered retai…² #> #> 1 p1 0 0 0 (0.904485 0.0777489) TRUE FALSE TRUE #> 2 p1 1 0 0 (0.904485 0.0777489) TRUE FALSE TRUE #> 3 p1 2 0 0 (0.668828 0.5246381) TRUE FALSE TRUE #> 4 p1 3 0 0 (0.668828 0.5246381) TRUE FALSE TRUE #> 5 p1 4 0 0 (0.7707701 0.1518462) TRUE FALSE TRUE #> 6 p1 5 0 0 (0.7707701 0.1518462) TRUE FALSE TRUE #> 7 p1 6 0 0 (0.7617792 0.2616453) TRUE FALSE TRUE #> 8 p1 7 0 0 (0.7617792 0.2616453) TRUE FALSE TRUE #> 9 p1 8 0 0 (0.9807475 0.04223008) TRUE FALSE TRUE #> 10 p1 9 0 0 (0.9807475 0.04223008) TRUE FALSE TRUE #> # … with 1,945 more rows, 4 more variables: alive , pedigree_id , #> # ind_id , pop_id , and abbreviated variable names ¹​time_tskit, #> # ²​retained 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":[]},{"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) #> OGR data source with driver: ESRI Shapefile #> Source: \"/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpOREb1U/naturalearth\", layer: \"ne_110m_land\" #> with 127 features #> It has 3 fields 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) #> OGR data source with driver: ESRI Shapefile #> Source: \"/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpOREb1U/naturalearth\", layer: \"ne_110m_land\" #> with 127 features #> It has 3 fields 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 = m, 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\")) tree <- ts_phylo(ts_small, i = 20) #> 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":"","code":"library(ggtree) #> ggtree v3.6.2 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(data = filter(nodes, is.na(name)), aes(color = pop, shape = pop), size = 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\", shape = \"none\") + 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/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 (2023). slendr: Simulation Framework Spatiotemporal Population Genetics. R package version 0.4.0.9000, https://github.com/bodkan/slendr.","code":"@Manual{, title = {slendr: A Simulation Framework for Spatiotemporal Population Genetics}, author = {Martin Petr}, year = {2023}, note = {R package version 0.4.0.9000}, 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 preprint bioRxiv website.","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). software active development! like stay updated: Click “Watch” button project’s GitHub website. Follow Twitter posting progress updates. 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) # 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\", parent = \"ancestor\", 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 preprint 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","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 all dependencies are available for slendr examples — check_dependencies","title":"Check that all dependencies are available for slendr examples — check_dependencies","text":"Check dependencies available slendr examples","code":""},{"path":"https://www.slendr.net/reference/check_dependencies.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Check that all dependencies are available for slendr examples — check_dependencies","text":"","code":"check_dependencies(python = FALSE, slim = FALSE)"},{"path":"https://www.slendr.net/reference/check_dependencies.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Check that all dependencies are available for slendr examples — check_dependencies","text":"python slendr Python environment required? slim SLiM required?","code":""},{"path":"https://www.slendr.net/reference/check_dependencies.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Check that all dependencies are available for slendr examples — check_dependencies","text":"return value. Called result error message particular software dependency missing example run.","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) # make sure dependencies are 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/msprime-1.2.0_tskit-0.5.2_pyslim-1.0/bin/python #> Python version: 3.8.15 | packaged by conda-forge | (default, Nov 22 2022, 08:49:06) [Clang 14.0.6 ] #> #> slendr requirements: #> - tskit: version 0.5.2 ✓ #> - msprime: version 1.2.0 ✓ #> - pyslim: version 1.0 ✓"},{"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":"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\") #> OGR data source with driver: ESRI Shapefile #> Source: \"/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpW5oB0n/naturalearth\", layer: \"ne_110m_land\" #> with 127 features #> It has 3 fields"},{"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 )"},{"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 (missing, SLiM's seed used) 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)?","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)","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) # make sure dependencies are 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 │ 37.4 KiB║ #> ╚═══════════════╧═══════════╝ #> ╔═══════════╤════╤═════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪═════════╪════════════╣ #> ║Edges │ 458│ 14.3 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Individuals│ 115│ 3.2 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Mutations │ 0│ 16 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Nodes │ 459│ 12.6 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, log = FALSE)"},{"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) log y-axis plotted log scale? Useful models long time-scales.","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) # make sure dependencies are 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 = \"ancestor\", 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 \"ancestor\" (indicating 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.","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, ...) # S3 method for slendr_nodes 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) # make sure dependencies are 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\") #> OGR data source with driver: ESRI Shapefile #> Source: \"/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpW5oB0n/naturalearth\", layer: \"ne_110m_land\" #> with 127 features #> It has 3 fields"},{"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.","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":"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, 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 (missing, SLiM's seed used) 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 Optional way specify path appropriate SLiM binary (useful slim binary $PATH).","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)","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) # make sure dependencies are 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 │ 1046║ #> ╟───────────────┼─────────╢ #> ║Total Size │319.5 KiB║ #> ╚═══════════════╧═════════╝ #> ╔═══════════╤════╤═════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪═════════╪════════════╣ #> ║Edges │1914│ 59.8 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Individuals│1344│133.0 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Nodes │1915│ 71.7 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Populations│ 4│ 2.5 KiB│ Yes║ #> ╟───────────┼────┼─────────┼────────────╢ #> ║Provenances│ 1│ 33.6 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/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","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 = FALSE )"},{"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 FALSE (default) allele frequency spectrum folded (.e. counts depend knowing allele ancestral)","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","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, please see tskit manual https://tskit.dev/tskit/docs/stable/python-api.html","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) # make sure dependencies are 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.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, mutate = TRUE, 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] 4 2 0 0 1 0 0 1 0 20 0 0 0 0 0 0 0 0 0 0"},{"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) # make sure dependencies are 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.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, simplify = TRUE) # 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: 93 × 12 #> name pop node_id level child_id parent_id child_…¹ paren…² child…³ paren…⁴ #> #> 1 EUR_1 EUR 16 1 16 37 0 2690 EUR EUR #> 2 EUR_1 EUR 16 1 16 38 0 2930 EUR EUR #> 3 EUR_1 EUR 16 1 16 40 0 4250 EUR EUR #> 4 EUR_1 EUR 16 2 37 38 2690 2930 EUR EUR #> 5 EUR_1 EUR 16 2 38 42 2930 6440 EUR EUR #> 6 EUR_1 EUR 16 2 38 47 2930 7730 EUR EUR #> 7 EUR_1 EUR 16 2 38 48 2930 8210 EUR EUR #> 8 EUR_1 EUR 16 2 38 49 2930 8300 EUR EUR #> 9 EUR_1 EUR 16 2 38 52 2930 10280 EUR EUR #> 10 EUR_1 EUR 16 2 40 42 4250 6440 EUR EUR #> # … with 83 more rows, 2 more variables: left_pos , right_pos , and #> # abbreviated variable names ¹​child_time, ²​parent_time, ³​child_pop, #> # ⁴​parent_pop"},{"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) # make sure dependencies are 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.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, simplify = TRUE) 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) # make sure dependencies are 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.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, simplify = TRUE) # 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: 2 × 12 #> name pop node_id level child_id parent_id child_t…¹ paren…² child…³ paren…⁴ #> #> 1 NEA_1 NEA 62 1 0 62 70000 70040 NEA NEA #> 2 NEA_1 NEA 62 1 1 62 70000 70040 NEA NEA #> # … with 2 more variables: left_pos , right_pos , and abbreviated #> # variable names ¹​child_time, ²​parent_time, ³​child_pop, ⁴​parent_pop"},{"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) # make sure dependencies are 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.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, mutate = TRUE, 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.0000442 #> 2 AFR NEA 0.000383 #> 3 EUR NEA 0.000387 #> 4 CH NEA 0.00412 #> 5 AFR CH 0.00415 #> 6 CH EUR 0.00416"},{"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) # make sure dependencies are 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.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, mutate = TRUE, 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 AFR 0 #> 2 CH 0 #> 3 NEA 0.000004 #> 4 EUR 0.00000484"},{"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 = 1500, height = 500, labels = FALSE, sampled_only = TRUE, ... )"},{"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. ... 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) # make sure dependencies are 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.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, simplify = TRUE) # 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\") #> Error in ts_draw(tree, time_scale = \"rank\"): For plotting trees using the native SVG tskit capabilities, please #> install the R package rsvg by calling `install.packages(\"rsvg\")"},{"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) # make sure dependencies are 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.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, simplify = TRUE) # extract an annotated table with (spatio-)temporal edge information ts_edges(ts) #> # A tibble: 133 × 6 #> child_node_id parent_node_id child_time parent_time child_pop parent_pop #> #> 1 14 26 0 20 CH CH #> 2 15 26 0 20 CH CH #> 3 4 36 0 1430 AFR AFR #> 4 5 30 0 80 AFR AFR #> 5 6 27 0 20 AFR AFR #> 6 7 28 0 20 AFR AFR #> 7 8 28 0 20 AFR AFR #> 8 9 31 0 110 AFR AFR #> 9 10 32 0 140 AFR AFR #> 10 11 29 0 50 AFR AFR #> # … with 123 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://www.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":"Calculate f2, f3, f4, f4-ratio statistics","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 (following nomenclature Patterson et al. 2021)","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":"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) # make sure dependencies are 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.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, mutate = TRUE, 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.000042 # 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.0000427 # 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.000022 # 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.000199 # 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 # 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 # 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 #> 2 EUR_2 NEA_1 NEA_2 AFR_1 CH_1 0 #> 3 EUR_4 NEA_1 NEA_2 AFR_1 CH_1 0 #> 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) # make sure dependencies are 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.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, mutate = TRUE, 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.933"},{"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) # make sure dependencies are 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.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, simplify = TRUE, mutate = TRUE, mutation_rate = 1e-8, random_seed = 42) # extract the genotype matrix (this could take a long time consume lots # of memory!) gts <- ts_genotypes(ts) #> 2 multiallelic sites (0.092% out of 2184 total) detected and removed"},{"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, recapitate = FALSE, simplify = FALSE, mutate = FALSE, recombination_rate = NULL, mutation_rate = NULL, Ne = NULL, random_seed = NULL, simplify_to = NULL, keep_input_roots = FALSE, demography = 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. recapitate tree sequence recapitated? simplify tree sequence simplified set sampled individuals (explicitly recorded)? mutate tree sequence mutated? recombination_rate, Ne Arguments passed ts_recapitate mutation_rate Mutation rate passed ts_mutate random_seed Random seed passed pyslim's recapitate method simplify_to character vector individual names. NULL, remembered individuals retained. used simplify = TRUE. keep_input_roots history ancestral MRCA samples retained tree sequence? Default FALSE. demography Ancestral demography passed internally msprime.sim_ancestry() (see msprime's documentation mode detail)","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) # make sure dependencies are 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.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, simplify = 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, recapitate = TRUE, simplify = TRUE, recombination_rate = 1e-8, Ne = 10000, random_seed = 42) # load tree sequence, recapitate it, simplify it and overlay neutral mutations ts <- ts_load(slendr_ts, model, recapitate = TRUE, simplify = TRUE, random_seed = 42, recombination_rate = 1e-8, Ne = 10000, mutation_rate = 1e-8) ts #> ╔════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤════════╣ #> ║Trees │ 24║ #> ╟───────────────┼────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼────────╢ #> ║Sample Nodes │ 26║ #> ╟───────────────┼────────╢ #> ║Total Size │58.6 KiB║ #> ╚═══════════════╧════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 133│ 4.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 55│ 7.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 68│ 3.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 5│ 2.6 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 4│36.6 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Sites │ 0│16 Bytes│ 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) # make sure dependencies are 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.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.3.0.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 #> #> $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 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) # make sure dependencies are 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.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 │ 24║ #> ╟───────────────┼─────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼─────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼─────────╢ #> ║Sample Nodes │ 26║ #> ╟───────────────┼─────────╢ #> ║Total Size │188.9 KiB║ #> ╚═══════════════╧═════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 133│ 4.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 55│ 7.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │2187│80.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 68│ 3.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 4│ 2.5 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 3│34.7 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Sites │2184│53.3 KiB│ No║ #> ╚═══════════╧════╧════════╧════════════╝ #>"},{"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) # make sure dependencies are 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.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, simplify = TRUE) # extract an annotated table with (spatio-)temporal node information ts_nodes(ts) #> slendr 'nodes' object #> --------------------- #> times are expressed in a backward time direction #> #> summary of the table data contents: #> CH - 1 'sampled', 1 'remembered', 1 'retained', 1 'alive' individuals #> AFR - 5 'sampled', 5 'remembered', 5 'retained', 5 'alive' individuals #> EUR - 5 'sampled', 5 'remembered', 5 'retained', 5 'alive' individuals #> NEA - 2 'sampled', 2 'remembered', NA 'retained', 0 'alive' individuals #> #> total: #> - 13 'sampled' individuals #> - 13 'remembered' individuals #> - 42 'retained' individuals #> - 11 'alive' individuals #> --------------------- #> oldest sampled individual: 70000 time units 'before present' #> youngest sampled individual: 0 time units 'before present' #> #> oldest node: 6000170 time units 'before present' #> youngest node: 0 time units 'before present' #> --------------------- #> overview of the underlying table object: #> #> # A tibble: 68 × 12 #> name pop node_id time time_tskit sampled remembered retai…¹ alive pedig…² #> #> 1 CH_1 CH 14 0 0 TRUE TRUE TRUE TRUE 5520343 #> 2 CH_1 CH 15 0 0 TRUE TRUE TRUE TRUE 5520343 #> 3 AFR_1 AFR 4 0 0 TRUE TRUE TRUE TRUE 5520350 #> 4 AFR_1 AFR 5 0 0 TRUE TRUE TRUE TRUE 5520350 #> 5 AFR_2 AFR 6 0 0 TRUE TRUE TRUE TRUE 5520351 #> 6 AFR_2 AFR 7 0 0 TRUE TRUE TRUE TRUE 5520351 #> 7 AFR_3 AFR 8 0 0 TRUE TRUE TRUE TRUE 5520352 #> 8 AFR_3 AFR 9 0 0 TRUE TRUE TRUE TRUE 5520352 #> 9 AFR_4 AFR 10 0 0 TRUE TRUE TRUE TRUE 5520357 #> 10 AFR_4 AFR 11 0 0 TRUE TRUE TRUE TRUE 5520357 #> # … with 58 more rows, 2 more variables: ind_id , pop_id , and #> # abbreviated variable names ¹​retained, ²​pedigree_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 (one-based indexing), mode = \"position\", tree covering -th base simulated genome returned. 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) # make sure dependencies are 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.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, simplify = TRUE) # 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 25 internal nodes. #> #> Tip labels: #> 25 (EUR_5), 24 (EUR_5), 23 (EUR_4), 22 (EUR_4), 21 (EUR_3), 20 (EUR_3), ... #> Node labels: #> 67, 27, 26, 29, 30, 31, ... #> #> 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","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) # make sure dependencies are 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.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 │ 24║ #> ╟───────────────┼────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼────────╢ #> ║Sample Nodes │ 26║ #> ╟───────────────┼────────╢ #> ║Total Size │58.1 KiB║ #> ╚═══════════════╧════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 133│ 4.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 55│ 7.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 68│ 3.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 5│ 2.6 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 3│36.1 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) # make sure dependencies are 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.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, simplify = TRUE) # 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) # make sure dependencies are 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.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) # make sure dependencies are 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.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, mutate = TRUE, 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 0 #> 2 CH 0 #> 3 EUR 8 #> 4 NEA 3"},{"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)"},{"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.","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) # make sure dependencies are 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.trees\", package = \"slendr\") model <- read_model(path = system.file(\"extdata/models/introgression\", package = \"slendr\")) ts <- ts_load(slendr_ts, model) ts #> ╔════════════════════════╗ #> ║TreeSequence ║ #> ╠═══════════════╤════════╣ #> ║Trees │ 24║ #> ╟───────────────┼────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼────────╢ #> ║Sample Nodes │ 26║ #> ╟───────────────┼────────╢ #> ║Total Size │55.8 KiB║ #> ╚═══════════════╧════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 133│ 4.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 55│ 7.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 68│ 3.2 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 4│ 2.5 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 2│34.0 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 │ 13║ #> ╟───────────────┼────────╢ #> ║Sequence Length│ 500000║ #> ╟───────────────┼────────╢ #> ║Time Units │ ticks║ #> ╟───────────────┼────────╢ #> ║Sample Nodes │ 14║ #> ╟───────────────┼────────╢ #> ║Total Size │50.1 KiB║ #> ╚═══════════════╧════════╝ #> ╔═══════════╤════╤════════╤════════════╗ #> ║Table │Rows│Size │Has Metadata║ #> ╠═══════════╪════╪════════╪════════════╣ #> ║Edges │ 68│ 2.1 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Individuals│ 29│ 4.6 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Migrations │ 0│ 8 Bytes│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Mutations │ 0│ 1.2 KiB│ No║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Nodes │ 36│ 2.0 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Populations│ 4│ 2.5 KiB│ Yes║ #> ╟───────────┼────┼────────┼────────────╢ #> ║Provenances│ 3│34.5 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.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, simplify = TRUE, mutate = TRUE, mutation_rate = 1e-8, random_seed = 42) # get the 'raw' tskit table of individuals ts_table(ts, \"individuals\") #> # A tibble: 55 × 11 #> ind_id time pedigree_id raste…¹ raste…² pop_id alive remem…³ retai…⁴ sampled #> #> 1 0 -10 5520343 0 0 0 TRUE TRUE TRUE TRUE #> 2 1 -10 5520350 0 0 1 TRUE TRUE TRUE TRUE #> 3 2 -10 5520351 0 0 1 TRUE TRUE TRUE TRUE #> 4 3 -10 5520352 0 0 1 TRUE TRUE TRUE TRUE #> 5 4 -10 5520357 0 0 1 TRUE TRUE TRUE TRUE #> 6 5 -10 5520358 0 0 1 TRUE TRUE TRUE TRUE #> 7 6 -10 5520506 0 0 3 TRUE TRUE TRUE TRUE #> 8 7 -10 5520601 0 0 3 TRUE TRUE TRUE TRUE #> 9 8 -10 5520655 0 0 3 TRUE TRUE TRUE TRUE #> 10 9 -10 5520773 0 0 3 TRUE TRUE TRUE TRUE #> # … with 45 more rows, 1 more variable: time_tskit , and abbreviated #> # variable names ¹​raster_x, ²​raster_y, ³​remembered, ⁴​retained # get the 'raw' tskit table of edges ts_table(ts, \"edges\") #> # A tibble: 133 × 5 #> id child parent left right #> #> 1 0 14 26 0 500000 #> 2 1 15 26 0 500000 #> 3 2 6 27 0 500000 #> 4 3 13 27 0 500000 #> 5 4 7 28 0 500000 #> 6 5 8 28 0 500000 #> 7 6 11 29 0 500000 #> 8 7 12 29 0 500000 #> 9 8 5 30 0 500000 #> 10 9 29 30 0 500000 #> # … with 123 more rows # get the 'raw' tskit table of nodes ts_table(ts, \"nodes\") #> # A tibble: 68 × 5 #> node_id ind_id pop_id time time_tskit #> #> 1 0 18 2 70010 2334 #> 2 1 18 2 70010 2334 #> 3 2 20 2 40010 1334 #> 4 3 20 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 #> # … with 58 more rows # get the 'raw' tskit table of mutations ts_table(ts, \"mutations\") #> # A tibble: 2,187 × 5 #> id site node time time_tskit #> #> 1 0 0 66 757010. 25234. #> 2 1 1 64 575160. 19172. #> 3 2 2 26 3622440. 120748. #> 4 3 3 66 693873. 23129. #> 5 4 4 63 220620. 7354. #> 6 5 5 66 5179605. 172654. #> 7 6 6 66 5212483. 173750. #> 8 7 7 66 2373328. 79111. #> 9 8 8 64 477414. 15914. #> 10 9 9 26 1158846. 38629. #> # … with 2,177 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) # make sure dependencies are 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.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, mutate = TRUE, 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 -0.619 #> 2 nea 2.01"},{"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 (one-based indexing), mode = \"position\", tree covering -th base simulated genome returned. 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) # make sure dependencies are 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.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, simplify = TRUE) # extract the first tree in the tree sequence tree <- ts_tree(ts, i = 1) # extract the tree at a position 100000bp 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\") #> OGR data source with driver: ESRI Shapefile #> Source: \"/private/var/folders/d_/hblb15pd3b94rg0v35920wd80000gn/T/RtmpW5oB0n/naturalearth\", layer: \"ne_110m_land\" #> with 127 features #> It has 3 fields"},{"path":"https://www.slendr.net/news/index.html","id":"slendr-development-version","dir":"Changelog","previous_headings":"","what":"slendr (development version)","title":"slendr (development version)","text":"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. named list provided sample_sets = argument oneway statistic function, names used set column resulting data frame even single samples used. (#2a6781) 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)","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":""}] diff --git a/man/figures/README-plot_gif-1.gif b/man/figures/README-plot_gif-1.gif index 1fea9d8f3..851224012 100644 Binary files a/man/figures/README-plot_gif-1.gif and b/man/figures/README-plot_gif-1.gif differ diff --git a/man/figures/README-plot_popmaps-1.png b/man/figures/README-plot_popmaps-1.png index 84aa4e38a..ff0a6deb9 100644 Binary files a/man/figures/README-plot_popmaps-1.png and b/man/figures/README-plot_popmaps-1.png differ diff --git a/man/figures/README-plot_regions-1.png b/man/figures/README-plot_regions-1.png index 31c97267e..3d0f2fb35 100644 Binary files a/man/figures/README-plot_regions-1.png and b/man/figures/README-plot_regions-1.png differ diff --git a/man/figures/README-plot_world-1.png b/man/figures/README-plot_world-1.png index dbea9446c..fa23bc110 100644 Binary files a/man/figures/README-plot_world-1.png and b/man/figures/README-plot_world-1.png differ diff --git a/vignettes/vignette-00-installation.Rmd b/vignettes/vignette-00-installation.Rmd index 29dc95395..64bbb39eb 100644 --- a/vignettes/vignette-00-installation.Rmd +++ b/vignettes/vignette-00-installation.Rmd @@ -11,11 +11,11 @@ vignette: > *slendr* is available on the CRAN R package repository. As such, you can install it simply by executing `install.packages("slendr")` in your R console. -If you want (or need) to get its development version, you can install it directly from GitHub by executing `devtools::install_github("bodkan/slendr")`** via the R package *devtools* ( `install.packages("devtools")`). In fact, if you decide to try *slendr*, please make sure to update it regularly and keep an eye on the [changelog](https://www.slendr.net/news/index.html) on a regular basis! +If you want (or need) to get its development version, you can install it directly from GitHub by executing `devtools::install_github("bodkan/slendr")` via the R package *devtools* (you can gen *devtools* by running `install.packages("devtools")`). In fact, if you decide to try *slendr*, please make sure to update it regularly and keep an eye on the [changelog](https://www.slendr.net/news/index.html) on a regular basis! This is where you can find information about latest bugfixes and potential breaking changes. Once you install *slendr*, **calling `library(slendr)` will check that all software dependencies are available**. If they are not, the R package will provide a brief helpful guide on how to resolve potential issues. The rest of this vignette talks about the necessary software dependencies in a bit more detail. -**Please note that *slendr* is only supported on macOS and Linux at the moment.** However, because *slendr*'s software dependencies are already available on Windows, I hope to make the R package fully portable as soon as I get access to a Windows machine to do proper testing on. If you are a Windows user and would like to help, [please get in touch](https://www.bodkan.net/)! +**Please note that *slendr* is fully supported only on macOS and Linux at the moment.** That said, there is an experimental support for running coalescent simulation via _slendr_'s Python backend `msprime()` and for analyzing tree-sequence outputs using its _tskit_ interface. ## Software dependencies @@ -29,7 +29,7 @@ Once you install *slendr*, **calling `library(slendr)` will check that all softw All three are widely used in their respective fields and, as such, are easily obtainable on all major operating systems (see below for more information on how to troubleshoot potential problems). -**Note that depending on your use case, not all three sets of dependencies will be necessarily needed.** If you're not going to be running forward spatial simulations, you don't need SLiM. If you don't want to analyze tree sequences in R, you won't need *slendr*'s Python dependencies. +**Note that depending on your use case, not all three sets of dependencies will be necessarily needed.** If you're not going to be running forward spatial simulations, you don't need SLiM. If you don't want to analyze tree sequences in R, you won't necesarily need *slendr*'s Python dependencies. In this vignette, I will briefly explain how to get all *slendr'*s software dependencies installed. That said, note that under normal circumstances (with the exception of SLiM), no manual installation of individual dependencies is required. @@ -65,9 +65,7 @@ Setting up an isolated Python environment with specific version of Python packag In order to make sure that the R package has the most appropriate version of Python available, with the correct versions of all of its Python module dependencies, *slendr* provides a dedicated function `setup_env()` which automatically **downloads a completely separate Python distribution and installs the required versions of *tskit*, *msprime*, and *pyslim* modules into a dedicated virtual environment**. Moreover, this Python installation and virtual environment are **entirely isolated from other Python configurations that are already present on the user's system**, avoiding potential conflicts with the versions of Python and Python modules required by *slendr*. -Not only that, after this dedicated Python environment is created, **calling `library(slendr)` at any later point will activate this environment automatically**. Therefore, despite using Python for internal handling of tree-sequence data and coalescent simulation, no interaction with Python is necessary for working with *slendr* in R. - -**You only have to call `setup_env()` once!** After that, everything will be taken care of by `library(slendr)` automatically. +**Next time you call `library(slendr)`, you will need to activate this environment automatically by calling `init_env()`**. If you're not comfortable with Python you don't need to worry beyond calling `setup_env()` and `init_env()`, no interaction with Python is necessary for working with *slendr* in R. #### Information for Python experts diff --git a/vignettes/vignette-01-tutorial.Rmd b/vignettes/vignette-01-tutorial.Rmd index 8d93d2c42..16fb5089e 100644 --- a/vignettes/vignette-01-tutorial.Rmd +++ b/vignettes/vignette-01-tutorial.Rmd @@ -111,7 +111,7 @@ In addition to the overall spatial map context, we can also define smaller geogr africa <- region( "Africa", map, polygon = list(c(-18, 20), c(38, 20), c(30, 33), - c(20, 33), c(10, 38), c(-6, 36)) + c(20, 33), c(10, 38), c(-6, 35)) ) europe <- region( "Europe", map, @@ -320,15 +320,13 @@ For example, if you look at the spatial boundaries plotted above, you'll see tha gf <- gene_flow(from = eur, to = afr, rate = 0.1, start = 20000, end = 15000) ``` - Not a sufficient overlap between population ranges of EUR and AFR - at time 20000. The required overlap is 0.20 but the current overlap is - 0.000000. + 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 geneflow without spatial overlap - between populations. + 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. The error message instructs us to visually verify that this is the case, which can be done by *slendr*'s `plot_map()` function and the optional parameter `pop_facets = F` (which is set to `TRUE` by default). diff --git a/vignettes/vignette-06-locations.Rmd b/vignettes/vignette-06-locations.Rmd index 9917fc841..035e7faa7 100644 --- a/vignettes/vignette-06-locations.Rmd +++ b/vignettes/vignette-06-locations.Rmd @@ -64,7 +64,7 @@ map <- world( africa <- region( "Africa", map, polygon = list(c(-18, 20), c(38, 20), c(30, 33), - c(20, 33), c(10, 38), c(-6, 36)) + c(20, 33), c(10, 38), c(-6, 35)) ) europe <- region( "Europe", map, @@ -138,7 +138,7 @@ model <- compile_model( populations = list(afr, ooa, ehg, eur, ana, yam), gene_flow = gf, generation_time = 30, resolution = 10e3, - competition = 130e3, mating = 100e3, dispersal = 70e3 + competition = 150e3, mating = 120e3, dispersal = 90e3 ) ``` @@ -161,7 +161,7 @@ Now we will schedule the sampling of a single individual from each population ev ```{r} # one ancient individual every two thousand years ancient <- schedule_sampling(model, - times = seq(40000, 1, by = -1000), + times = seq(40000, 1, by = -500), list(ooa, 1), list(ehg, 1), list(eur, 1), list(ana, 1), list(yam, 1)) @@ -276,7 +276,7 @@ Because we record the time and the location of every individual that happens to The simplest use case is determining the locations and times of every single node in the genealogical history of an individual along the tree sequence (it is possible to recover ancestral relationships for multiple samples at once too): ```{r} -ind <- "EUR_42" +ind <- "EUR_67" lineages <- ts_ancestors(ts, ind, verbose = TRUE) ``` @@ -302,19 +302,22 @@ counts <- filter(lineages, name == ind, level == 1) %>% as.data.frame() %>% coun As we mentioned above, there are three columns encoding spatial information: `location` and `parent_location` carry information about the location of the child and parent node (`POINT` class), and the `connection` object (`LINESTRING` class) contains the line connecting the two nodes (both a branch in the tree sequence and also the spatial connection). We can plot all three spatial features (two points and a line) individually on a map: ```{r level1_branches} -level1_branches <- ts_ancestors(ts, "EUR_3") %>% filter(level == 1) +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[, ]$parent_location, shape = 20, color = level1_branches[, ]$node_id) + geom_sf(data = level1_branches[, ]$connection, linetype = 3) + + geom_sf(data = level1_branches[, ]$parent_location, shape = 20, color = "blue") + theme_bw() + - scale_color_manual(values = c("darkblue", "lightblue")) + ggtitle("Parent nodes (blue) of a focal individual (red)") ``` -In the figure above we can see the red focal node and its immediate parents in the tree sequence genealogy (in the coalescent sense, not immediate parents of that individual!). +In the figure above we can see the red focal node and its immediate parents in the tree sequence genealogy (in the coalescent sense, not immediate parents of that individual!). In case you're surprised to see more than two parents, recall that recombination events make the history encoded by a sample more complicated as it can involve more ancestors as we "move up" a tree from a sample, not just two ancestors. Looking at our example in more detail, we can see that one node (chromosome) of the individual "EUR_67" has two ancestors, each covering a portion of that individuals chromosome, with the other chromosome being covered by a single ancestor (columns `left_pos` and `right_pos`): + +```{r} +as_tibble(level1_branches)[, c("name", "node_id", "child_id", "parent_id", "left_pos", "right_pos")] +``` A more convenient way to do this analysis is a companion function to `ts_ancestors()` called `plot_ancestors()`. This function accepts an `sf` object with the spatial branching data created by `ts_ancestors()` and plots the paths between nodes on a map leading from a focal node up to the root(s) of the tree sequence (instead of just paths to immediate parents shown in the previous figure). In this case, because we are working with a single diploid individual, we get two sets of paths for each of its nodes (chromosomes) and plot them in two facets: @@ -345,14 +348,15 @@ A more convenient way to do this analysis is a companion function to `ts_ancesto ```{r plot_ancestors_time} ggplot() + geom_sf(data = map) + - geom_sf(data = lineages, size = 0.5, aes(alpha = parent_time)) + + 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) + facet_grid(. ~ node_id) + + ggtitle("Ancestry encoded by two nodes (chromosomes) of EUR_67") ``` You can compare this result to the animation which recapitulates the simulation, presented in [the first vignette](vignette-01-tutorial.html). @@ -399,24 +403,25 @@ ts_samples(ts) %>% filter(pop == "ANA") ``` ```{r, include = FALSE} -ana_ind <- ts_samples(ts) %>% filter(name == "ANA_24") +ana_ind <- ts_samples(ts) %>% filter(name == "ANA_45") ``` Can we see a hint of the spatial dynamics of Anatolians in the spatio-temporal distribution of ancestral node locations of one of the sampled individuals? Let's pick the last individual and immediately plot its spatial ancestry tidyverse-style using the pipe operator `%>%`: ```{r, plot_ancestors_levels_ana} -lineages <- ts_ancestors(ts, "ANA_24") +lineages <- ts_ancestors(ts, "ANA_45") ggplot() + geom_sf(data = map) + - geom_sf(data = lineages, size = 0.5, aes(alpha = parent_time)) + + 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_24"), size = 3) + + 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) + facet_grid(. ~ node_id) + + ggtitle("Ancestry encoded by two nodes (chromosomes) of ANA_45") ``` As we might expect given the late age of the sample, its position in the map above (red crossed circle) is not in Anatolia but in Europe because it represents one of the descendants of migrants who moved from Anatolia into Europe. This can be clearly seen in the position of its parental nodes in the tree sequence: these nodes represent real individuals who lived at some point in the past, and we can see that they did, indeed, lived in Anatolia. @@ -466,7 +471,6 @@ Let's try to summarise the information about distances "traveled" by nodes in di ```{r, smooth_distance_fits} distances_long %>% - dplyr::filter(child_pop != "AFR") %>% 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) + diff --git a/vignettes/vignette-09-paper.Rmd b/vignettes/vignette-09-paper.Rmd index 979be8c5e..08e9aec4c 100644 --- a/vignettes/vignette-09-paper.Rmd +++ b/vignettes/vignette-09-paper.Rmd @@ -92,8 +92,8 @@ f4ratio <- ts_f4ratio( ### Complementary SLiM run from the same model ```{r, echo = FALSE, eval = eval_chunk && record_snapshot} -system(sprintf("cp -r %s %s", model$path, "/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.3/ex1")) -ts_save(ts, "/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.3/ex1.trees") +system(sprintf("cp -r %s %s", model$path, "/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.5/ex1")) +ts_save(ts, "/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.5/ex1.trees") ``` ### Plotting code @@ -151,7 +151,7 @@ p_ex1 ``` ```{r, include = FALSE, eval = eval_chunk && record_snapshot} -ggsave("/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.3/ex1.pdf", p_ex1, width = 9, height = 6, units = "in") +ggsave("/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.5/ex1.pdf", p_ex1, width = 9, height = 6, units = "in") ``` ## Example 2 (Figure 3) @@ -192,8 +192,8 @@ heterozygosity <- ts_samples(ts) %>% ```{r, echo = FALSE, eval = eval_chunk && record_snapshot} -system(sprintf("cp -r %s %s", model$path, "/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.3/ex2")) -ts_save(ts, "/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.3/ex2.trees") +system(sprintf("cp -r %s %s", model$path, "/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.5/ex2")) +ts_save(ts, "/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.5/ex2.trees") ``` ### Plotting code @@ -241,7 +241,7 @@ p_ex2 ``` ```{r, include = FALSE, eval = eval_chunk && record_snapshot} -ggsave("/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.3/ex2.pdf", p_ex2, width = 6, height = 9, units = "in") +ggsave("/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.5/ex2.pdf", p_ex2, width = 6, height = 9, units = "in") ``` ## Example 3 (Figure 4) @@ -249,7 +249,7 @@ ggsave("/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.3/ex2.pdf", ### Script from panel A ```{r, fig.keep='none'} -map <- world(xrange = c(-15, 60), yrange = c(20, 65), crs = 3035) +map <- world(xrange = c(-13, 70), yrange = c(18, 65), crs = 3035) R1 <- region( "EHG range", map, @@ -279,7 +279,7 @@ ooa_trajectory <- list(c(40, 30), c(50, 30), c(60, 40), c(45, 55)) ``` ```{r, eval = eval_chunk, fig.keep='none'} -map <- world(xrange = c(-15, 60), yrange = c(20, 65), crs = 3035) +map <- world(xrange = c(-13, 70), yrange = c(18, 65), crs = 3035) ooa <- population( "OOA", time = 50000, N = 500, remove = 23000, @@ -319,8 +319,7 @@ gf <- list( model <- compile_model( populations = list(ooa, ehg, eur, ana, yam), gene_flow = gf, generation_time = 30, resolution = 10e3, - competition = 130e3, mating = 100e3, - dispersal = 70e3, + competition = 150e3, mating = 120e3, dispersal = 90e3 ) samples <- schedule_sampling( @@ -338,10 +337,40 @@ ts <- slim( ``` ```{r, echo = FALSE, eval = eval_chunk && record_snapshot} -system(sprintf("cp -r %s %s", model$path, "/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.3/ex3")) -ts_save(ts, "/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.3/ex3.trees") +system(sprintf("cp -r %s %s", model$path, "/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.5/ex3")) +ts_save(ts, "/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.5/ex3.trees") ``` + +```{r, include=FALSE, eval=FALSE} +devtools::load_all() +init_env() +model <- read_model("/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.5/ex3") +ts <- ts_load("/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.5/ex3.trees", model = model) + +library(dplyr) +library(ggplot2) +library(purrr) +library(tidyr) +library(cowplot) +library(forcats) + +init_env() + +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() + +map <- world(xrange = c(-13, 70), yrange = c(18, 65), crs = 3035) + +e <- "EUR_578" +``` + + ### Plotting code ```{r, figure_ex3, fig.height=5, fig.width=7, eval = eval_chunk} @@ -363,75 +392,112 @@ p_ex3 ``` ```{r, include = FALSE, eval = eval_chunk && record_snapshot} -ggsave("/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.3/ex3.pdf", p_ex3, width = 9, height = 6, units = "in") +ggsave("/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.5/ex3.pdf", p_ex3, width = 9, height = 6, units = "in") ``` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +```{r, include = FALSE, eval = FALSE} +# eurs <- ts_samples(ts) %>% filter(pop == "EUR") %>% pull(name) +# # eurs <- c("EUR_542", "EUR_549", "EUR_567", "EUR_581", "EUR_582") +# eurs <- e <- c("EUR_578") + +# ############# +# ###### FOUND THE IND_578 (see anc.pdf) +# ###### actually ,keep the anc.pdf in the archive + +# # finding a EUR individual with illustratively rich spatial ancestry +# pdf("~/Desktop/anc.pdf") +# for (e in eurs) { +# ancestors <- ts_ancestors(ts, e, verbose=T) +# if (length(unique(as.character(ancestors$parent_pop))) < 5) next +# chrom_names <- stats::setNames( +# c(paste(e, "(chromosome 1, node 10)"), paste(e, "(chromosome 2, node 11)")), +# unique(ancestors$node_id) +# ) +# p_ancestors <- ggplot() + +# geom_sf(data = map) + +# geom_sf(data = ancestors, size = 0.5, alpha = 0.2) + +# 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 == e), 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 = "bottom"); print(p_ancestors) +# } +# dev.off() + + +# # finding appropriate ancestors for plotting an illustrative tree ("YAM" ancestor) +# ggplot() + +# geom_sf(data = map) + +# geom_sf(data = ancestors, size = 0.5, alpha = 0.2) + +# 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 == e), size = 1) + +# geom_sf_label(data = filter(ancestors, parent_pop == "YAM"), aes(label = parent_id), alpha = 0.5) + +# coord_sf(expand = 0) + +# labs(x = "longitude", y = "latitude") + +# theme_bw() + +# # facet_grid(. ~ node_id, labeller = labeller(node_id = chrom_names)) + +# theme(legend.position = "bottom") + +# # finding appropriate ancestors for plotting an illustrative tree ("ANA" ancestor) +# ggplot() + +# geom_sf(data = map) + +# geom_sf(data = ancestors, size = 0.5, alpha = 0.2) + +# 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 == e), size = 1) + +# geom_sf_label(data = filter(ancestors, parent_pop == "ANA"), aes(label = parent_id), alpha = 0.5) + +# coord_sf(expand = 0, xlim = c(20, 40), ylim = c(35, 45), crs = 4326) + +# labs(x = "longitude", y = "latitude") + +# theme_bw() + +# # facet_grid(. ~ node_id, labeller = labeller(node_id = chrom_names)) + +# theme(legend.position = "bottom") + +# # finding appropriate leaves for plotting an illustrative tree ("EHG" ancestor) +# ggplot() + +# geom_sf(data = map) + +# geom_sf(data = ancestors, size = 0.5, alpha = 0.2) + +# 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 == e), size = 1) + +# geom_sf_label(data = filter(ancestors, parent_pop == "EHG"), aes(label = parent_id), alpha = 0.5) + +# coord_sf(expand = 0) + +# labs(x = "longitude", y = "latitude") + +# theme_bw() + +# # facet_grid(. ~ node_id, labeller = labeller(node_id = chrom_names)) + +# theme(legend.position = "bottom") + +# ts_yam_anc <- ts_descendants(ts, x = 39806) %>% filter(!is.na(name)) %>% as.data.frame() %>% arrange(parent_time) +# ts_ana_anc <- ts_descendants(ts, x = 41734) %>% filter(!is.na(name)) %>% as.data.frame() %>% filter(grepl("ANA_", name)) +# ts_ehg_anc <- ts_descendants(ts, x = 42843) %>% filter(!is.na(name)) %>% as.data.frame( %>% arrange(parent_time)) + +# names <- c("EUR_578", ts_yam_anc$name, ts_ana_anc$name, ts_ehg_anc$name) +``` ## Example 4 (Figure 5) ### Script from panel A ```{r, eval = eval_chunk} -ts_small <- ts_simplify(ts, c("EUR_581", "ANA_120", "EHG_440", - "EUR_597", "YAM_59")) +ts_small <- ts_simplify(ts, simplify_to = c("EUR_578", "YAM_75", "ANA_163", "EHG_208")) -tree <- ts_phylo(ts_small, i = 10) +tree <- ts_phylo(ts_small, i = 20 / scaling) nodes <- ts_nodes(tree) edges <- ts_edges(tree) -ancestors <- ts_ancestors(ts, "EUR_581") +ancestors <- ts_ancestors(ts, "EUR_578") ``` ```{r, echo = FALSE, eval = eval_chunk && record_snapshot} -ts_save(ts, "/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.3/ex3_small.trees") +ts_save(ts, "/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.5/ex3_small.trees") ``` ### Plotting code -```{r, figure_ex4, eval = Sys.getenv("R_HAS_GGTREE") == TRUE && eval_chunk, fig.height=9, fig.width=7, class.source = "fold-hide"} +```{r, figure_ex4, eval = Sys.getenv("R_HAS_GGTREE") == TRUE && eval_chunk, fig.height=9, fig.width=8.5, class.source = "fold-hide"} library(ggtree) # prepare annotation table for ggtree linking R phylo node ID (not tskit integer @@ -442,7 +508,7 @@ abs_comma <- function (x, ...) { format(abs(x) / 1000, ..., scientific = FALSE, trim = TRUE) } -highlight_nodes <- as_tibble(nodes) %>% dplyr::filter(name == "EUR_581") %>% .$phylo_id +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, @@ -454,8 +520,8 @@ p_tree <- ggtree(tree, aes(color = pop, fill = pop)) %<+% df + theme_tree2() + theme(legend.position = "none") + xlab("time before present [thousand years ago]") + - scale_x_continuous(limits = c(-120000, 31000), labels = abs_comma, - breaks = -c(120, 100, 80, 60, 40, 20, 0) * 1000) + 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) @@ -471,8 +537,6 @@ nodes$label <- sapply(1:nrow(nodes), function(i) { p_map <- ggplot() + geom_sf(data = map) + geom_sf(data = edges, aes(color = parent_pop), size = 0.5) + - geom_sf(data = filter(nodes, is.na(name)), - aes(color = pop, shape = pop), size = 5) + geom_sf_label(data = nodes[!nodes$sampled, ], aes(label = node_id, fill = pop), size = 3) + geom_sf_label(data = nodes[nodes$sampled, ], @@ -481,23 +545,25 @@ p_map <- ggplot() + 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", shape = "none") + + 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_581 (node 10)", "EUR_581 (node 11)"), + 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, aes(alpha = parent_time)) + + 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_581"), size = 3) + + geom_sf(data = filter(ts_nodes(ts), name == "EUR_578"), size = 3) + coord_sf(expand = 0) + labs(x = "longitude", y = "latitude") + theme_bw() + @@ -521,5 +587,5 @@ p_ex4 ``` ```{r, include = FALSE, eval = eval_chunk && record_snapshot} -ggsave("/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.3/ex4.pdf", p_ex4, width = 7, height = 9, units = "in") +ggsave("/Users/mp/Documents/postdoc/slendr-paper/preprint_models_v0.5/ex4.pdf", p_ex4, width = 8.5, height = 9, units = "in") ```