Skip to content

Commit f9dd246

Browse files
authored
Merge pull request #126 from LynxJinyangii/add-tables-on-pr122
Add methods to grow node and edge tables
2 parents fea5853 + d577744 commit f9dd246

10 files changed

Lines changed: 1042 additions & 0 deletions

File tree

RcppTskit/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.idea/
2+
src/.idea/

RcppTskit/NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ and releases adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html
3131
- Added `rtsk_individual_table_add_row()` and
3232
`TableCollection$individual_table_add_row()` to append individual rows from
3333
\code{R}, mirroring `tsk_individual_table_add_row()`.
34+
- Added `rtsk_node_table_add_row()` and `TableCollection$node_table_add_row()`
35+
to append node rows from \code{R}, mirroring `tsk_node_table_add_row()`.
36+
- Added `rtsk_edge_table_add_row()` and `TableCollection$edge_table_add_row()`
37+
to append edge rows from \code{R}, mirroring `tsk_edge_table_add_row()`.
3438
- TODO
3539

3640
### Changed

RcppTskit/R/Class-TableCollection.R

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,62 @@ TableCollection <- R6Class(
202202
rtsk_table_collection_get_num_nodes(self$xptr)
203203
},
204204

205+
#' @description Add a row to the nodes table.
206+
#' @param flags integer flags for the new node.
207+
#' @param time numeric time value for the new node.
208+
#' @param population integer population row ID (0-based, or \code{-1});
209+
#' \code{NULL} maps to \code{-1}.
210+
#' @param individual integer individual row ID (0-based, or \code{-1});
211+
#' \code{NULL} maps to \code{-1}.
212+
#' @param metadata for the new node; accepts \code{NULL},
213+
#' a raw vector, or a character of length 1.
214+
#' @details See the \code{tskit Python} equivalent at
215+
#' \url{https://tskit.dev/tskit/docs/stable/python-api.html#tskit.NodeTable.add_row}.
216+
#' The function casts inputs to the expected class. For convenience,
217+
#' \code{population = NULL} and \code{individual = NULL} are mapped to
218+
#' \code{-1} (\code{TSK_NULL}).
219+
#' @return Integer row ID (0-based) of the newly added node.
220+
#' @examples
221+
#' ts_file <- system.file("examples/test.trees", package = "RcppTskit")
222+
#' tc <- tc_load(ts_file)
223+
#' n_before <- tc$num_nodes()
224+
#' new_id <- tc$node_table_add_row()
225+
#' new_id <- tc$node_table_add_row(time = 2.5)
226+
#' new_id <- tc$node_table_add_row(flags = 1L, time = 3.5, population = 0L)
227+
#' new_id <- tc$node_table_add_row(flags = 1L, time = 4.5, individual = 0L)
228+
#' new_id <- tc$node_table_add_row(metadata = "abc")
229+
#' new_id <- tc$node_table_add_row(metadata = charToRaw("cba"))
230+
#' n_after <- tc$num_nodes()
231+
node_table_add_row = function(
232+
flags = 0L,
233+
time = 0,
234+
population = -1L,
235+
individual = -1L,
236+
metadata = NULL
237+
) {
238+
if (is.null(metadata)) {
239+
metadata_raw <- NULL
240+
} else if (is.raw(metadata)) {
241+
metadata_raw <- metadata
242+
} else if (
243+
is.character(metadata) && length(metadata) == 1L && !is.na(metadata)
244+
) {
245+
metadata_raw <- charToRaw(metadata)
246+
} else {
247+
stop(
248+
"metadata must be NULL, a raw vector, or a length-1 non-NA character string!"
249+
)
250+
}
251+
rtsk_node_table_add_row(
252+
tc = self$xptr,
253+
flags = as.integer(flags),
254+
time = as.numeric(time),
255+
population = if (is.null(population)) -1L else as.integer(population),
256+
individual = if (is.null(individual)) -1L else as.integer(individual),
257+
metadata = metadata_raw
258+
)
259+
},
260+
205261
#' @description Get the number of edges in a table collection.
206262
#' @return A signed 64 bit integer \code{bit64::integer64}.
207263
#' @examples
@@ -212,6 +268,95 @@ TableCollection <- R6Class(
212268
rtsk_table_collection_get_num_edges(self$xptr)
213269
},
214270

