The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Package {bioIOT}


Type: Package
Title: Inverse Optimal Transport for Single-Cell Trajectory Analysis
Version: 0.2.2
Description: Semi-relaxed inverse optimal transport (IOT) for single-cell state-transition and pseudotime analysis: a self-contained R solver (Anderson-accelerated soft Sinkhorn with exact implicit gradients), feature-weight fitting with a two-stage bias-corrected refit and multi-restart, state transition matrices, random-walk pseudotime, 'ggplot2' visualisation, soft-gated 'Seurat' and 'SingleCellExperiment' interfaces, reproducible simulated demo data, and bulk-cohort pathway scoring utilities.
License: MIT + file LICENSE
Encoding: UTF-8
Depends: R (≥ 4.0.0)
Imports: utils, ggplot2
Suggests: testthat (≥ 3.0.0), knitr, rmarkdown, SingleCellExperiment, Seurat, SummarizedExperiment, S4Vectors
URL: https://github.com/XTSgreen/bioIOT-R
BugReports: https://github.com/XTSgreen/bioIOT-R/issues
VignetteBuilder: knitr
Config/testthat/edition: 3
NeedsCompilation: no
Packaged: 2026-09-14 15:40:40 UTC; XTS-green
Author: Han Dong [aut, cre] (Nickname: XTSgreen)
Maintainer: Han Dong <dh411424@163.com>
Repository: CRAN
Date/Publication: 2026-09-24 13:40:24 UTC

Collapse a probe-level expression matrix to gene level

Description

For each gene symbol keep the probe with the highest cross-sample mean expression. This is the paper's probe-annotation folding rule.

Usage

collapse_probes(expr, probe_id = rownames(expr), gene_id)

Arguments

expr

Probe x sample numeric matrix.

probe_id

Character vector of probe ids, length nrow(expr) (defaults to rownames(expr)).

gene_id

Character vector of gene symbols matching probe_id; NA / empty entries are dropped.

Value

Gene x sample numeric matrix (rownames = gene symbols).

Examples

expr <- matrix(rnorm(40), nrow = 4)
colnames(expr) <- paste0("S", 1:10)
collapse_probes(expr, c("P1", "P2", "P3", "P4"),
                c("VIM", "VIM", "CDH2", "MYC"))

Bundled bioIOT demo dataset

Description

Pre-computed synthetic demo data for quick experimentation with fit_iot, transition_matrix and runIOT. Regenerate with bioIOT::simulate_iot_states(seed = 1).

Format

A list as returned by simulate_iot_states(seed = 1) with default arguments: u, phi, a, b, P_true, T_true, theta_true, embedding, K, F_emb, cell_embedding, cell_state, cell_time.

Examples

data(demo_iot_states)
names(demo_iot_states)
demo_iot_states$K

Fit inverse optimal transport feature weights

Description

Fits feature weights \theta so that the soft-marginal OT plan induced by C = -einsum(\phi, \theta) reproduces the observed row-conditional transitions T. Two-stage fitting (l1 selection then Buehlmann-style debias refit) with multi-restart; gradients are exact implicit differentiations of the fixed point (implicit function theorem), which stays numerically stable where unrolled backpropagation diverges.

Usage

fit_iot(phi, a, b, T_obs, mu = 0.5, lam = 0.05, eps = 1, epochs = 300,
  lr = 0.01, n_restart = 4, seed = 1, two_stage = TRUE,
  iters = 1000L, damp = 0.5, standardize = TRUE, verbose = FALSE)
## S3 method for class 'bioIOT_fit'
print(x, ...)
## S3 method for class 'bioIOT_fit'
summary(object, ...)

Arguments

phi

(K, K, F) feature array, or a list of arrays (scenarios).

a, b

(K,) masses, or lists (auto-normalized).

T_obs

(K, K) observed row-conditional transitions, or a list.

mu

Soft-marginal strength (default 0.5, paper working point).

lam

l1 strength in stage 1 (default 0.05).

eps

Entropic regularization (default 1).

epochs

Adam steps per stage (default 300).

lr

Adam learning rate (default 0.01).

n_restart

Random restarts (default 4).

seed

Base seed for restart inits.

two_stage

Debias refit on the selected support (default TRUE).

iters, damp

Forward solver controls.

standardize

Z-score each scenario's features before fitting (default TRUE, paper pipeline).

verbose

Print progress.

x

A bioIOT_fit object.

object

A bioIOT_fit object.

...

Unused.

Value

