Skip to contents

Install

msuiter is a source install: the numerical kernels are a Rust workspace that R CMD INSTALL builds through the package configure face, so the toolchain floors stated in DESCRIPTION bind the install itself. The committed renv lockfile pins the R and package universe the campaign is validated against; restoring it before installing keeps the floor question answered by bytes rather than by luck.

if (!is.na(PKG)) {
  desc <- readLines(file.path(PKG, "DESCRIPTION"), warn = FALSE)
  print(desc[grepl("^Package:|^Version:|^Depends:|^SystemRequirements:",
                   desc)])
  lockfile <- file.path(PKG, "inst", "repro", "renv.lock")
  if (file.exists(lockfile)) {
    print(basename(lockfile))
  } else if (!dir.exists(file.path(PKG, "inst", "repro"))) {
    # inst/repro ships inside the source package, so this branch is the
    # synthetic-root face of the governing test rather than a real build
    # context; say so rather than stopping.
    print("renv.lock: outside this build context")
  } else {
    stop("committed renv lockfile missing from its own committed directory")
  }
} else {
  print("install face reads the source DESCRIPTION")
}
#> [1] "Package: msuiter"                          
#> [2] "Version: 0.1.0.9000"                       
#> [3] "Depends: R (>= 4.3)"                       
#> [4] "SystemRequirements: cargo, rustc (>= 1.71)"
#> [1] "renv.lock"

With a checkout in hand, the install face is one command:

R CMD INSTALL msuiter   # from the source root; configure builds the Rust core

Without a checkout, install the development build straight from GitHub – the same configure face builds the Rust core on the way in:

Rscript -e 'remotes::install_github("WangLabCSU/msuiter")'

Prebuilt packages are attached to the tagged release and install from a local file with install.packages(<file>, repos = NULL). There is no CRAN release yet.

Five-minute path

One chain, four faces, end to end: ms_variants() validates the typed input IR, ms_tally() runs it through the Rust kernel over a micro twoBit genome into a channel table, ms_signature() mounts the committed specimen matrix as a signature dictionary pinned to that channel table, and the bundled reference face arrives as an MsRefDb – the COSMIC v3.6 dictionaries ship inside the package, so the trusted default needs no download.

The genome is the same synthetic writer the tour uses: a trivial chromosome whose bases agree with the variant records base for base, so every printed number below is real kernel output over committed bytes.

.u32le <- function(v) writeBin(as.integer(v), raw(), size = 4L,
                               endian = "little")
.pack_bases <- function(bases) {
  out <- raw((length(bases) + 3L) %/% 4L)
  acc <- 0L; filled <- 0L; k <- 0L
  for (b in bases) {
    acc <- bitwOr(bitwShiftL(acc, 2L), b); filled <- filled + 1L
    if (filled == 4L) { k <- k + 1L; out[k] <- as.raw(acc); acc <- 0L; filled <- 0L }
  }
  if (filled > 0L) out[k + 1L] <- as.raw(bitwShiftL(acc, 2L * (4L - filled)))
  out
}
.write_2bit <- function(path) {
  chr1 <- rep(c(2L, 1L), 32L)
  chr2 <- rep(c(3L, 1L), 20L)
  recs <- list(
    list(name = "chr1", size = 64L, dna = .pack_bases(chr1),
         nb = integer(0), nl = integer(0)),
    list(name = "chr2", size = 40L, dna = .pack_bases(chr2),
         nb = integer(0), nl = integer(0)))
  off <- 16L + sum(vapply(recs, function(r) 1L + nchar(r$name) + 4L, 0L))
  index <- raw(); body <- raw()
  for (r in recs) {
    index <- c(index, as.raw(nchar(r$name)), charToRaw(r$name), .u32le(off))
    rec <- c(.u32le(r$size), .u32le(length(r$nb)), .u32le(r$nb), .u32le(r$nl),
             .u32le(0L), .u32le(0L), r$dna)
    body <- c(body, rec); off <- off + length(rec)
  }
  bytes <- c(.u32le(0x1A412743L), .u32le(0L), .u32le(length(recs)),
             .u32le(0L), index, body)
  con <- file(path, "wb"); on.exit(close(con), add = TRUE)
  writeBin(bytes, con); invisible(path)
}
genome <- file.path(tempdir(), "getstarted-2bit.2bit")
.write_2bit(genome)
tab <- data.frame(
  chrom  = c("chr1", "chr1", "chr1"),
  start  = c(12L, 22L, 14L),
  end    = c(12L, 22L, 14L),
  ref    = c("C", "C", "C"),
  alt    = c("A", "T", "T"),
  sample = c("S1", "S1", "S2"))