271+
#' @description Add a row to the edges table.
272+
#' @param left numeric scalar left coordinate for the new edge.
273+
#' @param right numeric scalar right coordinate for the new edge.
274+
#' @param parent integer scalar parent node row ID (0-based).
275+
#' @param child integer scalar child node row ID (0-based).
276+
#' @param metadata for the new edge; accepts \code{NULL},
277+
#' a raw vector, or a character of length 1.
278+
#' @details See the \code{tskit Python} equivalent at
279+
#' \url{https://tskit.dev/tskit/docs/stable/python-api.html#tskit.EdgeTable.add_row}.
280+
#' The function casts inputs to the expected class. Inputs are validated:
281+
#' \code{left} and \code{right} must be finite numeric scalars with
282+
#' \code{left < right}, and \code{parent} and \code{child} must be
283+
#' non-\code{NA} integer scalars.
284+
#' @return Integer row ID (0-based) of the newly added edge.
285+
#' @examples
286+
#' ts_file <- system.file("examples/test.trees", package = "RcppTskit")
287+
#' tc <- tc_load(ts_file)
288+
#' parent <- 0L
289+
#' child <- 1L
290+
#' n_before <- tc$num_edges()
291+
#' new_id <- tc$edge_table_add_row(
292+
#' left = 0, right = 1, parent = parent, child = child
293+
#' )
294+
#' new_id <- tc$edge_table_add_row(
295+
#' left = 1, right = 2, parent = parent, child = child, metadata = "abc"
296+
#' )
297+
#' new_id <- tc$edge_table_add_row(
298+
#' left = 2, right = 3, parent = parent, child = child, metadata = charToRaw("cba")
299+
#' )
300+
#' n_after <- tc$num_edges()
301+
edge_table_add_row = function(
302+
left,
303+
right,
304+
parent,
305+
child,
306+
metadata = NULL
307+
) {
308+
if (
309+
is.null(left) ||
310+
length(left) != 1L ||
311+
!is.numeric(left) ||
312+
is.na(left) ||
313+
!is.finite(left)
314+
) {
315+
stop("left must be a non-NA finite numeric scalar!")
316+
}
317+
if (
318+
is.null(right) ||
319+
length(right) != 1L ||
320+
!is.numeric(right) ||
321+
is.na(right) ||
322+
!is.finite(right)
323+
) {
324+
stop("right must be a non-NA finite numeric scalar!")
325+
}
326+
if (as.numeric(left) >= as.numeric(right)) {
327+
stop("left must be strictly less than right!")
328+
}
329+
if (
330+
is.null(parent) || length(parent) != 1L || is.na(as.integer(parent))
331+
) {
332+
stop("parent must be a non-NA integer scalar!")
333+
}
334+
if (is.null(child) || length(child) != 1L || is.na(as.integer(child))) {
335+
stop("child must be a non-NA integer scalar!")
336+
}
337+
if (is.null(metadata)) {
338+
metadata_raw <- NULL
339+
} else if (is.raw(metadata)) {
340+
metadata_raw <- metadata
341+
} else if (
342+
is.character(metadata) && length(metadata) == 1L && !is.na(metadata)
343+
) {
344+
metadata_raw <- charToRaw(metadata)
345+
} else {
346+
stop(
347+
"metadata must be NULL, a raw vector, or a length-1 non-NA character string!"
348+
)
349+
}
350+
rtsk_edge_table_add_row(
351+
tc = self$xptr,
352+
left = as.numeric(left),
353+
right = as.numeric(right),
354+
parent = as.integer(parent),
355+
child = as.integer(child),
356+
metadata = metadata_raw
357+
)
358+
},
359+
215360
#' @description Get the number of sites in a table collection.
216361
#' @return A signed 64 bit integer \code{bit64::integer64}.
217362
#' @examples

RcppTskit/R/RcppExports.R

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,14 @@ rtsk_individual_table_add_row <- function(tc, flags = 0L, location = NULL, paren
207207
.Call(`_RcppTskit_rtsk_individual_table_add_row`, tc, flags, location, parents, metadata)
208208
}
209209

210+
rtsk_node_table_add_row <- function(tc, flags = 0L, time = 0, population = -1L, individual = -1L, metadata = NULL) {
211+
.Call(`_RcppTskit_rtsk_node_table_add_row`, tc, flags, time, population, individual, metadata)
212+
}
213+
214+
rtsk_edge_table_add_row <- function(tc, left, right, parent, child, metadata = NULL) {
215+
.Call(`_RcppTskit_rtsk_edge_table_add_row`, tc, left, right, parent, child, metadata)
216+
}
217+
210218
test_tsk_bug_assert_c <- function() {
211219
invisible(.Call(`_RcppTskit_test_tsk_bug_assert_c`))
212220
}
@@ -243,3 +251,11 @@ test_rtsk_individual_table_add_row_forced_error <- function(tc) {
243251
invisible(.Call(`_RcppTskit_test_rtsk_individual_table_add_row_forced_error`, tc))
244252
}
245253

254+
test_rtsk_node_table_add_row_forced_error <- function(tc) {
255+
invisible(.Call(`_RcppTskit_test_rtsk_node_table_add_row_forced_error`, tc))
256+
}
257+
258+
test_rtsk_edge_table_add_row_forced_error <- function(tc) {
259+
invisible(.Call(`_RcppTskit_test_rtsk_edge_table_add_row_forced_error`, tc))
260+
}
261+

RcppTskit/inst/include/RcppTskit_public.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,11 @@ int rtsk_individual_table_add_row(
6262
Rcpp::Nullable<Rcpp::NumericVector> location = R_NilValue,
6363
Rcpp::Nullable<Rcpp::IntegerVector> parents = R_NilValue,
6464
Rcpp::Nullable<Rcpp::RawVector> metadata = R_NilValue);
65+
int rtsk_node_table_add_row(
66+
SEXP tc, int flags = 0, double time = 0, int population = -1,
67+
int individual = -1, Rcpp::Nullable<Rcpp::RawVector> metadata = R_NilValue);
68+
int rtsk_edge_table_add_row(
69+
SEXP tc, double left, double right, int parent, int child,
70+
Rcpp::Nullable<Rcpp::RawVector> metadata = R_NilValue);
6571

6672
#endif

0 commit comments

Comments
 (0)