Object of class bioIOT_fit with components theta (debiased weights), theta1 (stage-1 weights), support (logical mask), loss (final row-CE), restart_losses, scenarios (stored standardized scenarios), meta (standardization transforms), hyper and dimensions K, n_feat.

Examples

set.seed(1)
sim <- simulate_iot_states(K = 5, seed = 1)
fit <- fit_iot(sim$phi, sim$a, sim$b, sim$T_true, n_restart = 1, epochs = 100)
fit$theta
summary(fit)

Extract GSM ids from CEL filenames

Description

Extract GSM sample ids from CEL filenames, vectorized.

Usage

gsm_id(filenames)

Arguments

filenames

Character vector of filenames such as "GSM1523727_INT_A.CEL.gz".

Value

Character vector of GSM ids; NA where no match.

Examples

gsm_id(c("GSM1523727_INT_A.CEL.gz", "sample_no_id.CEL", NA))

Cost construction, likelihood and feature standardization

Description

make_cost: linear feature cost C_{ij} = -\sum_k \phi_{ijk} \theta_k. row_ce_loss: cross-entropy between observed row-conditional transitions and the model Q = P/a; zero-mass source states are masked out. zscore_phi: z-scores each feature across all (i, j) entries and returns the transform for re-application.

Usage

make_cost(phi, theta)
row_ce_loss(T_obs, P, a, eps_t = 1e-12)
zscore_phi(phi)

Arguments

phi

(K, K, F) feature array; a (K, K) matrix is promoted to a single feature.

theta

Numeric length F (a scalar is recycled for 2-D phi).

T_obs

(K, K) observed row-conditional transition matrix.

P

(K, K) model plan.

a

(K,) source masses.

eps_t

Log floor.

Value

make_cost: (K, K) cost matrix. row_ce_loss: numeric loss (lower is better). zscore_phi: list with phi_z ((K, K, F) standardized array) and meta (2 x F matrix with rows "mean" and "sd").

Examples

phi <- array(rnorm(3 * 3 * 2), c(3, 3, 2))
C <- make_cost(phi, c(1, -1))
out <- zscore_phi(phi)
row_ce_loss(matrix(0.5, 3, 3), matrix(0.25, 3, 3), rep(1, 3) / 3)

IOT pathway marker genes (8 pathways)

Description

The pathway marker gene library used by the paper's 8-dimensional IOT cost features: EMT, Angiogenesis, Hypoxia, Stemness, Immune_Cytotoxic, CellCycle, TGFb and Chemokine. Genes are HGNC symbols.

Usage

pathway_markers

Value

A named list of 8 character vectors of HGNC gene symbols.

Examples

names(pathway_markers)
length(pathway_markers$EMT)

bioIOT visualisation

Description

plot_transition_heatmap: transition-matrix heatmap with annotated weights. plot_transition_flow: transition arrows on a 2-D state embedding, width proportional to transition mass (CellRank-style). plot_theta: barplot of fitted feature weights, selected support highlighted. plot_pathway_trend: pathway score trajectories over time (loess).

Usage

plot_transition_heatmap(Q, labels = NULL)
plot_transition_flow(Q, embedding, labels = NULL, threshold = 0.05)
plot_theta(fit, labels = NULL)
plot_pathway_trend(pw_scores, time, se = TRUE)

Arguments

Q

(K, K) row-stochastic transition matrix.

labels

Optional state / feature labels.

embedding

(K x >= 2) state coordinates (e.g. cluster centroids).

threshold

Minimum transition mass to draw an arrow.

fit

A bioIOT_fit object (or named numeric weights with an optional support attribute).

pw_scores

Sample x pathway score matrix.

time

Numeric time / pseudotime per sample (row).

se

Show the smooth confidence band (default TRUE).

Value

A ggplot object.

Examples

Q <- matrix(c(0.7, 0.3, 0, 0.2, 0.6, 0.2, 0.1, 0.1, 0.8), 3, 3, byrow = TRUE)
plot_transition_heatmap(Q)
emb <- matrix(c(0, 0, 1, 1, 2, 0), 3, 2, byrow = TRUE)
plot_transition_flow(Q, emb)

set.seed(1)
sim <- simulate_iot_states(K = 5, seed = 1)
fit <- fit_iot(sim$phi, sim$a, sim$b, sim$T_true, n_restart = 1, epochs = 100)
plot_theta(fit)

expr <- matrix(rnorm(200 * 12), nrow = 200)
rownames(expr) <- paste0("G", 1:200)
colnames(expr) <- paste0("S", 1:12)
rownames(expr)[1] <- "VIM"; rownames(expr)[2] <- "CDH2"; rownames(expr)[3] <- "MKI67"
plot_pathway_trend(score_pathways(expr), time = sort(runif(12)))

