diff --git a/RcppTskit/R/Class-TableCollection.R b/RcppTskit/R/Class-TableCollection.R
index 80dd49e..ed896b1 100644
--- a/RcppTskit/R/Class-TableCollection.R
+++ b/RcppTskit/R/Class-TableCollection.R
@@ -205,10 +205,10 @@ TableCollection <- R6Class(
#' @description Add a row to the nodes table.
#' @param flags integer flags for the new node.
#' @param time numeric time value for the new node.
- #' @param population integer population row ID (0-based, or \code{-1});
- #' \code{NULL} maps to \code{-1}.
- #' @param individual integer individual row ID (0-based, or \code{-1});
- #' \code{NULL} maps to \code{-1}.
+ #' @param population integer population row ID (0-based);
+ #' use \code{-1} if not known - \code{NULL} maps to \code{-1}.
+ #' @param individual integer individual row ID (0-based);
+ #' use \code{-1} if not known - \code{NULL} maps to \code{-1}.
#' @param metadata for the new node; accepts \code{NULL},
#' a raw vector, or a character of length 1.
#' @details See the \code{tskit Python} equivalent at
@@ -285,17 +285,16 @@ TableCollection <- R6Class(
#' @examples
#' ts_file <- system.file("examples/test.trees", package = "RcppTskit")
#' tc <- tc_load(ts_file)
- #' parent <- 0L
- #' child <- 1L
+ #' child <- tc$node_table_add_row(time = 0.0)
#' n_before <- tc$num_edges()
#' new_id <- tc$edge_table_add_row(
- #' left = 0, right = 1, parent = parent, child = child
+ #' left = 0, right = 50, parent = 16L, child = child
#' )
#' new_id <- tc$edge_table_add_row(
- #' left = 1, right = 2, parent = parent, child = child, metadata = "abc"
+ #' left = 50, right = 75, parent = 17L, child = child, metadata = "abc"
#' )
#' new_id <- tc$edge_table_add_row(
- #' left = 2, right = 3, parent = parent, child = child, metadata = charToRaw("cba")
+ #' left = 75, right = 100, parent = 18L, child = child, metadata = charToRaw("cba")
#' )
#' n_after <- tc$num_edges()
edge_table_add_row = function(
diff --git a/RcppTskit/man/TableCollection.Rd b/RcppTskit/man/TableCollection.Rd
index 513f731..8f54de0 100644
--- a/RcppTskit/man/TableCollection.Rd
+++ b/RcppTskit/man/TableCollection.Rd
@@ -125,17 +125,16 @@ tc$num_edges()
ts_file <- system.file("examples/test.trees", package = "RcppTskit")
tc <- tc_load(ts_file)
-parent <- 0L
-child <- 1L
+child <- tc$node_table_add_row(time = 0.0)
n_before <- tc$num_edges()
new_id <- tc$edge_table_add_row(
- left = 0, right = 1, parent = parent, child = child
+ left = 0, right = 50, parent = 16L, child = child
)
new_id <- tc$edge_table_add_row(
- left = 1, right = 2, parent = parent, child = child, metadata = "abc"
+ left = 50, right = 75, parent = 17L, child = child, metadata = "abc"
)
new_id <- tc$edge_table_add_row(
- left = 2, right = 3, parent = parent, child = child, metadata = charToRaw("cba")
+ left = 75, right = 100, parent = 18L, child = child, metadata = charToRaw("cba")
)
n_after <- tc$num_edges()
@@ -619,11 +618,11 @@ Add a row to the nodes table.
\item{\code{time}}{numeric time value for the new node.}
-\item{\code{population}}{integer population row ID (0-based, or \code{-1});
-\code{NULL} maps to \code{-1}.}
+\item{\code{population}}{integer population row ID (0-based);
+use \code{-1} if not known - \code{NULL} maps to \code{-1}.}
-\item{\code{individual}}{integer individual row ID (0-based, or \code{-1});
-\code{NULL} maps to \code{-1}.}
+\item{\code{individual}}{integer individual row ID (0-based);
+use \code{-1} if not known - \code{NULL} maps to \code{-1}.}
\item{\code{metadata}}{for the new node; accepts \code{NULL},
a raw vector, or a character of length 1.}
@@ -723,17 +722,16 @@ Integer row ID (0-based) of the newly added edge.
\if{html}{\out{
}}
\preformatted{ts_file <- system.file("examples/test.trees", package = "RcppTskit")
tc <- tc_load(ts_file)
-parent <- 0L
-child <- 1L
+child <- tc$node_table_add_row(time = 0.0)
n_before <- tc$num_edges()
new_id <- tc$edge_table_add_row(
- left = 0, right = 1, parent = parent, child = child
+ left = 0, right = 50, parent = 16L, child = child
)
new_id <- tc$edge_table_add_row(
- left = 1, right = 2, parent = parent, child = child, metadata = "abc"
+ left = 50, right = 75, parent = 17L, child = child, metadata = "abc"
)
new_id <- tc$edge_table_add_row(
- left = 2, right = 3, parent = parent, child = child, metadata = charToRaw("cba")
+ left = 75, right = 100, parent = 18L, child = child, metadata = charToRaw("cba")
)
n_after <- tc$num_edges()
}
diff --git a/RcppTskit/src/RcppTskit.cpp b/RcppTskit/src/RcppTskit.cpp
index e38e676..aeaaf63 100644
--- a/RcppTskit/src/RcppTskit.cpp
+++ b/RcppTskit/src/RcppTskit.cpp
@@ -1246,18 +1246,20 @@ Rcpp::List rtsk_table_collection_metadata_length(const SEXP tc) {
// @param flags passed to \code{tskit C}.
// @param location numeric vector with the location of the new individual
// (can be \code{NULL}).
-// @param parents integer vector with parent individual IDs
+// @param parents integer vector with parent individual IDs (0-based)
// (can be \code{NULL}).
// @param metadata raw vector with metadata bytes
// (can be \code{NULL}).
// @details This function calls
// \url{https://tskit.dev/tskit/docs/stable/c-api.html#c.tsk_individual_table_add_row}
// on the individuals table of \code{tc}.
-// @return The 0-based row ID of the newly added individual.
+// @return The row ID (0-based) of the newly added individual.
// @examples
// ts_file <- system.file("examples/test.trees", package = "RcppTskit")
// tc_xptr <- RcppTskit:::rtsk_table_collection_load(ts_file)
// n_before <- RcppTskit:::rtsk_table_collection_get_num_individuals(tc_xptr)
+// m_before
+// <- RcppTskit:::rtsk_table_collection_metadata_length(tc_xptr)$individuals
// tc_py <- RcppTskit:::rtsk_table_collection_r_to_py(tc_xptr)
// tc_py$individuals$max_rows
// tc_py$individuals["flags"]
@@ -1279,8 +1281,13 @@ Rcpp::List rtsk_table_collection_metadata_length(const SEXP tc) {
// new_id <- RcppTskit:::rtsk_individual_table_add_row(tc = tc_xptr, flags = 3L,
// location = c(2, 11), parents = c(1L, 3L), metadata = charToRaw("abc"))
// n_after <- RcppTskit:::rtsk_table_collection_get_num_individuals(tc_xptr)
-// new_id == as.integer(n_before) && n_after == n_before + 3L
-// tc_py <- RcppTskit:::rtsk_table_collection_r_to_py(tc_xptr)
+// m_after <-
+// RcppTskit:::rtsk_table_collection_metadata_length(tc_xptr)$individuals
+// new_id == n_after - 1L
+// n_after == n_before + 3L
+// m_after == m_before + 3L
+// tc_py <-
+// RcppTskit:::rtsk_table_collection_r_to_py(tc_xptr)
// tc_py$individuals$max_rows
// tc_py$individuals["flags"]
// tc_py$individuals["location"]
@@ -1340,18 +1347,21 @@ int rtsk_individual_table_add_row(
// \code{tsk_table_collection_t} object.
// @param flags passed to \code{tskit C}.
// @param time numeric time value for the new node.
-// @param population integer population row ID (0-based, or \code{-1}).
-// @param individual integer individual row ID (0-based, or \code{-1}).
+// @param population integer population row ID (0-based);
+// use \code{-1} if not known.
+// @param individual integer individual row ID (0-based);
+// use \code{-1} if not known.
// @param metadata raw vector with metadata bytes
// (can be \code{NULL}).
// @details This function calls
// \url{https://tskit.dev/tskit/docs/stable/c-api.html#c.tsk_node_table_add_row}
// on the nodes table of \code{tc}.
-// @return The 0-based row ID of the newly added node.
+// @return The row ID (0-based) of the newly added node.
// @examples
// ts_file <- system.file("examples/test.trees", package = "RcppTskit")
// tc_xptr <- RcppTskit:::rtsk_table_collection_load(ts_file)
// n_before <- RcppTskit:::rtsk_table_collection_get_num_nodes(tc_xptr)
+// m_before <- RcppTskit:::rtsk_table_collection_metadata_length(tc_xptr)$nodes
// tc_py <- RcppTskit:::rtsk_table_collection_r_to_py(tc_xptr)
// tc_py$nodes$max_rows
// tc_py$nodes["flags"]
@@ -1370,7 +1380,10 @@ int rtsk_individual_table_add_row(
// metadata = charToRaw("abc")
// )
// n_after <- RcppTskit:::rtsk_table_collection_get_num_nodes(tc_xptr)
-// new_id == as.integer(n_before) && n_after == n_before + 3L
+// m_after <- RcppTskit:::rtsk_table_collection_metadata_length(tc_xptr)$nodes
+// new_id == n_after - 1L
+// n_after == n_before + 4L
+// m_after == m_before + 3L
// tc_py <- RcppTskit:::rtsk_table_collection_r_to_py(tc_xptr)
// tc_py$nodes$max_rows
// tc_py$nodes["flags"]
@@ -1428,27 +1441,29 @@ int rtsk_node_table_add_row(
// @details This function calls
// \url{https://tskit.dev/tskit/docs/stable/c-api.html#c.tsk_edge_table_add_row}
// on the edges table of \code{tc}.
-// @return The 0-based row ID of the newly added edge.
+// @return The row ID (0-based) of the newly added edge.
// @examples
// ts_file <- system.file("examples/test.trees", package = "RcppTskit")
// tc_xptr <- RcppTskit:::rtsk_table_collection_load(ts_file)
-// parent <- 0L
-// child <- 1L
+// child <- rtsk_node_table_add_row(tc_xptr, time = 0.0)
// n_before <- RcppTskit:::rtsk_table_collection_get_num_edges(tc_xptr)
-// m_before <-
-// RcppTskit:::rtsk_table_collection_metadata_length(tc_xptr)[["edges"]] new_id
-// <- RcppTskit:::rtsk_edge_table_add_row(
-// tc = tc_xptr, left = 0, right = 1, parent = parent, child = child
+// m_before <- RcppTskit:::rtsk_table_collection_metadata_length(tc_xptr)$edges
+// new_id <- RcppTskit:::rtsk_edge_table_add_row(
+// tc = tc_xptr, left = 0, right = 50, parent = 16L, child = child
// )
// new_id <- RcppTskit:::rtsk_edge_table_add_row(
-// tc = tc_xptr, left = 1, right = 2, parent = parent, child = child,
-// metadata = charToRaw("abc")
+// tc = tc_xptr, left = 50, right = 75, parent = 17L, child = child,
+// metadata = "abc"
+// )
+// new_id <- RcppTskit:::rtsk_edge_table_add_row(
+// tc = tc_xptr, left = 75, right = 100, parent = 18L, child = child,
+// metadata = charToRaw("cba")
// )
// n_after <- RcppTskit:::rtsk_table_collection_get_num_edges(tc_xptr)
-// m_after <-
-// RcppTskit:::rtsk_table_collection_metadata_length(tc_xptr)[["edges"]] new_id
-// == as.integer(n_before) && n_after == n_before + 2L && m_after == m_before +
-// 3L
+// m_after <- RcppTskit:::rtsk_table_collection_metadata_length(tc_xptr)$edges
+// new_id == n_after - 1L
+// n_after == n_before + 3L
+// m_after == m_before + 3L
// [[Rcpp::export]]
int rtsk_edge_table_add_row(
const SEXP tc, const double left, const double right, const int parent,
diff --git a/RcppTskit/tests/testthat/test_TableCollection.R b/RcppTskit/tests/testthat/test_TableCollection.R
index f31751a..4b5752c 100644
--- a/RcppTskit/tests/testthat/test_TableCollection.R
+++ b/RcppTskit/tests/testthat/test_TableCollection.R
@@ -282,7 +282,7 @@ test_that("individual_table_add_row wrapper expands the table collection and han
tc_xptr <- rtsk_table_collection_load(ts_file)
n_before <- rtsk_table_collection_get_num_individuals(tc_xptr)
- m_before <- rtsk_table_collection_metadata_length(tc_xptr)[["individuals"]]
+ m_before <- rtsk_table_collection_metadata_length(tc_xptr)$individuals
expect_error(
rtsk_individual_table_add_row(tc_xptr, flags = -1L),
@@ -301,7 +301,7 @@ test_that("individual_table_add_row wrapper expands the table collection and han
as.integer(n_before) + 1L
)
expect_equal(
- as.integer(rtsk_table_collection_metadata_length(tc_xptr)[["individuals"]]),
+ as.integer(rtsk_table_collection_metadata_length(tc_xptr)$individuals),
as.integer(m_before) + 3L
)
@@ -317,9 +317,7 @@ test_that("individual_table_add_row wrapper expands the table collection and han
tc_xptr <- rtsk_table_collection_load(ts_file)
n0 <- as.integer(rtsk_table_collection_get_num_individuals(tc_xptr))
- m0 <- as.integer(rtsk_table_collection_metadata_length(tc_xptr)[[
- "individuals"
- ]])
+ m0 <- as.integer(rtsk_table_collection_metadata_length(tc_xptr)$individuals)
# Defaults map to NULL in the generated R wrapper and should be accepted.
id0 <- rtsk_individual_table_add_row(tc_xptr)
@@ -329,7 +327,7 @@ test_that("individual_table_add_row wrapper expands the table collection and han
n0 + 1L
)
expect_equal(
- as.integer(rtsk_table_collection_metadata_length(tc_xptr)[["individuals"]]),
+ as.integer(rtsk_table_collection_metadata_length(tc_xptr)$individuals),
m0
)
@@ -375,20 +373,20 @@ test_that("individual_table_add_row wrapper expands the table collection and han
)
expect_equal(as.integer(tc$num_individuals()), n_before_method + 1L)
- m_before_char <- as.integer(rtsk_table_collection_metadata_length(tc$xptr)[[
- "individuals"
- ]])
+ m_before_char <- as.integer(
+ rtsk_table_collection_metadata_length(tc$xptr)$individuals
+ )
expect_no_warning(tc$individual_table_add_row(metadata = "abc"))
expect_equal(
- as.integer(rtsk_table_collection_metadata_length(tc$xptr)[["individuals"]]),
+ as.integer(rtsk_table_collection_metadata_length(tc$xptr)$individuals),
m_before_char + 3L
)
- m_before_raw <- as.integer(rtsk_table_collection_metadata_length(tc$xptr)[[
- "individuals"
- ]])
+ m_before_raw <- as.integer(
+ rtsk_table_collection_metadata_length(tc$xptr)$individuals
+ )
expect_no_error(tc$individual_table_add_row(metadata = charToRaw("xyz")))
expect_equal(
- as.integer(rtsk_table_collection_metadata_length(tc$xptr)[["individuals"]]),
+ as.integer(rtsk_table_collection_metadata_length(tc$xptr)$individuals),
m_before_raw + 3L
)
expect_error(
@@ -419,7 +417,7 @@ test_that("node_table_add_row wrapper expands the table collection and handles i
tc_xptr <- rtsk_table_collection_load(ts_file)
n_before <- rtsk_table_collection_get_num_nodes(tc_xptr)
- m_before <- rtsk_table_collection_metadata_length(tc_xptr)[["nodes"]]
+ m_before <- rtsk_table_collection_metadata_length(tc_xptr)$nodes
expect_error(
rtsk_node_table_add_row(tc_xptr, flags = -1L),
@@ -440,7 +438,7 @@ test_that("node_table_add_row wrapper expands the table collection and handles i
as.integer(n_before) + 1L
)
expect_equal(
- as.integer(rtsk_table_collection_metadata_length(tc_xptr)[["nodes"]]),
+ as.integer(rtsk_table_collection_metadata_length(tc_xptr)$nodes),
as.integer(m_before) + 3L
)
@@ -456,9 +454,9 @@ test_that("node_table_add_row wrapper expands the table collection and handles i
tc_xptr <- rtsk_table_collection_load(ts_file)
n0 <- as.integer(rtsk_table_collection_get_num_nodes(tc_xptr))
- m0 <- as.integer(rtsk_table_collection_metadata_length(tc_xptr)[["nodes"]])
+ m0 <- as.integer(rtsk_table_collection_metadata_length(tc_xptr)$nodes)
- # Defaults map to NULL in the generated R wrapper and should be accepted.
+ # Testing defaults
id0 <- rtsk_node_table_add_row(tc_xptr)
expect_equal(id0, n0)
expect_equal(
@@ -466,7 +464,7 @@ test_that("node_table_add_row wrapper expands the table collection and handles i
n0 + 1L
)
expect_equal(
- as.integer(rtsk_table_collection_metadata_length(tc_xptr)[["nodes"]]),
+ as.integer(rtsk_table_collection_metadata_length(tc_xptr)$nodes),
m0
)
@@ -489,6 +487,13 @@ test_that("node_table_add_row wrapper expands the table collection and handles i
),
regexp = "population must not be NA_integer_ in rtsk_node_table_add_row"
)
+ expect_error(
+ rtsk_node_table_add_row(
+ tc = tc_xptr,
+ flags = 0L,
+ population = NULL
+ )
+ )
expect_error(
rtsk_node_table_add_row(
tc = tc_xptr,
@@ -497,6 +502,13 @@ test_that("node_table_add_row wrapper expands the table collection and handles i
),
regexp = "individual must not be NA_integer_ in rtsk_node_table_add_row"
)
+ expect_error(
+ rtsk_node_table_add_row(
+ tc = tc_xptr,
+ flags = 0L,
+ individual = NULL
+ )
+ )
tc <- TableCollection$new(xptr = tc_xptr)
n_before_method <- as.integer(tc$num_nodes())
@@ -513,22 +525,23 @@ test_that("node_table_add_row wrapper expands the table collection and handles i
expect_no_error(tc$node_table_add_row(population = NULL, individual = NULL))
expect_equal(as.integer(tc$num_nodes()), n_before_method + 2L)
- m_before_char <- as.integer(rtsk_table_collection_metadata_length(tc$xptr)[[
- "nodes"
- ]])
+ m_before_char <- as.integer(
+ rtsk_table_collection_metadata_length(tc$xptr)$nodes
+ )
expect_no_warning(tc$node_table_add_row(metadata = "abc"))
expect_equal(
- as.integer(rtsk_table_collection_metadata_length(tc$xptr)[["nodes"]]),
+ as.integer(rtsk_table_collection_metadata_length(tc$xptr)$nodes),
m_before_char + 3L
)
- m_before_raw <- as.integer(rtsk_table_collection_metadata_length(tc$xptr)[[
- "nodes"
- ]])
+ m_before_raw <- as.integer(
+ rtsk_table_collection_metadata_length(tc$xptr)$nodes
+ )
expect_no_error(tc$node_table_add_row(metadata = charToRaw("xyz")))
expect_equal(
- as.integer(rtsk_table_collection_metadata_length(tc$xptr)[["nodes"]]),
+ as.integer(rtsk_table_collection_metadata_length(tc$xptr)$nodes),
m_before_raw + 3L
)
+
expect_error(
tc$node_table_add_row(population = NA_integer_),
regexp = "population must not be NA_integer_ in rtsk_node_table_add_row"
@@ -558,12 +571,12 @@ test_that("node_table_add_row wrapper expands the table collection and handles i
test_that("edge_table_add_row wrapper expands the table collection and handles inputs", {
ts_file <- system.file("examples/test.trees", package = "RcppTskit")
tc_xptr <- rtsk_table_collection_load(ts_file)
- expect_gt(as.integer(rtsk_table_collection_get_num_nodes(tc_xptr)), 1L)
- parent <- 0L
- child <- 1L
n_before <- rtsk_table_collection_get_num_edges(tc_xptr)
- m_before <- rtsk_table_collection_metadata_length(tc_xptr)[["edges"]]
+ m_before <- rtsk_table_collection_metadata_length(tc_xptr)$edges
+
+ parent <- 0L
+ child <- 1L
new_id <- rtsk_edge_table_add_row(
tc = tc_xptr,
@@ -579,7 +592,7 @@ test_that("edge_table_add_row wrapper expands the table collection and handles i
as.integer(n_before) + 1L
)
expect_equal(
- as.integer(rtsk_table_collection_metadata_length(tc_xptr)[["edges"]]),
+ as.integer(rtsk_table_collection_metadata_length(tc_xptr)$edges),
as.integer(m_before) + 3L
)
@@ -598,11 +611,9 @@ test_that("edge_table_add_row wrapper expands the table collection and handles i
)
tc_xptr <- rtsk_table_collection_load(ts_file)
- parent <- 0L
- child <- 1L
n0 <- as.integer(rtsk_table_collection_get_num_edges(tc_xptr))
- m0 <- as.integer(rtsk_table_collection_metadata_length(tc_xptr)[["edges"]])
+ m0 <- as.integer(rtsk_table_collection_metadata_length(tc_xptr)$edges)
# Explicit NULL metadata should be accepted.
id0 <- rtsk_edge_table_add_row(
@@ -619,7 +630,7 @@ test_that("edge_table_add_row wrapper expands the table collection and handles i
n0 + 1L
)
expect_equal(
- as.integer(rtsk_table_collection_metadata_length(tc_xptr)[["edges"]]),
+ as.integer(rtsk_table_collection_metadata_length(tc_xptr)$edges),
m0
)
@@ -707,9 +718,9 @@ test_that("edge_table_add_row wrapper expands the table collection and handles i
)
expect_equal(as.integer(tc$num_edges()), n_before_method + 1L)
- m_before_char <- as.integer(rtsk_table_collection_metadata_length(tc$xptr)[[
- "edges"
- ]])
+ m_before_char <- as.integer(
+ rtsk_table_collection_metadata_length(tc$xptr)$edges
+ )
expect_no_warning(
tc$edge_table_add_row(
left = 3,
@@ -720,12 +731,12 @@ test_that("edge_table_add_row wrapper expands the table collection and handles i
)
)
expect_equal(
- as.integer(rtsk_table_collection_metadata_length(tc$xptr)[["edges"]]),
+ as.integer(rtsk_table_collection_metadata_length(tc$xptr)$edges),
m_before_char + 3L
)
- m_before_raw <- as.integer(rtsk_table_collection_metadata_length(tc$xptr)[[
- "edges"
- ]])
+ m_before_raw <- as.integer(
+ rtsk_table_collection_metadata_length(tc$xptr)$edges
+ )
expect_no_error(
tc$edge_table_add_row(
left = 4,
@@ -736,7 +747,7 @@ test_that("edge_table_add_row wrapper expands the table collection and handles i
)
)
expect_equal(
- as.integer(rtsk_table_collection_metadata_length(tc$xptr)[["edges"]]),
+ as.integer(rtsk_table_collection_metadata_length(tc$xptr)$edges),
m_before_raw + 3L
)
expect_error(
diff --git a/RcppTskit/vignettes/RcppTskit_intro.qmd b/RcppTskit/vignettes/RcppTskit_intro.qmd
index fa2f318..b7e3989 100644
--- a/RcppTskit/vignettes/RcppTskit_intro.qmd
+++ b/RcppTskit/vignettes/RcppTskit_intro.qmd
@@ -270,23 +270,29 @@ ts2 <- tc$tree_sequence()
help(package = "RcppTskit")
```
-Developers should also explore the low-level `R` and `C++` functions.
+Developers should also explore the internal `R` and `C++` functions.
Their names all start with `rtsk_` and are accessible via `RcppTskit:::`.
+Since these are internal functions we instruct the linter `jarl`
+not to warn about their use.
For example, the above `R` function `ts_load()` effectively calls:
```{r}
#| label: use_case_1_dev_funcs
# Low-level R function, which further calls the C++ function
+# jarl-ignore internal_function: exposing for demo/doc
RcppTskit:::rtsk_treeseq_load
# C++ function (see also the C++ source code)
+# jarl-ignore internal_function: exposing for demo/doc
RcppTskit:::`_RcppTskit_rtsk_treeseq_load`
# The same as the ts_load() example, but exposing the external pointer
+# jarl-ignore internal_function: exposing for demo/doc
xptr <- RcppTskit:::rtsk_treeseq_load(ts_file)
methods::is(xptr)
# We pass the external pointer to other low-level functions
+# jarl-ignore internal_function: exposing for demo/doc
RcppTskit:::rtsk_treeseq_get_num_individuals(xptr)
```