Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Update docs for R, fix binding, test, and easy install #97

Merged
merged 8 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/ci-R.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: CI R

on:
push:
branches:
- main
- dev
pull_request:

permissions:
contents: read

env:
PIXI_COLOR: always
R_ENV: r-phylo2vec

jobs:
build_and_test:
name: R project
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: prefix-dev/[email protected]
with:
environments: ${{ env.R_ENV }}
- run: pixi run -e ${{ env.R_ENV }} test "./${{ env.R_ENV}}"
6 changes: 6 additions & 0 deletions pixi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,9 @@ depends-on = ["install-python"]
[feature.r.dependencies]
r = "4.*"
r-devtools = ">=2.4.5,<3"

[feature.r.tasks.install-r]
cmd = "Rscript ./r-phylo2vec/scripts/install-package.R"

[feature.r.tasks.test]
cmd = "Rscript ./r-phylo2vec/scripts/run-tests.R"
2 changes: 1 addition & 1 deletion py-phylo2vec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
**NOTE: This is currently in active development and APIs will change. Use at
your own risk.**

This directory contains the pylo2vec Python codebase, which includes Rust
This directory contains the phylo2vec Python codebase, which includes Rust
binding setup.

To install this python package, simply run the following within the root
Expand Down
3 changes: 3 additions & 0 deletions r-phylo2vec/DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.2
Config/rextendr/version: 0.3.1
Suggests:
testthat (>= 3.0.0)
Config/testthat/edition: 3
4 changes: 4 additions & 0 deletions r-phylo2vec/NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Generated by roxygen2: do not edit by hand

export(check_v)
export(sample)
export(to_newick)
export(to_vector)
useDynLib(phylo2vec, .registration = TRUE)
4 changes: 4 additions & 0 deletions r-phylo2vec/R/extendr-wrappers.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,19 @@
NULL

#' Sample a random tree via Phylo2Vec
#' @export
sample <- function(n_leaves, ordered) .Call(wrap__sample, n_leaves, ordered)

#' Recover a rooted tree (in Newick format) from a Phylo2Vec v
#' @export
to_newick <- function(input_integers) .Call(wrap__to_newick, input_integers)

#' Convert a newick string to a Phylo2Vec vector
#' @export
to_vector <- function(newick) .Call(wrap__to_vector, newick)

#' Validate a Phylo2Vec vector
#' @export
check_v <- function(input_integers) invisible(.Call(wrap__check_v, input_integers))


Expand Down
82 changes: 78 additions & 4 deletions r-phylo2vec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,100 @@
**NOTE: This is currently in active development and APIs will change. Use at
your own risk.**

This directory contains the pylo2vec R codebase, which includes Rust binding
This directory contains the phylo2vec R codebase, which includes Rust binding
setup.

## Quick install and run

To quickly install the package and run it, simply run the following

```console
pixi run -e r-phylo2vec install-r
```

Once the package is installed you can open up the R terminal:

```console
pixi run -e r-phylo2vec R --interactive
```

In the R terminal, you can then import the `phylo2vec` library:

```R
library(phylo2vec)

# A small demo
v = sample(10, FALSE)
to_newick(v)
```

## Development Guide

The core Rust code for phylo2vec is located in [phylo2vec](../phylo2vec)
directory. To add additional bindings for the Rust code, you can add more define
these in [`lib.rs`](./src/rust/src/lib.rs).