Run IOT on a single-cell object

Description

Aggregates cells into states (clusters), builds state-transition features from the cell embedding, optionally fits IOT weights against observed transitions T_obs, and returns the state transition matrix with optional random-walk pseudotime.

Usage

runIOT(object, ...)

## S3 method for class 'matrix'
runIOT(object, state, from, to, root = NULL,
  n_dim = NULL, T_obs = NULL, mu = 0.5, eps = 1, lam = 0.05,
  epochs = 300, lr = 0.01, n_restart = 4, seed = 1,
  two_stage = TRUE, ...)

## S3 method for class 'SingleCellExperiment'
runIOT(object, state_col, time_col,
  from, to, dimred = "PCA", root = NULL, ...)

## S3 method for class 'Seurat'
runIOT(object, group.by = NULL, split.by = NULL,
  from = NULL, to = NULL, reduction = "pca", root = NULL, ...)

Arguments

object

Cell embedding matrix (cells x dims) or a SingleCellExperiment / Seurat object.

state

Factor/character of state (cluster) labels, one per cell.

from, to

Logical vectors or indices marking source / target timepoint cells.

root

Optional root state (name or index) for pseudotime.

n_dim

Number of embedding dims used as state features.

T_obs

Optional (K, K) observed row-conditional transition matrix (e.g. from lineage/clone data). When given, feature weights are fitted; otherwise the plan is solved with uniform feature weights.

mu, eps, lam, epochs, lr, n_restart, seed, two_stage

Passed to fit_iot (only used when T_obs is given).

state_col

State label column in colData (or a vector).

time_col

Timepoint column in colData (or a vector).

dimred

Reduced dimension name (default "PCA").

group.by

Seurat ident / metadata column for states.

split.by

Metadata column holding the timepoint values from/to.

reduction

Reduction name (default "pca").

...

Additional arguments.

Value

List with fit (bioIOT_fit or NULL), Q (transition matrix), u (state centroids), a, b, phi, theta and pseudotime (if root given).

Examples

set.seed(1)
sim <- simulate_iot_states(K = 5, n_cells = 40, seed = 1)
res <- runIOT(sim$cell_embedding, sim$cell_state,
              from = sim$cell_time == "t0", to = sim$cell_time == "t1",
              root = "S1", n_restart = 1, epochs = 100)
res$Q[1:3, 1:3]
res$pseudotime

Score bulk-cohort samples on the 8 IOT pathways

Description

Per-gene z-scores across samples, then the mean of the pathway marker genes per sample. Exactly the scoring used to build the paper's bulk pathway scores from gene x sample expression matrices.

Usage

score_pathways(expr_gene, markers = pathway_markers)

Arguments

expr_gene

Gene x sample numeric matrix (rownames = gene symbols).

markers

Named list of character vectors; default pathway_markers (8 pathways).

Value

Sample x pathway numeric matrix (rownames = sample ids, colnames = pathway names). Pathways without any marker present in expr_gene yield NA columns.

Examples

set.seed(1)
expr <- matrix(rnorm(200 * 6), nrow = 200)
rownames(expr) <- paste0("G", 1:200)
colnames(expr) <- paste0("S", 1:6)
rownames(expr)[1] <- "VIM"; rownames(expr)[2] <- "CDH2"
pw <- score_pathways(expr)
dim(pw)

Simulate single-cell state-transition data for bioIOT

Description

Generates a reproducible synthetic single-cell-like dataset: states with feature centroids, source/target timepoint masses, a true IOT plan and transition matrix, plus cell-level metadata for runIOT. The bundled demo_iot_states dataset is produced by this function with its default seed.

Usage

simulate_iot_states(K = 6, F_emb = 2, n_cells = 50, seed = 1,
  theta_true = c(0.9, -0.7, 1.1), mu = 0.5, eps = 1)

Arguments

K

Number of states.

F_emb

Number of state feature dimensions (>= 2 for plotting).

n_cells

Cells per state per timepoint.

seed

Random seed.

theta_true

True feature weights (length F_emb + 1).

mu

Solver hyperparameter used to build the true plan.

eps

Solver hyperparameter used to build the true plan.

Value

List with u (K x F_emb state centroids), phi ((K, K, F_emb + 1) features), a, b (normalized state masses), P_true, T_true (row-conditional), theta_true, embedding (K x 2 state coordinates), K, F_emb, cell_embedding (cells x F_emb), cell_state and cell_time (cell-level factors).

