--- title: "Building CDMetaPOP input files with the R wrapper" subtitle: "Create ClassVars, PatchVars, PopVars and RunVars objects, and launch a simulation" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Building CDMetaPOP input files in R} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set( echo = TRUE, message = FALSE, warning = FALSE, collapse = TRUE, comment = "#>" ) library(cdmetapopR) ``` # Overview CDMetaPOP input files consist of a series of connected csv files: a `RunVars.csv` naming one or more `PopVars.csv` files, each naming a `PatchVars.csv`, which in turn names a `ClassVars.csv` plus cost-distance matrices, gene frequency files, and other inputs. This wrapper is mean to help the user create and assemble these files and handle the directories and relative paths of the different input files under the hood. `cdmetapopR` represents these file types as R objects based on unique classes: | Object | File | Each row is | |---|---|---| | `ClassVars()` | `ClassVars.csv` | an age class | | `PatchVars()` | `PatchVars.csv` | a patch | | `PopVars()` | `PopVars.csv` | a batch | | `RunVars()` | `RunVars.csv` | a run | Default values for each input class match values in CDMetaPOP's own example files, each column can be modified by the user, after which the wrapper will validate everything assigned to an input object, and can hold another object wherever the inputs call for another object. 'launch_cdmetapop()' will write the entire input file directory for you, and you never have to name a csv file or manage subdirectories. If your CDMetaPOP input files already exist, you can read them in as R objects using 'read_cdmetapop()' or using the 'path' argument in each of the above functions. Here is on example that will create all necessary inputs: ```{r overview-sketch, eval=FALSE} mycv <- ClassVars() mypv <- PatchVars(class_vars = mycv) # an object, not a path mypopv <- PopVars(xyfilename = mypv) myrv <- RunVars(Popvars = mypopv) run_dir <- launch_cdmetapop(myrv, pythonFilepath = "python", CDMetaPOPFilepath = "CDMetaPOP.py") ``` Even simpler, you can run the default example simulation by just calling 'RunVars()' in the 'launch_cdmetapop()' function. ```{r launch-example, eval=FALSE} run_dir <- launch_cdmetapop(RunVars(), pythonFilepath = "python", CDMetaPOPFilepath = "CDMetaPOP.py") ``` `write_cdmetapop()` can be used to write a single object to file, `read_cdmetapop()` or the `path =` argument can be used to read an existing file in as an R object. This vignette builds a complete, valid input set from scratch. Everything except the launch itself runs as shown. # ClassVars `ClassVars.csv` holds the age-class parameters: size at age, mortality, maturation, migration probability, etc. A default call reproduces CDMetaPOP's `ClassVars_AS1.csv`, which has six age classes. ```{r classvars-default} mycv <- ClassVars() mycv$ages ``` Columns are read and written as vectors with one value per age class. Printing the object shows the table; `as.data.frame()` gives you an ordinary data frame to inspect or subset. ```{r classvars-inspect} as.data.frame(mycv)[, c("Age class", "Body Size Mean", "Age Mortality Out")] ``` Default columns can be modified when the function is called, or already created objects can be modified just like a data frame. Input values are validated immediately, so incorrect input values will be flagged immediately: ```{r classvars-modify} mycv$age_mortality_out <- c(0.6, 0.4, 0.2, 0.1, 0.1, 0.1) mycv$maturation <- c(0, 0, 0.5, 1, 1, 1) mycv$age_mortality_out # Alternatively, edit the columns at creation mycv <- ClassVars(age_mortality_out = c(0.6, 0.4, 0.2, 0.1, 0.1, 0.1), maturation = c(0, 0, 0.5, 1, 1, 1)) ``` `add_rows()` adds age classes, copying the current last row so you only edit what differs: ```{r classvars-addrow} add_rows(mycv) mycv$ages mycv$maturation ``` # PatchVars `PatchVars.csv` contains one row for each patch and includes spatial coordinates, carrying capacity, initial population size, mortality, migration, and growth parameters. The default is CDMetaPOP's seven-patch `PatchVarsS1.csv`. The `class_vars` column is where a `PatchVars` file would normally name a `ClassVars.csv`. With the wrapper, you can provide either the R object or the relative filepath: ```{r patchvars-build} mypv <- PatchVars(class_vars = mycv, genes_initialize = "random") mypv$patch_id ``` `genes_initialize = "random"` draws random starting genotypes rather than reading an allele-frequency file. Edit columns one value per patch, and add patches with `add_rows()`: ```{r patchvars-modify} mypv$k <- c(300, 300, 500, 500, 200, 200, 200) mypv$n0 <- 100 # Alternatively, mypv <- PatchVars(k = c(300, 300, 500, 500, 200, 200, 200), n0 = 100) add_rows(mypv) mypv$patch_id mypv$k ``` # Changing parameter values over time and by sex CDMetaPOP packs multiple values into one cell using delimiters, be careful to get the formatting correct. | Delimiter | Meaning | Example | |---|---|---| | | | changes over time, at the years set by `RunVars$cdclimgentime` | `"0|0.2|0.5"` | | `~` | differs by sex, in the order FXX, MXY, MYY, FYY | `"0.5~0.5"` | | `;` | multiple species, or multiple files for one field | `"popvars/speciesA.csv;popvars/speciesB.csv"` | **A delimited value is a single string, not a vector.** ```{r delimiters} # One patch's mortality changing over time: 0, then 0.2, then 0.5 mypv$mortality_out <- "0|0.2|0.5" # Eight patches, each with different moratlity values over time mypv$mortality_out <- c("0|0.2|0.2","0|0.2|0.3","0|0.2|0.4","0|0.2|0.5","0|0.2|0.6","0|0.2|0.7","0|0.2|0.8","0|0.2|0.8") # Eight patches, each with its own constant mortality mypv$mortality_out <- c(0, 0.1, 0.1, 0.2, 0.2, 0.2, 0.3, 0.3) ``` The first assigns the same three-stage schedule to every patch. The second gives each patch different values over time, and the third gives one value for each patch. Writing `c(0, 0.2, 0.5)` when you meant `"0|0.2|0.5"` won't raise any errors but is not correct and won't be caught. Each segment is validated independently, so an out-of-range value inside a delimited string is still rejected: ```{r delimiters-validated, error=TRUE} mypv$mortality_out <- "0|0.2|1.5" ``` ```{r delimiters-reset, include=FALSE} mypv$mortality_out <- c(0, 0.1, 0.1, 0.2, 0.2, 0.2, 0.3, 0.3) ``` Sex-specific values work the same way, as one `~`-delimited string: ```{r delimiters-tilde} # XX~XY mycv$sex_ratio <- "0.5~0.5" ``` # Cost-distance matrices `PopVars` has five movement fields (mating, emigration, immigration, straying and dispersal) that CDMetaPOP reads as patch-by-patch cost-distance matrices. Each accepts either a path to a csv or **a raw R matrix** which will be created and serialized for you at launch. `create_cdmat()` builds a distance matrix from patch coordinates: ```{r cdmat} coords <- as.data.frame(mypv)[, c("X", "Y")] cdmat <- create_cdmat(coords, method = "euclidean") dim(cdmat) round(cdmat[1:4, 1:4]) ``` `method = "equal"` gives every patch pair the same cost, and `method = "lcp"` computes least-cost paths across a resistance raster. See the main vignette for more on `create_cdmat()`. # PopVars `PopVars.csv` holds one row per *batch* - a set of population-level settings that CDMetaPOP runs as an independent simulation. The `xyfilename` column points at a `PatchVars` file, so hand it the object, and give the five movement fields the matrix built above: ```{r popvars-build} mypopv <- PopVars( n_batches = 1, xyfilename = mypv, mate_cdmat = cdmat, migrateout_cdmat = cdmat, migrateback_cdmat = cdmat, stray_cdmat = cdmat, disperseLocal_cdmat = cdmat, correlation_matrix = "N", subpopmort_file = "N", betaFile_selection = "N" ) ``` `"N"` is CDMetaPOP's off switch, used here for the three optional fields so that nothing outside this session is referenced. `PopVars` has 81 columns, and unlike `ClassVars`/`PatchVars` CDMetaPOP reads its headers as dictionary keys so the `PopVars()` argument and the csv column names match exactly: ```{r popvars-modify} mypopv$loci <- 4 mypopv$matemoveno <- "4" add_rows(mypopv) mypopv$popmodel <- c("packing", "logistic_back") as.data.frame(mypopv)[, c("loci", "alleles", "matemoveno", "popmodel")] ``` The second batch reuses the same `PatchVars` object with a different set of population parameters, which CDMetaPOP will run as a separate simulation. # RunVars `RunVars.csv` is the top of the file tree. Each row is a *run*, and its `Popvars` column names one `PopVars` file per species. CDMetaPOP executes every run × every batch × every Monte Carlo replicate as a separate simulation. ```{r runvars-build} myrv <- RunVars(n_runs = 1, Popvars = mypopv) myrv$runtime <- 50 myrv$output_years <- 5 myrv ``` The set of R input objects is now complete: `myrv` → `mypopv` → `mypv` → `mycv`, plus the cost matrix. Nothing has been written to disk at this point, and no file has been named. # Writing and reading single files The normal route writes everything at launch (next section). But when you want one file on its own to inspect, hand-edit, send to a collaborator, or feed it to one of the `make_*()` Shiny apps, `write_cdmetapop()` writes a single object to a csv you name: ```{r write-one} out_dir <- file.path(tempdir(), "cdmetapop_inputs") dir.create(out_dir, showWarnings = FALSE) write_cdmetapop(mycv, file.path(out_dir, "ClassVars.csv")) ``` Read one back either with `read_cdmetapop()`, or by passing `path =` to the constructor. The two are equivalent: ```{r read-two-ways} cv_a <- read_cdmetapop(file.path(out_dir, "ClassVars.csv"), type = "ClassVars") cv_b <- ClassVars(path = file.path(out_dir, "ClassVars.csv")) identical(as.data.frame(cv_a), as.data.frame(cv_b)) identical(as.data.frame(cv_a), as.data.frame(mycv)) ``` `path =` has the advantage that you can override columns as you read: ```{r read-override} cv_c <- ClassVars(path = file.path(out_dir, "ClassVars.csv"), maturation = 1) cv_c$maturation ``` The same works for all four classes. There is one important limit. `write_cdmetapop()` deliberately does **not** follow references: a cell holding a path is written verbatim, but a cell holding a live object or a raw matrix has no path to write, so it is written as `NA` with a warning: ```{r write-warning, warning=TRUE} write_cdmetapop(myrv, file.path(out_dir, "RunVars_nested.csv")) ``` A file written that way cannot be read back in immediately or launched with `launch_cdmetapop`, since `NA` is not a valid value. So `write_cdmetapop()` is more for getting an object onto disk to look at, hand-edit, or prep for a direct Python launch. # Launching a simulation `launch_cdmetapop()` takes the `RunVars` object, writes every file in the set into a fresh timestamped run directory, and calls Python to start CDMetaPOP: ```{r launch, eval=FALSE} run_dir <- launch_cdmetapop( myrv, pythonFilepath = "C:/Users/User1/anaconda3/python.exe", CDMetaPOPFilepath = "C:/Users/User1/CDMetaPOP/src/CDMetaPOP.py" ) ``` Runs can take days, so the simulation launches in the background by default and the function returns immediately. Pass `wait = TRUE` to block until it finishes. On macOS and Linux a background run opens no console window, so check CDMetaPOP's `CDmetaPOP0.log` in the output folder for progress and errors. You can also point it at a directory of existing csvs instead of an object: ```{r launch-path, eval=FALSE} launch_cdmetapop("C:/Users/User1/CDMetaPOP/example_files", wait = TRUE) ``` ## What gets written The run directory holds CDMetaPOP's canonical layout, with every cross-reference rewritten to the right relative path: ``` cdmetapop_run_20261002_143015/ ├── RunVars.csv ├── popvars/mypopv.csv ├── patchvars/mypv.csv ├── classvars/mycv.csv ├── cdmats/cdmat.csv └── manifest.csv ``` Files are named after the R variables that held the objects, so you can trace any csv back to where it came from. `manifest.csv` records that mapping explicitly: # Validation Values are checked as you assign them, against the rules in CDMetaPOP's user manual, so problems surface at the point you introduce them: ```{r validation-enum, error=TRUE} myrv$gridformat <- "csv" ``` ```{r validation-range, error=TRUE} mypv$straying_prob <- 1.5 ``` ```{r validation-length, error=TRUE} mycv$maturation <- c(0, 1) ``` Cross-file consistency is checked at launch, where the whole file set is visible at once. For example, a `PopVars` whose referenced `PatchVars` is missing something it needs. Those errors are raised before any directory is created, so a failed launch leaves nothing behind to clean up. # Reading results `launch_cdmetapop()` returns the run directory, which is what the `summary_*()` functions take. Once a run has finished: ```{r read-results, eval=FALSE} summary_pop(run_dir, type = "N_Initial") ``` Using the example output bundled with the package: ```{r read-results-live, fig.width=7, fig.height=4.5, out.width="100%"} example_out <- system.file("extdata", "Example_dat", package = "cdmetapopR") summary_pop(example_out, type = "N_Initial") ``` See the main vignette, *Reading, summarizing, customizing, and plotting CDMetaPOP outputs*, for the full set of summary and plotting functions. ```{r cleanup, include=FALSE} unlink(out_dir, recursive = TRUE) ```