v <- ms_variants(tab, "GRCh38", caller = "get-started",
                 matched_normal = "none")
v
#> <MsVariants> 3 variants | genome: GRCh38
cat1 <- ms_tally(v, genome)
cat1
#> <MsCatalog> SBS96: 96 channels x 2 samples; skipped 0/3 variants

The signature dictionary is the committed specimen itself – read verbatim, its first two columns mounted under the channel labels the tally produced, so every exposure figure below is the fixture’s own number and the channel hash is derived from the validated catalog, never hand-forged:

raw_spec <- utils::read.delim(FIX, check.names = FALSE,
                              stringsAsFactors = FALSE)
labels <- cat1@channels$labels
spec <- as.matrix(raw_spec[, 2L:3L, drop = FALSE])
rownames(spec) <- raw_spec[[1L]]
if (!identical(rownames(spec), labels)) stop("specimen rows must ride the channel labels")
exposures <- matrix(c(0.6, 0.4), 2L, 1L,
                    dimnames = list(colnames(spec), "S1"))
summary1 <- list(
  n_channels   = length(labels), n_samples = 1L,
  channel_name = cat1@channels$name, channel_hash = cat1@channels$hash,
  build = "GRCh38")
sig <- ms_signature(spec, exposures, summary1, engine = "synthetic", seed = 1L)
sig
#> <MsSignature> 2 signatures x 1 samples | engine: synthetic | seed: 1
br <- ms_refdb_bundled()
db <- br[["SBS_GRCh38"]]
db
#> <MsRefDb> class: SBS | version: v3.6 | 1 matrices
head(db@matrices[[1L]][, 1L:3L], 3L)
#>                 SBS1         SBS2        SBS3
#> A[C>A]A 0.0008760226 5.789892e-07 0.020919749
#> A[C>A]C 0.0022201200 1.455043e-04 0.016343192
#> A[C>A]G 0.0001797268 5.361706e-05 0.001807548

Anatomy of the output

The MsSignature above is a typed object, not a loose matrix: the signature matrix, the exposure matrix, the pinned channel summary and the provenance (engine, seed) are separate slots, each validated at the boundary that owns it.

print(class(sig))
#> [1] "msuiter::MsSignature" "S7_object"
str(sig)
#> <msuiter::MsSignature>
#>  @ signatures     : num [1:96, 1:2] 2.18e-03 8.57e-05 1.30e-04 4.07e-04 2.39e-03 ...
#>  .. - attr(*, "dimnames")=List of 2
#>  ..  ..$ : chr [1:96] "A[C>A]A" "A[C>A]C" "A[C>A]G" "A[C>A]T" ...
#>  ..  ..$ : chr [1:2] "SBS96A" "SBS96B"
#>  @ exposures      : num [1:2, 1] 0.6 0.4
#>  .. - attr(*, "dimnames")=List of 2
#>  ..  ..$ : chr [1:2] "SBS96A" "SBS96B"
#>  ..  ..$ : chr "S1"
#>  @ stability      : list()
#>  @ k_evidence     :'data.frame': 0 obs. of  0 variables
#>  @ engine         : chr "synthetic"
#>  @ seed           : int 1
#>  @ catalog_summary:List of 5
#>  .. $ n_channels  : int 96
#>  .. $ n_samples   : int 1
#>  .. $ channel_name: chr "SBS96"
#>  .. $ channel_hash: chr "1edf6b63f9d98c7b6c62744d09d69889"
#>  .. $ build       : chr "GRCh38"
print(dim(sig@signatures))
#> [1] 96  2
print(dim(sig@exposures))
#> [1] 2 1
print(sig@engine)
#> [1] "synthetic"
print(substr(sig@catalog_summary$channel_hash, 1L, 16L))
#> [1] "1edf6b63f9d98c7b"

The channel hash printed above is the tamper seal: it is recomputed from the validated channel table, and a hand-edited dictionary is refused at construction – the same seal the tour demonstrates from the refusing side.

Where to go next

The concept bridge is vignettes/articles/msu-map.qmd (one row per export: concept, pillar, peer counterpart). The narrative tour continues in tour.html; the whole docs corpus is navigated from docs-bridge.html; every exported face is documented in the reference index.