| name | bio-temporal-genomics-trajectory-modeling |
| description | Models continuous temporal trajectories from bulk or time-resolved omics data using generalized additive models (mgcv), spline regression, and changepoint detection (segmented, ruptures). Fits smooth gene expression curves and tests trajectory differences between conditions. Use when fitting non-linear temporal models to bulk time-series data or comparing developmental trajectories across conditions. Not for single-cell pseudotime (see single-cell/trajectory-inference). |
| tool_type | mixed |
| primary_tool | mgcv |
Temporal Trajectory Modeling
Fits smooth non-linear curves to gene expression time series using generalized additive models (GAMs) and detects abrupt changes in temporal dynamics using changepoint algorithms.
Core Workflow
- Prepare expression data with timepoint and condition metadata
- Fit GAM or spline models per gene
- Test for significant temporal trends and condition differences
- Detect changepoints where trajectory dynamics shift
- Predict and visualize fitted trajectories with confidence intervals
mgcv GAM (R)
Basic GAM Fitting
library(mgcv)
fit <- gam(expression ~ s(time, k = 6), data = gene_df, method = 'REML')
summary(fit)
Condition Comparison with GAM
fit_cond <- gam(
expression ~ condition + s(time, k = 6, by = condition),
data = gene_df, method = 'REML'
)
fit_diff <- gam(
expression ~ s(time, k = 6) + s(time, k = 6, by = is_treated),
data = gene_df, method = 'REML'
)
summary(fit_diff)
Model Diagnostics
gam.check(fit)
concurvity(fit_cond, full = TRUE)
Prediction and Visualization
new_data <- data.frame(time = seq(min(gene_df$time), max(gene_df$time), length.out = 200))
pred <- predict(fit, newdata = new_data, se.fit = TRUE)
new_data$fitted <- pred$fit
new_data$lower <- pred$fit - 1.96 * pred$se.fit
new_data$upper <- pred$fit + 1.96 * pred$se.fit
Genome-Wide GAM Fitting
results <- data.frame()
for (gene in rownames(expr_mat)) {
gene_df <- data.frame(expression = as.numeric(expr_mat[gene, ]), time = timepoints)
fit <- gam(expression ~ s(time, k = 6), data = gene_df, method = 'REML')
s_table <- summary(fit)$s.table
results <- rbind(results, data.frame(
gene = gene, edf = s_table[, 'edf'],
F_stat s_table p_value s_table
resultsq_value p.adjustresultsp_value method
temporal_genes resultsresultsq_value
tradeSeq (R/Bioconductor)
Wrapper around mgcv designed for trajectory analysis with built-in statistical tests.
library(tradeSeq)
sce <- fitGAM(counts = count_mat, pseudotime = time_mat, cellWeights = weight_mat, nKnots = 6)
assoc_res <- associationTest(sce)
cond_res <- conditionTest(sce)
segmented (R)
Piecewise linear regression with automatic breakpoint detection.
library(segmented)
lm_fit <- lm(expression ~ time, data = gene_df)
seg_fit <- segmented(lm_fit, seg.Z = ~time, psi = NA)
davies.test(lm_fit, seg.Z = ~time)
summary(seg_fit)$psi
ruptures (Python)
Changepoint detection for identifying abrupt shifts in temporal dynamics.
import numpy as np
import ruptures as rpt
signal = np.array(expression_values)
algo = rpt.Pelt(model='rbf', min_size=2).fit(signal)
n = len(signal)
penalty = np.log(n) * np.var(signal)
changepoints = algo.predict(pen=penalty)
Binary Segmentation Alternative
algo_binseg = rpt.Binseg(model='rbf', min_size=2).fit(signal)
changepoints_binseg = algo_binseg.predict(n_bkps=3)
Genome-Wide Changepoint Detection
import pandas as pd
results = []
for gene_idx in range(expr_mat.shape[0]):
signal = expr_mat[gene_idx, :]
algo = rpt.Pelt(model='rbf', min_size=2).fit(signal)
penalty = np.log(len(signal)) * np.var(signal)
bkps = algo.predict(pen=penalty)
n_changes = len(bkps) - 1
results.append({'gene': f'gene_{gene_idx}', 'n_changepoints': n_changes,
'changepoint_indices': bkps[:-1]})
results_df = pd.DataFrame(results)
Model Comparison
| Method | Model Type | Best For | Key Parameter |
|---|
| mgcv GAM | Smooth non-linear | Continuous trajectories | k (basis dimension) |
| tradeSeq | GAM wrapper | Condition comparison | nKnots |
| segmented | Piecewise linear | Breakpoint detection | psi (initial guess) |
| ruptures Pelt | Changepoint | Abrupt dynamic shifts | penalty |
| ruptures BinSeg | Changepoint | Fast approximate | n_bkps |
Tips
- GAMs with REML estimation are preferred over GCV for smooth parameter estimation; REML is less prone to overfitting
- Always run gam.check() to verify basis dimension is sufficient (k-index should be >= 1.0)
- For comparing conditions, the difference smooth approach (by=is_treated) directly tests trajectory divergence
- Changepoint methods complement GAMs: use GAMs for smooth trends, changepoints for abrupt shifts
- AIC/BIC comparison between linear and GAM fits reveals whether non-linear modeling is warranted
Related Skills
- temporal-clustering - Group genes after trajectory fitting
- circadian-rhythms - Periodic trajectory models
- differential-expression/timeseries-de - Linear model alternatives for temporal DE
- single-cell/trajectory-inference - Single-cell pseudotime trajectories