All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
sctrial.benchmarksubpackage: hierarchical gamma-Poisson simulator (SimulationConfig,simulate_trial,calibrate_from_real_data) and benchmark orchestrator (run_benchmark) for controlled method comparisonsrun_gsea_cross_sectional()andrun_gsea_within_arm()now exported fromsctrial.statssensitivity_analysis()now exported fromsctrial.stats- Concepts and Methods documentation page with statistical background and references
- Changelog page in documentation
- API reference split into navigable sections (Design, Statistics, Scoring, Plotting, Datasets, Workflow, Utilities, Benchmark)
stats/__init__.py: missing exports forrun_gsea_cross_sectional,run_gsea_within_arm, andsensitivity_analysis- Documentation URLs standardized to Read the Docs
- CITATION.cff updated to v0.3.0 with full author list matching the preprint
- README updated with preprint citation, PyPI badge, and corrected API links
- Module-level docstrings added to 8 core modules
- Tutorial notebooks revised for clarity and consistent use of sctrial API
power_paired(): Power for paired pre/post designs (vaccine, CAR-T, etc.)sample_size_paired(): Required sample size for paired designssensitivity_paired(): Minimum detectable effect size for paired designs
TrialDesign.arm_colnow acceptsNonefor single-arm studiesrequired_cols(),validate(),subset_cells()handlearm_col=Nonearm_bin()raises clearValueErrorfor single-arm designs
simulate_did_data(): Generate synthetic DiD datasets with known ground truthrun_method_comparison(): Compare sctrial DiD vs pseudobulk OLS vs Wilcoxon
n_bootdefault: 1000 → 999 inbootstrap_effect_size_ci()- Zero-SE paired delta returns
NaNinstead oft=0, p=1 - Non-finite SE coerced to
NaNinstead of0.0 validate()no longer crashes whenarm_col=Nonecheck_covariate_balance()raises clear error for single-arm designs- mypy: fixed
catch_warningstype incomparisons.py
prior_predictive_check(): Run prior predictive checks to calibrate Bayesian priors before fitting.did_table_bayes()now acceptsprior_scaleandsigma_scaleparameters for prior sensitivity analysis.
cohens_d(): Calculate Cohen's d effect size between two groupshedges_g(): Bias-corrected effect size (recommended for n < 20)add_effect_sizes_to_did(): Add standardized effect sizes to DiD resultsbootstrap_effect_size_ci(): Bootstrap confidence intervals for effect sizeseffect_size_ci(): Analytical confidence intervals using noncentral t
power_did(): Calculate power for DiD analysis given sample sizesample_size_did(): Determine required sample size for desired powerpower_curve(): Generate power curves across sample sizesdesign_effect(): Calculate design effect for clustered dataeffective_sample_size(): Compute effective n accounting for ICC
did_table_mixed(): DiD with random participant effectscompare_fixed_vs_mixed(): Compare both approaches for sensitivity analysis- Returns ICC (intraclass correlation) and variance components
trend_interaction(): Treatment × time trend for 3+ timepointsevent_study_did(): Generalized DiD comparing each visit to baselinepolynomial_trend(): Fit polynomial trajectories by armtest_parallel_trends(): Validate parallel trends assumption
loo_cv_did(): Leave-one-out CV for influence diagnosticskfold_cv_did(): K-fold CV for effect stability assessmentinfluence_diagnostics(): Identify influential participantscv_summary(): Summary statistics from CV results
add_effect_sizes_to_did()now uses residual SD directly from the OLS/WLS fit when available, instead of back-calculating from standard errors with a balanced-design assumption.module_score_did_by_pool()now acceptsfdr_globalparameter; emits a global FDR column (FDR_DiD_global) and a warning when per-group FDR is used.kfold_cv_did()now stratifies fold assignment by treatment arm for balanced folds.did_table_mixed()convergence handling improved: trustsfit.convergedas primary indicator withlbfgsfallback optimizer.design_effect()andeffective_sample_size()now validate inputs (ICC, cluster_size).- Missing feature error messages in
did_fit()now show total count when more than 5 are missing. add_log1p_cpm_layer()now supportsoverwrite=Trueto replace an existing layer andinplace=Trueto modify the AnnData in place without copying._to_bool_series()now emits aWARNING-level log when non-finite values are encountered in a boolean column, aiding data quality diagnostics.profile_features()docstring now documents that aggregation is cell-weighted; for balanced participant-level comparisons, pre-aggregate to pseudobulk first.- Replaced
print()withloggingthroughoutconvenience,datasets, andvalidationmodules. - Enhanced
did_fit()docstring with full mathematical model specification - Added explicit null hypothesis statements to all statistical functions
- Expanded FAQ with bootstrap vs standard errors guidance
- Expanded FAQ with minimum sample size recommendations
- Expanded FAQ with missing data handling guidance
- Reorganized API documentation by statistical method category
- Statistical: Fixed WLS weighting in
did_fit()— now usesn_cells(correct inverse-variance weights) instead ofsqrt(n_cells)for pre-aggregated participant-level means. - Statistical: Fixed
pseudobulk_expression()to drop groups with zero total counts before CPM normalization instead of adding a1e-12epsilon. - Preprocessing:
add_log1p_cpm_layer()now validates input: raisesValueErroron negative counts, warns on NaN/inf values, and warns when all cells in the counts layer are zero. - Preprocessing:
add_log1p_cpm_layer()now records provenance metadata inadata.uns["log1p_cpm_info"](source layer, target layer, timestamp). - adata_tools: Fixed
_to_bool_series()truncating fractional crossover values (e.g.0.5was cast toint→0→False). Now any non-zero finite value is truthy. - adata_tools: Fixed
_to_bool_series()crashing withIntCastingNaNErroronnp.infcrossover values. Non-finite values (NaN, inf) are now treated asFalsewith a logged warning. - analysis: Fixed
DiDAnalyzer.fit()returning a mutable alias to internalresults_DataFrame. Now returns a copy so external mutations cannot corrupt internal state. - Fixed duplicate
_params_match()definition indatasets.pythat silently overwrote the robust version; also fixed numpy array comparison bug. - Fixed README.md example with incorrect
arm_colparameter value. - Fixed
auto_detect_designdocstring example showing incorrect mutation of frozen dataclass. - Fixed
test_plot_gsea_heatmaptest to skip when matplotlib is not installed.
- Added
__all__exports to all modules for better API clarity:design,preprocessing,scoring,adata_tools,utils,plotting. - Added
validationandconveniencemodules to API documentation.
- Core trial-aware inference engine: Difference-in-Differences (DiD) with participant fixed effects and covariate support.
- Robust statistical methods: Wild Cluster Bootstrap (Rademacher) and Permutation tests.
- Cell-type abundance DiD for compositional analysis.
- GSEA integration with trial-aware rankings (signed confidence, beta, or t-statistic).
- Stratified DiD analysis across cell-type hierarchies (
did_table_by_celltype). - Advanced visualizations: Trial interaction plots, forest plots, spaghetti plots, radar plots, and trial-stratified UMAP panels.
- Automated summary reporting for DiD results.
- Comprehensive Sphinx documentation with API reference and detailed tutorials.
- Professional infrastructure: MIT License, pre-commit hooks, and GitHub Actions CI.
- Full support for sparse
AnnDataobjects.