Examples

sim <- simulate_iot_states(K = 5, seed = 1)
names(sim)
round(sim$T_true, 2)

Semi-relaxed OT solver and row-conditional transitions

Description

soft_sinkhorn solves the row-marginal-hard / column-marginal-KL-soft problem \min_P \langle C, P \rangle - \epsilon H(P) + \mu\, KL(col(P) \| b) subject to P 1 = a, via Anderson-accelerated damped fixed-point iteration. row_conditional returns Q(i,\cdot) = P(i,\cdot) / a_i.

Usage

soft_sinkhorn(C, a, b, mu = 0.5, eps = 1, iters = 1000L, damp = 0.5,
  tol = 1e-12)
row_conditional(P, a, eps_t = 1e-300)

Arguments

C

(K, K) cost matrix.

a, b

(K,) source / target masses; any positive scale is accepted (auto-normalized). Zero-mass states are allowed in a.

mu

Soft-marginal strength; large mu approaches hard-marginal OT, mu = 0 recovers a plain row-softmax.

eps

Entropic regularization (> 0).

iters

Fixed-point iteration cap.

damp

Damping factor of the base iteration.

tol

Fixed-point residual tolerance.

P

(K, K) transport plan.

eps_t

Numerical floor.

Value

soft_sinkhorn: (K, K) transport plan with row sums equal to the normalized a. row_conditional: (K, K) matrix; rows with a_i = 0 are all-zero.

Examples

K <- 5
set.seed(1)
P <- soft_sinkhorn(matrix(rnorm(25), 5), rep(1, 5), rep(1, 5))
rowSums(P)
row_conditional(P, rep(1, 5) / 5)

Inspect a GEO RAW tar without extracting

Description

Check whether a GEO *_RAW.tar contains CEL data files or only platform (bgx.gz) files, without extracting the archive.

Usage

has_cel_file(tar_path)
find_platform_file(tar_path)

Arguments

tar_path

Path to a *_RAW.tar archive.

Value

has_cel_file: TRUE if the tar contains *.CEL (optionally .gz) members. find_platform_file: the first *.bgx.gz platform filename, or NA_character_.

Examples

d <- file.path(tempdir(), "bioIOT-tar-example")
dir.create(d, showWarnings = FALSE)
cel <- file.path(d, "sample.CEL.gz")
bgx <- file.path(d, "platform.bgx.gz")
writeLines("demo", cel)
writeLines("demo", bgx)
tmp_tar <- tempfile(fileext = ".tar")
utils::tar(tmp_tar, c(cel, bgx), tar = "internal")
has_cel_file(tmp_tar)
find_platform_file(tmp_tar)
unlink(c(tmp_tar, d), recursive = TRUE)

Transition matrix, pseudotime and state features

Description

transition_matrix: re-solves the plan at the fitted \theta and returns Q = P/a. pseudotime_from_transition: expected number of random-walk steps to reach the root state (root absorbing), turning an IOT transition matrix into per-state pseudotime. build_state_features: builds the paper's feature library: per-dimension pure-column target-state features plus the state-similarity interaction block \phi_{ij,F+1} = u_i \cdot u_j.

Usage

transition_matrix(fit, which = 1, phi = NULL, a = NULL, b = NULL)
pseudotime_from_transition(Q, root)
build_state_features(u)

Arguments

fit

A bioIOT_fit object.

which

Scenario index (default 1).

phi, a, b

Optional user-supplied scenario overriding the stored one (phi must be standardized the same way as in the fit).

Q

(K, K) row-stochastic transition matrix.

root

Root state: integer index or a name matching rownames of Q.

u

(K, D) matrix of state feature vectors (e.g. cluster centroids in a reduced space).

Value

transition_matrix: (K, K) row-stochastic transition matrix. pseudotime_from_transition: named numeric vector of expected random-walk hitting times (root = 0). build_state_features: (K, K, D + 1) feature array with dimnames list(NULL, NULL, c(colnames(u), "sim")).

Examples

set.seed(1)
sim <- simulate_iot_states(K = 5, seed = 1)
fit <- fit_iot(sim$phi, sim$a, sim$b, sim$T_true, n_restart = 1, epochs = 100)
Q <- transition_matrix(fit)
rowSums(Q)
pseudotime_from_transition(Q, root = 1)
u <- matrix(rnorm(6 * 2), 6, 2, dimnames = list(NULL, c("PC1", "PC2")))
dim(build_state_features(u))

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.