It uses [extendr](https://github.com/extendr/extendr), a safe and user-friendly
R extension interface using Rust. You should be able to directly import the
necessary functions from `phylo2vec` Rust crate.

**Note: You will need to run the steps below from the root of the repository for
it to work**

Open up `R` command line interactive mode within the pixi environment:

```console
pixi run -e r-phylo2vec R --interactive
```

Once in R, you can run the following to start using the package:
### 1. Modify `src/rust/src/lib.rs`

Add the function with @export, so it will get exported from the generated R
package. (Without this tag, the function would be available internally for
package programming but not externally to users of the package.)

```Rust
/// Recover a rooted tree (in Newick format) from a Phylo2Vec v
/// @export
#[extendr]
fn to_newick(input_integers: Vec<i32>) -> String {
let input_vector = input_integers.iter().map(|&x| x as usize).collect();
let newick = ops::to_newick(&input_vector);
newick
}
```

Don’t forget to add the function to `extendr_module!`:

```Rust
extendr_module! {
mod phylo2vec;
...
fn to_newick;
...
}
```

### 2. Run `rextendr::document` for building docs and binding R code

To rebuild the docs and binding code for R, you can simply run
`rextendr::document`:

```R
# Install rextendr if not already installed
install.packages("rextendr")

# Install phylo2vec package
rextendr::document('./r-phylo2vec')
```

### 3. Run `devtools::load_all` and test the function

# Import the library
library('phylo2vec')
Once in R, you can run the following to load and use the package:

```R
# Compile, install, and load phylo2vec package
devtools::load_all('./r-phylo2vec')

# A small demo
v = sample(5, FALSE)
Expand Down
17 changes: 17 additions & 0 deletions r-phylo2vec/scripts/install-package.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# File to run binary build and install for the package
# Usage: Rscript install-package.R <package-path>

args = commandArgs(trailingOnly=TRUE)

if (length(args)==0) {
# default path from root
args[1] = "./r-phylo2vec"
}

fn = devtools::build(args[1], binary = TRUE, args = c('--preclean'))

devtools::install_local(fn, force = TRUE)

if (file.exists(fn)) {
file.remove(fn)
}
11 changes: 11 additions & 0 deletions r-phylo2vec/scripts/run-tests.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# File to run tests for the package
# Usage: Rscript run-tests.R <package-path>

args = commandArgs(trailingOnly=TRUE)

if (length(args)==0) {
# default path from root
args[1] = "./r-phylo2vec"
}

devtools::test(args[1], stop_on_failure = TRUE)
4 changes: 4 additions & 0 deletions r-phylo2vec/src/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ use phylo2vec::tree_vec::ops;
use phylo2vec::utils;

/// Sample a random tree via Phylo2Vec
/// @export
#[extendr]
fn sample(n_leaves: usize, ordered: bool) -> Vec<i32> {
let v = utils::sample(n_leaves, ordered);
v.iter().map(|&x| x as i32).collect()
}

/// Recover a rooted tree (in Newick format) from a Phylo2Vec v
/// @export
#[extendr]
fn to_newick(input_integers: Vec<i32>) -> String {
let input_vector = input_integers.iter().map(|&x| x as usize).collect();
Expand All @@ -19,13 +21,15 @@ fn to_newick(input_integers: Vec<i32>) -> String {
}

/// Convert a newick string to a Phylo2Vec vector
/// @export
#[extendr]
fn to_vector(newick: &str) -> Vec<i32> {
let v = ops::to_vector(&newick);
v.iter().map(|&x| x as i32).collect()
}

/// Validate a Phylo2Vec vector
/// @export
#[extendr]
fn check_v(input_integers: Vec<i32>) {
let input_vector = input_integers.iter().map(|&x| x as usize).collect();
Expand Down
12 changes: 12 additions & 0 deletions r-phylo2vec/tests/testthat.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This file is part of the standard setup for testthat.
# It is recommended that you do not modify it.
#
# Where should you do additional test configuration?
# Learn more about the roles of various files in:
# * https://r-pkgs.org/testing-design.html#sec-tests-files-overview
# * https://testthat.r-lib.org/articles/special-files.html

library(testthat)
library(phylo2vec)

test_check("phylo2vec")
12 changes: 12 additions & 0 deletions r-phylo2vec/tests/testthat/test_to_newick.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
library(testthat)
library(phylo2vec)

test_that(desc = "Vector to newick", code = {

vec <- c(0L, 0L, 0L, 1L, 3L)

newick <- to_newick(vec)

# Test that the result is the correct value
expect_equal( newick, "(((0,(3,5)6)8,2)9,(1,4)7)10;");
})
Loading