Changelog
Source:NEWS.md
TSENAT 0.99.35
-
Statistical inference hardening (August 2026). Main changes:
-
Functional reframing of q: q is a deterministic functional argument of the Tsallis statistic, not a time index. ARIMA(1,1,0) differencing was removed from all confirmatory paths (GEE, GAM/GAMM, LMM, FPCA) — the interaction is now tested on the original H(q) curve (H0: beta(q) = 0 for all q); the legacy differencing helpers (
.compute_arima_differences,.apply_arima_differencing,.apply_arima_differencing_fpca) and their tests were deleted, and the LMM fallbackslope_diffis now extracted from fixed effects (nlme::fixef) instead of per-subject coefficients.. -
Correlation structure: AR(1)-type within subject × condition modelled over actual q distances (
nlme::corCAR1, Corr(e_i, e_j) = exp(-φ|q_i - q_j|)) as the primary structure in GAMM and LMM, so irregular q grids are handled correctly (the q-grid-indexrho^|Δgrid|form, which is valid only on equally spaced grids, is kept as a documented fallback and for the legacy mgcv paths); GEE fits H(q) with a joint Wald test and a small-cluster F reference (df = n_clusters − p); the AR(1) design effect is descriptive-only. -
Salmon input integrity (audit hardening): Salmon quantification files are now matched by transcript ID rather than positional order; transcript sets and sample identifiers must be unique and consistent across files (a mismatch is a hard error, not a warning), and negative or non-finite quantification values are rejected at input. Paired-design bootstrap also validates the 1-control + 1-treatment-per-pair invariant before resampling. * TPM/effective-length contract: diversity is computed from raw counts with effective-length correction;
tpm = TRUEtogether with aneffective_length(parameter or SummarizedExperiment metadata) is now a hard error, since TPM already incorporates effective-length normalization (double normalization rejected). TPM remains available for abundance-based filtering/QC. -
Pseudocount ordering and
'auto'resolution: effective-length normalization is now applied BEFORE the pseudocount, so regularization is constant on the effective-abundance scale (previously the count-space pseudocount was implicitly divided by transcript length, systematically boosting short isoforms);pseudocount = 'auto'is now estimated from the resolved raw-count matrix after input resolution and is rejected for TPM input. * Paired GAMM:nlme::lmewithns(q, df = 3) × conditionand a marginal F-test (mgcv gamm is singular on paired designs); no p-value underflow for strong signals (log-space recomputation) and pseudo-R²effect_size;slope_difffrom population-level predictions; fit metadata recordsmodel_used/fallback_level/correlation_structure/test_type. -
Bootstrap resampling invariant: the read-level bootstrap now resamples from exactly the point-estimate proportions
(x/l + c)/sum(x/l + c)— the pseudocount is embedded on the effective-abundance scale BEFORE the depth rescale (previously it was added after the rescale, breaking the factorization forc > 0and shifting the resampling probabilities away from the assay estimate); the CI point estimate is computed by the estimator itself on the raw input, and q = 0 bootstrap replicates now carry the support distribution of the multinomial draws (entropy_cppq = 0 counts positive entries — zero-proportion bins no longer count as species). Locked bytest-bootstrap-invariant.R. -
Provenance rename: the primary paired GAMM metadata
fit_method/model_usedis nowlme_ns_car1(continuous CAR(1) correlation over ACTUAL q distances), reservingar1_grid_within_subject_conditionfor the grid-index fallback; previously the primary path was mislabelledlme_ns_ar1. -
Westfall–Young schemes:
block_col,strata_colandpermutation_schemewith exchangeability validation (confounded blocks/strata rejected). - Post-selection inference: LASSO/ElasticNet selection is exploratory-only and never modifies the confirmatory model (testthat lock).
- Robust M-estimation: sandwich variance with robust SE/p-values/95% CIs.
-
Performance (ART): the Aligned Rank Transform no longer recomputes ANOVAs for all effects per gene — only the q × condition interaction row is extracted via
ARTool::artlm()+flat.anova()(identical F and p-values, ~3× faster on the ANOVA step). Parallel per-gene workers now pin BLAS/OpenMP to a single thread to avoid core oversubscription (ART vignette step measured 42 s → 3.3 s at nthreads = 3). -
Documented limitations: unpaired ART slightly anti-conservative at small n (Conover-Iman
method='rt'recommended for confirmatory unpaired inference); GEE mildly anti-conservative under strong heteroscedasticity + outliers; read-level bootstrap/divergence CIs under-cover at low depth; GEE QICcorstr='auto'validated under H0 but pre-specification still recommended. -
Validation suite: 22 Monte Carlo tests in
tests/testthat/(type I, FWER/FDR, power, q-grid invariance, missing-q, filtering, effect sizes, bootstrap coverage, robustness), skipped on Bioconductor builds viaskip_on_bioc()and runnable locally viaRscript tests/testthat/run-validation.R. -
Divergence reimplementation: Tsallis divergence now compares per-condition isoform distributions (reads summed across samples within isoforms — the pooled condition-level composition) instead of sample-level aggregates; formula corrected to D_q(P||Q) = (sum P_i^q Q_i^(1-q) - 1)/(q - 1) without
abs()(KL only at q = 1, no ±0.01 band); q = 0 is evaluated on the RAW (pre-pseudocount) support — D_0 = 1 - sum_{i: P_i>0} Q_i — so the low-q end of the spectrum keeps its support-difference meaning under the default pseudocount instead of collapsing to 0 (review Option A); bootstrap CIs resample biological replicates (paired pairs as units; for paired designs the pairing is preserved when estimating uncertainty around the pooled estimate, not a subject-level divergence);method='bca'falls back to percentile with a warning and the effective method is recorded in metadata; defaultnorm = 'none'; mathematical property test battery added (identity, non-negativity, KL limit, asymmetry, permutation/count-scale invariance, support, q=0, construct validity) plus coarse-graining, biological-replicate replication invariance, bootstrap consistency, directed support, and biological construct-validity scenarios (abundance-only, isoform switch, rare vs dominant remodeling). -
S4 layer hardening:
paired/bootstrap/norm/stringencynow default toNULLsoconfigvalues are actually resolved (previously the literal defaults short-circuited the resolver);calculate_assumptions(q=)resolves q against available diversity keys with numeric tolerance (q_1.000/q_0.5/q_1_00conventions) and errors instead of silently analyzing another q;TSENATAnalysis[i, j]subsets divergence results by genes only (columns are q-values, not samples), subsets gene-level SAIT rows, and recordsmetadata$subset_applied/stale_resultsso inferential results computed on the full dataset are explicitly flagged;calculate_jis()restricts q to available diversity results (error if none); plot wrappers validate the object before touching@config; the constructor patchescolDatain place instead of rebuilding the SummarizedExperiment (preserves rowRanges/altExps); class validity no longer requiressample_id/gene_id/transcript_idcolumns (module-level contracts instead); effect-size docs corrected to config-based resolution; 5 end-to-end S4 integration tests added (configpaired/bootstrapreaching the core, exact q lookup, q=0 preservation, subset q-column invariance, staleness flag). -
Plotting layer hardening: the global divergence spectrum no longer presents averaged gene-wise CI bounds as a “Bootstrap 95% CI” — it computes a valid global bootstrap CI of the across-gene mean/median (shared resampling plan, quantiles of the aggregated statistic) and labels it explicitly;
metric="median"is now honored when CIs exist;plot_sait()plots the STORED diversity results (via.combine_diversity_results_for_sait()) instead of recomputing withnorm=TRUE; gene identity is never reconstructed by position (rep()) in q-curve plots (explicit error instead); IQR ribbons are labeled as descriptive spread (“Median ± IQR/2”) and the per-sample bootstrap CI ribbon is labeled as a descriptive aggregation, not a CI of the median;plot_diversity_violin_density()acceptsq=and errors instead of silently using the first stored q;plot_expression()gainedquantity="usage"(within-gene isoform fractions) vs"abundance"; heatmaps warn when requested genes cannot be plotted;plot_divergence_spectrum()returns the file path invisibly when saving (documented contract); SE dimension validation messages corrected (rows=genes, columns=samples). -
Performance: removed the O(G×T) transcript scans — transcript→gene indices (
split(seq_along(genes), genes)) are now built once and reused across diversity (.tsallis_row), divergence (.compute_group_isoform_counts/.process_single_gene_div), the global-divergence bootstrap, diversity bootstrap (.bootstrap_diversity_ci), gene aggregation (.aggregate_counts_to_genes), shrinkage and JIS summaries, and isoform filtering — each gene lookup is now O(1);.calculate_tsallis_entropy()computes only the requested quantity (what="S"no longer also evaluates Hill numbers and vice versa, ~2× on that path);.tsallis_row()extracts each gene block and applies pseudocount/effective-length once instead of per sample;.estimate_shrinkage_params()no longer does O(G²) rowname scans (vectorized row variances). Numerically identical outputs (locked by the existing test batteries: 2,313 expectations green in the affected suites). Benchmark (sequential): 2,000 genes × 20 samples × 5 isoforms × 5 q ≈ 2 s for diversity; 300 genes × 4 q divergence ≈ 1 s. -
Performance: new
tsallis_divergence_vector_cpp()computes the whole q-spectrum from one normalization pass (exact mirror of the R semantics: pseudocount normalization, q=0 limit on unclamped probabilities, min_prob clamp only for pseudocount=0, KL limit with log_base correction, log-space fallback, roundoff clamp);.tsallis_divergence_vector()now calls it (2.3× on the kernel). Newbootstrap_compute_multi_q_cpp()resamples ONCE per iteration and evaluates ALL q on the same resample (buffers preallocated outside the loop); the multi-q diversity bootstrap uses it as a fast path (percentile, unpaired, read-level), preserving the legacy per-q pipeline as an exact fallback for QC regeneration and degenerate cases (3.1× with 5 q; grows with the number of q). Point estimates bit-identical; bootstrap CIs now share one resampling plan across q, preserving the joint correlation structure. All affected suites green (2,917 expectations). -
Tables and data: robust p/effect-size formatting in the vignette tables (no
0.00e+00/NA%), top-10 concordance table, method-estimand table in README, and regeneratedinst/extdata/analysis_sait.rds.
-
Functional reframing of q: q is a deterministic functional argument of the Tsallis statistic, not a time index. ARIMA(1,1,0) differencing was removed from all confirmatory paths (GEE, GAM/GAMM, LMM, FPCA) — the interaction is now tested on the original H(q) curve (H0: beta(q) = 0 for all q); the legacy differencing helpers (
TSENAT 0.99.33
-
Statistical implementation audit (July 2026): Fixed 22 bugs from systematic review of
sait_*,diversity_*,divergence_*, andentropy_*modules.-
Critical fixes (4):
-
.hochberg_stepup()now uses correct Hochberg step-up (rev(cummin(rev(...)))) instead of Holm step-down (cummax). Matchesp.adjust(..., "hochberg")exactly. - GEE bias-correction thresholds unified from mixed
<20/<30to consistent<30. - Kauermann-Carroll HC1 multiplier now actually applied —
vcov(fit_alt)andcoef_valuepassed to.kc_bias_correct(). - Bootstrap CIs no longer invalidated by cross-gene normalization — remain on raw divergence scale.
-
-
High-impact fixes (7):
-
(method, regularization)validation preventsmatch.argerrors with incompatible combos. - AR(1) design-effect replaced asymptotic formula with correct finite-m form; dead duplicate removed.
- Westfall-Young permutation preserves paired structure (permutes within subjects).
- ARIMA differencing uses
group[-1]to preserve both condition levels. -
log_basethreaded through diversity computation chain (was silently nats). -
method="bca"warns and reports"percentile"instead of silently substituting. -
log_odds_ratiouses data-driven column-maximum normalization.
-
-
Other fixes (11): Removed ~280 lines dead stationarity code; standardized
min_obs; exposedcorstr="auto"; FPCA MANOVA returnsNAon failure; AR(1) ρ pooled within-cluster; q=0 divergence is support-difference; paired bootstrap warns on fallback; concordance handles empty results; plus 4 low-severity robustness fixes.
-
Critical fixes (4):
TSENAT 0.99.31
Aligned Rank Transform (ART):
calculate_rank_transform()now defaults to the Aligned Rank Transform via the ARTool package (Kay et al. 2021) for proper non-parametric interaction testing. ART strips main effects before ranking (“alignment”), preserving interaction structure — a known limitation of classical rank-transform methods. The Conover-Iman Rank Transform remains available viamethod='rt'. ARTool added to Imports.-
Bug fixes (July 2026 audit): Comprehensive fixes from systematic code audit:
Entropy & divergence core: Fixed
.entropy_core()q=0 species richness inflated by zero-count isoforms (B1); fixed.entropy_max()q=0 theoretical maximum off-by-one (B2); threadedlog_basethrough.normalize_log_odds_ratio()pipeline (B3); restrictedlog_baseto KL limit (q≈1) in Tsallis divergence (B10); eliminated pseudocount + min_prob double-correction (B11); corrected max divergence normalization for q≠1 using q-dependent formula (B12).C++ resampling kernels: Fixed
entropy_cpp()q=0 returninglog(n)instead ofn-1; removed>1e-15threshold so zeros contribute zero entropy; addedRNGseedfor reproducible parallel execution.Parallel reproducibility (R-layer): Fixed
.bplapply()not propagatingset.seed()to BiocParallel workers, causing non-deterministic results across parallel runs (Westfall-Young, bootstrap, etc.); now derivesRNGseedfrom current RNG state so all parallel operations are reproducible withset.seed().Bootstrap & CI infrastructure: Fixed BCa acceleration computed from bootstrap distribution instead of true jackknife (audit #3); fixed BCa z0 using wrong point estimate with effective_length mismatch (audit #4); added defensive copies in
bootstrap_compute_cpp_wrapper()andblock_bootstrap_compute_cpp_wrapper()(B6, I9); fixed BCa degenerate distribution handling and strict comparison with 0.5 padding (audit #12); implemented replicate-level bootstrap with proper C++ path (audit #11).Rank-based testing: Renamed all Scheirer-Ray-Hare labels to Conover-Iman Rank Transform (B4, I3); fixed η² computed on ranks instead of original entropy scale via separate
lm()(B7, I5).Shrinkage & edge cases: Eliminated silent zero-filling of NAs in
.apply_shrinkage()by initializingmeans_vectortoNA_real_(B5, I8).Vectorized divergence: Fixed
.tsallis_divergence_vector()q=0 returning scalar 0 instead of per-pair divergences (B13); fixed.divergence_normalize_log_odds_ratio()hardcoded maximum divergence ignoring q-dependence (B17).GAM interaction models: Identified GAM LRT statistically invalid due to REML + non-nested models + different k (audit #1); identified missing main-effect smooth s(q) in interaction model making comparison non-nested (audit #2); removed undeclared p-value bias correction multiplier (B14, audit #8); scoped
suppressWarnings()to only suppress rank-deficient warnings instead of all warnings globally (B15).Heteroscedasticity & weights: Fixed
.handle_arima_and_weights()silently dropping heteroscedasticity weights by directly assigning to correlation structure instead of callingupdate()(B16).Normalization bias: Fixed
.normalize_range_matrix()distorting CI bounds due to per-column normalization applied globally; changed to matrix-wide [0,1] normalization preserving rank order (B18).Convergence diagnostics: Fixed
.mest_irls_location()convergence check skipping first iteration (B8); removed allocated matrix immediately overwritten in.estimate_storey_pi0()(B9).FPCA gene-level testing: Deprecated
min(BH-adjusted PC p-values)as gene-level aggregate; replaced with sum-of-χ² pooling following Crainiceanu et al. (2009) guidance (audit #9).JIS bootstrap p-values: Fixed inverted JIS bootstrap p-values where
p_boot = 1 - mean(null ≥ obs)never rejected; corrected tomean(null ≥ obs)(audit #7).
Code quality: Split monolithic
plots_helpers.R(4,385 lines) into 5 thematic files; splits4_functions.R(2,561 lines, 11 exports) into 11 per-function files; split bootstrap test file (7,752 lines) into 6 focused test files.Testing: Added 85 golden reference tests for entropy/divergence formulas; added 39 ART-specific tests; test suite now exceeds 4,800 test blocks.
Documentation: Updated all vignettes and man pages to reflect ART as default method; corrected Hochberg vs. Benjamini-Hochberg labeling; fixed heteroscedasticity interpretation in main vignette; added ART citations (S271–S273) to TSENAT.bib.
TSENAT 0.99.0
Initial Bioconductor release. TSENAT provides scale-dependent analysis of transcript isoform diversity using Tsallis entropy, enabling detection of splicing-driven regulatory changes orthogonal to count-based differential expression methods.
Core analysis via
calculate_diversity(),calculate_divergence(),calculate_rank_transform()for Q×Condition interaction testing,calculate_sait()for scale-adaptive interaction testing (GAM, LMM, GEE, FPCA) with AR(1) support for repeated measures, andcalculate_concordance()for method comparison. Supports Conover-Iman Rank Transform tests, permutation tests, and jackknife bootstrap.Parameter
qtunes Tsallis entropy sensitivity: q < 1 emphasizes rare isoforms, q ≈ 1 recovers Shannon entropy, q > 1 emphasizes dominant isoforms.Unified S4 class
TSENATAnalysisintegrating SummarizedExperiment, configuration, results, and cached plots with full subsetting and accessor support.Data input:
build_analysis()for RNA-seq count matrices or Salmon quantification (via internal utilities); supports GFF3 annotation files for transcript-to-gene mapping viatx2geneparameter.Quality control:
filter_analysis()for multi-criteria filtering;jackknife_entropy_outliers_s4()for outlier detection.Visualization suite (8 plot types): diversity q-curves, volcano/MA plots, violin/density plots, transcript composition heatmaps, divergence distance matrices, interaction surfaces, concordance plots, multi-gene q-spectrum plots. All ggplot2-based with publication-ready styling.
High-level workflow orchestration via
TSENAT()and flexible configuration management withTSENAT_config().Performance: Rcpp/RcppArmadillo for entropy calculations, BiocParallel support, lazy-loading of visualization libraries (~30% faster non-plot workflows).
Comprehensive documentation: main vignette + 2 appendices (SplicingFactory validation, advanced workflows), 25 exported functions with complete roxygen2 documentation.