Re-analysing pancancer dataset with dispersion priors
Published
April 27, 2026
Load dependencies
Load metadata
Show code
# WARNING! THIS INCLUDES UNPIBLISHED DATAmeta_path <-"./data/ash_pancancer/metadata_full.tsv"meta <-read.csv(meta_path, sep ='\t') meta =cbind(run_acc = meta$run_accession, meta)# From paper:# RvsP = CR or PR VS. PD or cPD - excluded patients with a BOR of stable disease (SD) (n=29)# Outcomemeta$RvsP ="R"meta$RvsP[which(meta$BOR =="PD"| meta$BOR =="cPD")] ="NR"meta$RvsP =factor(meta$RvsP, levels =c("NR", "R"))
Load sylph outputs
Show code
sy <-read_sylph("./data/ash_pancancer/combined_q_99.tsv.gz") # q99)
Detected Sylph query output file.
Show code
# annoying renames to match meta V sylph filecolnames(sy) <-gsub("_1", "", colnames(sy))colData(sy)$Sample_file <-gsub("_1", "", basename(colData(sy)$Sample_file))# Reorder meta meta = meta[match(colnames(sy), meta$run_accession), ]# get rid of SDrmidx =which(meta$BOR =="SD")if(length(rmidx) >0){ meta = meta[-rmidx, ] sy = sy[, -rmidx]}sy <-filter_by_presence(sy, min_nonzero =8) # filter at 10%
Retained 19139 rows after filtering
Show code
dim(sy)
[1] 19139 77
Show code
# Checks before merging metadataall(colnames(sy) %in% meta$run_accession)
[1] TRUE
Show code
all(meta$run_accession %in%colnames(sy))
[1] TRUE
Show code
sy =modify_metadata(sy, meta)
Empirical Bayes priors without dispersion term
Show code
design <-as.formula("~ RvsP + histology_cohort.x + age + sex + BMI") save_path <-"output_rds/ASH_prior_analysis_zib_q_99_ebp.rds"if(file.exists(save_path)){ ZB_fit <-readRDS(save_path)} else { ebp =compute_eb_priors(sy, design, nthreads = parallel::detectCores(), low_cutoff =0,high_cutoff =Inf)# Run with weak prior for prediction ZB_fit <-glmZiBFit(sy, design, nthreads = parallel::detectCores(), MAP_prior = ebp)saveRDS(ZB_fit, save_path)}
There are 167 top hits, some of them dodgy
Show code
th =top_hits(ZB_fit)
Found 167 tophits for RvsPR at alpha = 0.05 using holm
Show code
# Looking at the first 10plot_ani_dist(sy, 'RvsP', th$Contig_name[1:10])
Warning: Removed 689 rows containing non-finite outside the scale range
(`stat_boxplot()`).
Clearly, at least B. animalis and F. nucleatum should NOT be picked…
Post-hoc testing
Show code
th_ph = strainspy::comp_ani_diff_and_posthoc_test(sy, ZB_fit, th, progress =FALSE)table(th_ph$Comment, useNA ='always') # now there are only 16 hits
<3 nonzero <3 nonzero; too few nonzero
17 83
too few nonzero <NA>
26 41
Warning: Removed 1367 rows containing non-finite outside the scale range
(`stat_boxplot()`).
Not enough to kill B. animalis though…
Post-hoc testing
Show code
th_debp_ph = strainspy::comp_ani_diff_and_posthoc_test(sy, ZB_fit, th_debp, progress =FALSE)table(th_debp_ph$Comment, useNA ='always') # now there are only 15 hits, one less from before
<3 nonzero <3 nonzero; too few nonzero
10 48
too few nonzero <NA>
12 27