Skip to content

Commit 8a64bdf

Browse files
committed
add site and mutation table rows
1 parent f9dd246 commit 8a64bdf

10 files changed

Lines changed: 1038 additions & 0 deletions

File tree

RcppTskit/NEWS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ and releases adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html
3535
to append node rows from \code{R}, mirroring `tsk_node_table_add_row()`.
3636
- Added `rtsk_edge_table_add_row()` and `TableCollection$edge_table_add_row()`
3737
to append edge rows from \code{R}, mirroring `tsk_edge_table_add_row()`.
38+
- Added `rtsk_site_table_add_row()` and `TableCollection$site_table_add_row()`
39+
to append site rows from \code{R}, mirroring `tsk_site_table_add_row()`.
40+
- Added `rtsk_mutation_table_add_row()` and
41+
`TableCollection$mutation_table_add_row()` to append mutation rows from
42+
\code{R}, mirroring `tsk_mutation_table_add_row()`.
3843
- TODO
3944

4045
### Changed

RcppTskit/R/Class-TableCollection.R

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,75 @@ TableCollection <- R6Class(
367367
rtsk_table_collection_get_num_sites(self$xptr)
368368
},
369369

370+
#' @description Add a row to the sites table.
371+
#' @param position numeric scalar site position.
372+
#' @param ancestral_state for the new site; accepts \code{NULL},
373+
#' a raw vector, or a character of length 1.
374+
#' @param metadata for the new site; accepts \code{NULL},
375+
#' a raw vector, or a character of length 1.
376+
#' @details See the \code{tskit Python} equivalent at
377+
#' \url{https://tskit.dev/tskit/docs/stable/python-api.html#tskit.SiteTable.add_row}.
378+
#' The function casts inputs to the expected class. \code{position}
379+
#' must be a non-\code{NA} finite numeric scalar.
380+
#' @return Integer row ID (0-based) of the newly added site.
381+
#' @examples
382+
#' ts_file <- system.file("examples/test.trees", package = "RcppTskit")
383+
#' tc <- tc_load(ts_file)
384+
#' n_before <- tc$num_sites()
385+
#' new_id <- tc$site_table_add_row(position = 0.5, ancestral_state = "A")
386+
#' new_id <- tc$site_table_add_row(position = 1.5, ancestral_state = charToRaw("G"))
387+
#' new_id <- tc$site_table_add_row(position = 2.5, ancestral_state = "T", metadata = "abc")
388+
#' n_after <- tc$num_sites()
389+
site_table_add_row = function(
390+
position,
391+
ancestral_state = NULL,
392+
metadata = NULL
393+
) {
394+
if (
395+
is.null(position) ||
396+
length(position) != 1L ||
397+
!is.numeric(position) ||
398+
is.na(position) ||
399+
!is.finite(position)
400+
) {
401+
stop("position must be a non-NA finite numeric scalar!")
402+
}
403+
if (is.null(ancestral_state)) {
404+
ancestral_state_raw <- NULL
405+
} else if (is.raw(ancestral_state)) {
406+
ancestral_state_raw <- ancestral_state
407+
} else if (
408+
is.character(ancestral_state) &&
409+
length(ancestral_state) == 1L &&
410+
!is.na(ancestral_state)
411+
) {
412+
ancestral_state_raw <- charToRaw(ancestral_state)
413+
} else {
414+
stop(
415+
"ancestral_state must be NULL, a raw vector, or a length-1 non-NA character string!"
416+
)
417+
}
418+
if (is.null(metadata)) {
419+
metadata_raw <- NULL
420+
} else if (is.raw(metadata)) {
421+
metadata_raw <- metadata
422+
} else if (
423+
is.character(metadata) && length(metadata) == 1L && !is.na(metadata)
424+
) {
425+
metadata_raw <- charToRaw(metadata)
426+
} else {
427+
stop(
428+
"metadata must be NULL, a raw vector, or a length-1 non-NA character string!"
429+
)
430+
}
431+
rtsk_site_table_add_row(
432+
tc = self$xptr,
433+
position = as.numeric(position),
434+
ancestral_state = ancestral_state_raw,
435+
metadata = metadata_raw
436+
)
437+
},
438+
370439
#' @description Get the number of mutations in a table collection.
371440
#' @return A signed 64 bit integer \code{bit64::integer64}.
372441
#' @examples
@@ -377,6 +446,104 @@ TableCollection <- R6Class(
377446
rtsk_table_collection_get_num_mutations(self$xptr)
378447
},
379448

449+
#' @description Add a row to the mutations table.
450+
#' @param site integer scalar site row ID (0-based).
451+
#' @param node integer scalar node row ID (0-based).
452+
#' @param parent integer scalar parent mutation row ID (0-based, or \code{-1}).
453+
#' @param time numeric scalar mutation time; use \code{NaN} for
454+
#' \code{TSK_UNKNOWN_TIME}.
455+
#' @param derived_state for the new mutation; accepts \code{NULL},
456+
#' a raw vector, or a character of length 1.
457+
#' @param metadata for the new mutation; accepts \code{NULL},
458+
#' a raw vector, or a character of length 1.
459+
#' @details See the \code{tskit Python} equivalent at
460+
#' \url{https://tskit.dev/tskit/docs/stable/python-api.html#tskit.MutationTable.add_row}.
461+
#' The function casts inputs to the expected class. \code{site},
462+
#' \code{node}, and \code{parent} must be non-\code{NA} integer scalars.
463+
#' \code{time} must be a numeric scalar that is finite or \code{NaN}
464+
#' (unknown time).
465+
#' @return Integer row ID (0-based) of the newly added mutation.
466+
#' @examples
467+
#' ts_file <- system.file("examples/test.trees", package = "RcppTskit")
468+
#' tc <- tc_load(ts_file)
469+
#' n_before <- tc$num_mutations()
470+
#' new_id <- tc$mutation_table_add_row(site = 0L, node = 0L, derived_state = "T")
471+
#' new_id <- tc$mutation_table_add_row(
472+
#' site = 0L,
473+
#' node = 0L,
474+
#' parent = -1L,
475+
#' time = 1.5,
476+
#' derived_state = charToRaw("C"),
477+
#' metadata = "abc"
478+
#' )
479+
#' n_after <- tc$num_mutations()
480+
mutation_table_add_row = function(
481+
site,
482+
node,
483+
parent = -1L,
484+
time = NaN,
485+
derived_state = NULL,
486+
metadata = NULL
487+
) {
488+
if (is.null(site) || length(site) != 1L || is.na(as.integer(site))) {
489+
stop("site must be a non-NA integer scalar!")
490+
}
491+
if (is.null(node) || length(node) != 1L || is.na(as.integer(node))) {
492+
stop("node must be a non-NA integer scalar!")
493+
}
494+
if (
495+
is.null(parent) || length(parent) != 1L || is.na(as.integer(parent))
496+
) {
497+
stop("parent must be a non-NA integer scalar!")
498+
}
499+
if (
500+
is.null(time) ||
501+
length(time) != 1L ||
502+
!is.numeric(time) ||
503+
(is.na(time) && !is.nan(time)) ||
504+
!(is.finite(time) || is.nan(time))
505+
) {
506+
stop("time must be a non-NA numeric scalar that is finite or NaN!")
507+
}
508+
if (is.null(derived_state)) {
509+
derived_state_raw <- NULL
510+
} else if (is.raw(derived_state)) {
511+
derived_state_raw <- derived_state
512+
} else if (
513+
is.character(derived_state) &&
514+
length(derived_state) == 1L &&
515+
!is.na(derived_state)
516+
) {
517+
derived_state_raw <- charToRaw(derived_state)
518+
} else {
519+
stop(
520+
"derived_state must be NULL, a raw vector, or a length-1 non-NA character string!"
521+
)
522+
}
523+
if (is.null(metadata)) {
524+
metadata_raw <- NULL
525+
} else if (is.raw(metadata)) {
526+
metadata_raw <- metadata
527+
} else if (
528+
is.character(metadata) && length(metadata) == 1L && !is.na(metadata)
529+
) {
530+
metadata_raw <- charToRaw(metadata)
531+
} else {
532+
stop(
533+
"metadata must be NULL, a raw vector, or a length-1 non-NA character string!"
534+
)
535+
}
536+
rtsk_mutation_table_add_row(
537+
tc = self$xptr,
538+
site = as.integer(site),
539+
node = as.integer(node),
540+
parent = as.integer(parent),
541+
time = as.numeric(time),
542+
derived_state = derived_state_raw,
543+
metadata = metadata_raw
544+
)
545+
},
546+
380547
#' @description Get the sequence length.
381548
#' @return A numeric.
382549
#' @examples

RcppTskit/R/RcppExports.R

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,14 @@ rtsk_edge_table_add_row <- function(tc, left, right, parent, child, metadata = N
215215
.Call(`_RcppTskit_rtsk_edge_table_add_row`, tc, left, right, parent, child, metadata)
216216
}
217217

218+
rtsk_site_table_add_row <- function(tc, position, ancestral_state = NULL, metadata = NULL) {
219+
.Call(`_RcppTskit_rtsk_site_table_add_row`, tc, position, ancestral_state, metadata)
220+
}
221+
222+
rtsk_mutation_table_add_row <- function(tc, site, node, parent, time, derived_state = NULL, metadata = NULL) {
223+
.Call(`_RcppTskit_rtsk_mutation_table_add_row`, tc, site, node, parent, time, derived_state, metadata)
224+
}
225+
218226
test_tsk_bug_assert_c <- function() {
219227
invisible(.Call(`_RcppTskit_test_tsk_bug_assert_c`))
220228
}
@@ -259,3 +267,11 @@ test_rtsk_edge_table_add_row_forced_error <- function(tc) {
259267
invisible(.Call(`_RcppTskit_test_rtsk_edge_table_add_row_forced_error`, tc))
260268
}
261269

270+
test_rtsk_site_table_add_row_forced_error <- function(tc) {
271+
invisible(.Call(`_RcppTskit_test_rtsk_site_table_add_row_forced_error`, tc))
272+
}
273+
274+
test_rtsk_mutation_table_add_row_forced_error <- function(tc) {
275+
invisible(.Call(`_RcppTskit_test_rtsk_mutation_table_add_row_forced_error`, tc))
276+
}
277+

RcppTskit/inst/WORDLIST

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@ SLiM
66
TableCollection
77
TreeSequence
88
Tskit
9+
arXiv
910
bitmask
11+
cloneable
12+
com
1013
doi
1114
etc
1215
finaliser
16+
github
17+
HighlanderLab
1318
iyae
1419
kastore
1520
msprime
21+
num
1622
tc
1723
ts
1824
tskit

RcppTskit/inst/include/RcppTskit_public.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,5 +68,13 @@ int rtsk_node_table_add_row(
6868
int rtsk_edge_table_add_row(
6969
SEXP tc, double left, double right, int parent, int child,
7070
Rcpp::Nullable<Rcpp::RawVector> metadata = R_NilValue);
71+
int rtsk_site_table_add_row(
72+
SEXP tc, double position,
73+
Rcpp::Nullable<Rcpp::RawVector> ancestral_state = R_NilValue,
74+
Rcpp::Nullable<Rcpp::RawVector> metadata = R_NilValue);
75+
int rtsk_mutation_table_add_row(
76+
SEXP tc, int site, int node, int parent, double time,
77+
Rcpp::Nullable<Rcpp::RawVector> derived_state = R_NilValue,
78+
Rcpp::Nullable<Rcpp::RawVector> metadata = R_NilValue);
7179

7280
#endif

0 commit comments

Comments
 (0)