pdactrace_reference
(audit_score_layer, _direction, _early, _serum, _rescue, the
gate multipliers and flags) were frozen at v0.3.0, before the 12-template
catalog. 286 genes whose best RNA template became Monotonic (284) or Late
(2) therefore kept Early-onset and RNA-layer credit, and genes whose
protein label changed kept their old layer and direction credit. The
columns are now recomputed from the atlas's current labels with the same
code that scores a user evidence table, so atlas and user scores follow
one rule. data-raw/attach_audit_columns.R, which previously copied the
v0.3.0 CSV, now does this recomputation.supported_uncertain -> low, 9 high_confidence -> low, NCAPG and
IQGAP3 high_confidence -> supported_uncertain). Class counts are now
high_confidence 370, supported_uncertain 7941, low 1749,
penalized 22, excluded 31. The top gene, the four case-study genes,
SERPINA1 and the anchor enrichment (7 hits in the top 100, 39.3x;
leave-one-out median 41.6x; bootstrap 95% CI 20.2-56.3) are unchanged,
and the top 100 differs by one gene. Monte Carlo columns were
regenerated (stable_high 153, high_uncertain 620, medium 502,
low 8807).methodology_validation vignette
reported the same top-100 anchor enrichment (7 hits, 39.3x) for every
weight profile, including single-axis extremes, and concluded that the
ranking is "fundamentally insensitive" to the weights. The sweep was a
no-op: it wrote a reweighted audit_score into the atlas and passed it to
evaluate_anchor_enrichment(), which recomputes audit_score with the
frozen weights. Ranked directly, the profiles give 7, 6, 1, 5 and 6 hits
(biological-coherence-only: 5.6x, not significant). The section now
ranks the reweighted score itself and states that the enrichment depends
on the weights; across the simplex the top-100 hit count ranges from 1 to
8.?pdactrace_reference and the README now document that the scRNA
cell-origin layer exists only for the 300 genes of an earlier candidate
ranking (Phase 2D; tissue stage effects plus serum detection by the
author's account, no literature or known-marker list; its script was not
retained). 11 of the 18 secondary anchors are among them. Within those
genes the top-100 enrichment is 1.9x (p = 0.04); with the scRNA layer
removed from the score it is 16.9x (3 hits).classify_claim_tier() now uses strict TRACE-D only. A gene is
serum_concordant only when its measured serum log2FC reaches
tau_serum in the tissue direction, and translation_status follows the
same strict class. Previously the legacy translation_class label could
override a strict class C, although that label records only the sign of
the phase77 serum change, not its size or significance. The legacy label
is still returned, as legacy_translation_class, and does not raise the
tier. Strict class C is no longer counted as a serum signal.serum_concordant 8 -> 6 (LGALS3BP, log2FC
0.035, adjusted p 0.81, and FN1, 0.006, move to exportable_plausible);
serum_observed 13 -> 9 (ECM1, FBLN1, GGH, LCN2 move to
exportable_plausible). LTBP1, SPARC and TAGLN2 stay serum_observed,
but their translation_status is serum_observed_no_tissue_direction
rather than direction_inverted: their serum change opposes tissue, but
their tissue meta-effect is below tau_tissue. Audit scores, audit
classes and the anchor enrichment are unchanged.serum_log2fc_PDAC_vs_HC in pdactrace_reference now holds the pooled
phase77 log2FC for the 19 serum-detected genes that had no phase42 value,
so strict TRACE-D sees all 38 serum-detected genes (19 before). No other
column changed. The rule is in data-raw/build_reference.R;
data-raw/attach_phase77_serum_log2fc.R applied it to the shipped atlas.compute_trace_d() treated a missing pancreatitis log2FC as 0 and could
call such a gene pdac_specific; it is now ambiguous. A serum-detected
gene with no measured log2FC is recorded as serum_unmeasured in
tracd_decision_path instead of serum_subthr.?pdactrace_reference documents that rna_padj_E/M/L are copies of the
omnibus LRT padj (stage-specific values are rna_wald_padj_*), where each
serum log2FC comes from, what translation_class does and does not
encode, and that the plasma high-abundance gate is a curated list:
SERPINA1 is not on it (adding it would give 0.32, penalized, and 6
rather than 7 anchor hits in the top 100); the list is kept as frozen.propagate_uncertainty() perturbed the pre-v0.3.0 seven-feature score
(weights 0.20/0.20/0.20/0.10/0.10) instead of the 3-axis score that
compute_audit_score() returns, so its intervals, rank intervals and
confidence_class described a different score. SERPINA1 scored 0.6406
but had a Monte Carlo median of 0.520 (the old formula gives 0.519). The
loop now uses the 3-axis formula (SERPINA1 median 0.641). Only template
rho, cohort agreement and I2 are perturbed, as before.pdactrace_reference
(audit_score_median, _lo95, _hi95, audit_uncertainty_width,
audit_rank_*, audit_confidence_class) were regenerated with the fixed
loop (500 draws, seed 42); every other column is byte-identical.
data-raw/monte_carlo_uncertainty.R, which no longer ran on the current
atlas, now calls the package's own loop, and its stale figures were
removed. confidence_class counts: stable_high 241 -> 153,
high_uncertain 820 -> 622, medium 684 -> 509, low 8337 -> 8798.sb_lock_manifest() failed on Windows ("Every locked file must be inside
root") because normalizePath() returned backslashes while the prefix
check used /. Paths are now normalised with winslash = "/".compute_audit_score(), explain_score() and the README now state that
the gated score is divided by the largest gated score in the scored table,
so audit_score is relative to the top gene (LGALS3BP in the bundled
atlas), and that there are five audit classes, including low.classify_trajectory() and classify_protein_trajectory() no longer say
the 0.85 default matches the bundled atlas: the atlas was built with 0.75.
The README no longer claims 0.85 is hard to reach with four points; for a
gene with no stage effect the best of 12 templates exceeds it about 58% of
the time.audit/PROVENANCE.md and vignette 7 described both PDAC
one-shot audits as stopped by assay coverage. Only MSV000101183 v1_1
stopped at technical QC; MSV000101183 v2 and PXD067770 stopped because
the deposited outcome labels did not match the frozen dictionary or group
counts. The tables now list each lock with its recorded reason.PDAC refocus: prespecification and audit layer merged in. The PDAC
subset of the wider cross-cancer working tree is now part of the
package; the non-PDAC analyses stay in the v0.1.0-pancancer-archive
tag and are out of scope here.
stagebridge(),
sb_one_shot(), sb_default_one_shot_rule(), sb_pareto_fronts(),
sb_loco_stability(), sb_observability(), sb_validate_effects(),
sb_simulate(), sb_method_scores(),
sb_multiblock_plsda_scores(), sb_binary_auc(),
sb_average_precision() and sb_topk_recall().sb_one_shot() returns a terminal PASS / FAIL / INCONCLUSIVE
decision, where INCONCLUSIVE records that a frozen gate halted the
run before the endpoint was computed and is therefore distinct from a
biological FAIL.audit/PROVENANCE.md records the archive tag, the transfer hashes and
the two PDAC one-shot audits, both of which terminated
INCONCLUSIVE at the prespecified coverage gate.prespecification_audit, covers the whole
prespecification layer: stagebridge() ranking, exact Pareto fronts,
leave-one-cohort-out stability, the shipped comparators scored with
sb_binary_auc() / sb_average_precision() / sb_topk_recall(), and
sb_one_shot() driven to PASS, FAIL and INCONCLUSIVE. It reports
that StageBridge has the lowest AUROC of the eight methods on the
simulated translation scenario while ranking second on AUPRC and
top-20 recall, rather than selecting a scenario that flatters it.\VignetteIndexEntry, and stale author: version strings are
replaced with the maintainer name.sb_default_one_shot_rule() now records that its thresholds come from
a lock held in the archived working tree, not from a path inside this
package.DESCRIPTION and README.md state the PDAC-specific scope and the
prospectively frozen score layer.withr::local_seed() rather
than set.seed(), matching the existing BiocCheck-compliant pattern.stats::reshape() is called with its namespace qualified.report_gene() failed for every gene with "'pdactrace_reference' is
not an exported object". Its report templates read the atlas as
pdactrace::pdactrace_reference, which stopped resolving when 0.99.20
set LazyData: false; the \donttest{} example hid it from
R CMD check. The templates now load the atlas with data().citation("pdactrace") and the README cited Zenodo DOI
10.5281/zenodo.20076698, which is the v0.99.0 record under an older
title. Both now use the concept DOI 10.5281/zenodo.20068234, which
resolves to the latest archived version, and the current title.\donttest{} examples of fit_stage_de(), fit_stage_de_protein(),
classify_trajectory() and classify_protein_trajectory() referenced
undefined placeholder objects (my_counts, my_intensity) and failed
under --run-donttest. They now run on the bundled toy data.download_phase_csvs() could not work for anyone: it fetched from a
private repository, at a path that repository does not contain, while
its documentation called the source public. The two upstream fits
(phase33 RNA, phase34 protein; gene-level summary statistics) now live
in data-raw/ of this repository, the helper fetches them from there,
and data-raw/build_reference.R and build_protein_betas.R read them
in place. A clean checkout with no other repository reproduces the 64
base columns of pdactrace_reference exactly.test-sb-core.R and test-sb-one-shot.R. The one-shot suite is
a positive control: it drives the frozen runner to all three terminal
states on synthetic input and checks that AUROC rises monotonically
with planted signal, so a PASS is reachable in principle and the
real-data INCONCLUSIVE results reflect coverage, not an
over-conservative gate.Bioconductor pre-submission polish. This release keeps the claim-audit API unchanged and addresses BiocCheck new-package feedback before opening the Bioconductor Contributions issue.
\donttest{} examples, clearing the BiocCheck
runnable-example ERROR.\dontrun{} examples with \donttest{}.LazyData: false and added missing vignette chunk labels plus
sessionInfo() chunks where BiocCheck requested them.R CMD check --no-manual and BiocCheck(new-package=TRUE) were run
on the source tarball as the final submission gate.BiB-facing claim-audit release. This release reframes pdactrace from a scalar biomarker prioritisation package into a deterministic stage-aware PDAC atlas and tissue-to-blood biomarker claim-audit framework.
classify_claim_tier() and summarize_translation_gap() separate
tissue dysregulation from stronger blood-biomarker claims.compute_trace_d() implements TRACE-D in strict mode, with an
explicit legacy_translation = "fallback" compatibility mode for
historical translation_class annotations.run_weight_robustness(), compute_pareto_class(),
compute_pareto_layers(), and evaluate_pareto_stability() audit
whether candidates depend on one arbitrary 3-axis weight vector.R CMD check --no-manual passes with rebuilt vignettes.viz_gene() default flips to multi-page (layout = "split").
The v0.99.16 split mode was opt-in, so the bare viz_gene("X")
call still rendered the cramped single-page 2x3 patchwork. This
release flips the default so the natural call gives the six
panels at full size, one per plot-pane page.
viz_gene(layout) default flipped from "compact" to
"split". Calling viz_gene("LTBP1") now returns a
pdactrace_viz_panels named list of six full-size ggplots
(rna, protein, cell, serum, filter, hexagon).print.pdactrace_viz_panels renders each
of the six panels sequentially to the active graphics device.
In RStudio the six panels become six entries in the Plots
pane history (navigate with back/forward arrows). In a batch
script with pdf() open they become six pages of the PDF.viz_gene("X", layout = "compact") for embedding contexts
and back-compatibility.viz_gene("X") test now expects
pdactrace_viz_panels instead of patchwork.layout = "compact" patchwork tests retained, gated on
skip_if_not_installed("patchwork").print.pdactrace_viz_panels round-trip.This is a behaviour change but not an API removal: every
existing viz_gene(..., layout = "compact") call still works,
and the named-list shape for layout = "split" is unchanged.
README compression for Bioconductor reviewer scan-readability.
The pre-submission README had grown to 1,749 lines as scenarios
and a per-function reference accreted; this rewrite compresses
it to 532 lines (-70%) without removing any reviewer-defending
content. Function-level argument tables are intentionally pushed
to ?function_name Rd pages (the canonical R discovery surface)
and scenario-level worked examples to the existing vignettes.
README.md rewritten:
vignette("...") pointers for the long form.?function_name (the canonical R help surface).No code, vignette, test, or NAMESPACE changes; documentation-only release.
viz_gene() gains layout = "split" for full-size per-panel
output. The 6-panel composite layout is great for a one-glance
overview, but the per-panel cells get cramped at default print
sizes. The new split mode returns each panel as its own
full-size figure -- either as a named list of ggplots (for
custom layout in a script) or as one cairo-PDF per panel
(when output_dir is set).
viz_gene(layout = c("compact", "split")) -- backwards-
compatible. "compact" (default) keeps the 2x3 patchwork
composite; "split" returns a named list of 6 ggplots
(rna, protein, cell, serum, filter, hexagon).viz_gene(..., layout = "split", output_dir = ...) -- writes
each of the 6 panels to a separate cairo-PDF file via
[pdactrace_save()] (default width = 6, height = 4.5
inches, single-column NCS-grade). Files are named
viz_gene_<gene>_<panel>.pdf. Returns the named list
invisibly with attr(., "files") carrying the file paths.No public API removals; layout, output_dir, width, height
are additive optional arguments.
Final pre-Bioconductor-submission audit fixes. Addresses two items found in the v0.99.14 R CMD check NOTEs and tightens BIOCONDUCTOR.md to proactively address the maintainer-team review questions most likely to come up.
.Rbuildignore now excludes the .claude hidden directory
(caught by R CMD check checking for hidden files and directories ... NOTE). The directory holds editor scratch
state and is not part of the package.R/pdactrace-package.R utils::globalVariables() now declares
serum_log2fc_Pan_vs_HC (caught by R CMD check checking R code for possible problems ... NOTE for the
.ft_serum_strip() helper).viz_gene, query_gene,
explain_gene, compare_candidates) and frames the broader
71-export API as layered, not unstructured.knitr::knit());.claude hidden-dir
NOTE eliminated; serum_log2fc_Pan_vs_HC global-binding NOTE
eliminated; remaining 3 are CRAN incoming feasibility,
pandoc-not-installed, pre-existing R CMD check static-analysis
noise).DESCRIPTION bumped 0.99.14 -> 0.99.15. End of pre-submission hardening.
Pre-Bioconductor-submission audit fix.
inst/CITATION was stale (carried the old "Queryable Stage-Aware
PDAC Tissue-to-Serum Biomarker Reference Atlas" title and a
hard-coded "0.99.0" version note). Updated to the current
DESCRIPTION title ("Transparent Multi-Omics Tissue-to-Serum
Biomarker Translation Framework with PDAC Reference Atlas") and
to read utils::packageVersion("pdactrace") so the citation note
follows future version bumps automatically.
This release also marks the end of pre-submission hardening. v0.99.0 -> v0.99.14 covers: Bioconductor pre-submission blockers (v0.99.0), Bioconductor compliance pass (v0.99.3), reproducibility vignette + on-demand fetcher (v0.99.4), Evidence Math layer (v0.99.5), interpretable ML layer (v0.99.6), pandoc-friendly report_gene (v0.99.6.1), viz_gene canvas + BiB framing (v0.99.7), viz_gene rebalanced (v0.99.7.1), viz_gene 6-panel + plot_serum_direction (v0.99.8), serum projection helper (v0.99.9), methodology validation pass (v0.99.10), anchor-language softening (v0.99.11), held-out PDAC stress test + 3-way baseline (v0.99.12), BIOCONDUCTOR.md submission summary (v0.99.13), CITATION fix (this release).
Reviewer-facing documentation pass + Bioconductor submission summary added. Final hardening before Bioconductor submission issue. No API change; documentation-only.
BIOCONDUCTOR.md (NEW) -- single-page submission summary
prepared as a copy-paste-ready body for the Bioconductor
review issue. Documents package purpose, what the package is
and is not, user-facing API groups (Core query / Visualization /
Evidence math / User cohort / Translation discipline /
Optional / Reports + I/O), evaluation discipline including
the 3-way anchor enrichment table, an explicit limitations
section, and the conservative submission tone for the issue
body itself ("prepared for Bioconductor review and passes
local checks; standard reviewer iteration expected").README.md -- new top-level section "Projection stress test
and evidence-layer dependence" inserted into the Audit
scoring rule chapter. Surfaces the 3-way anchor enrichment
table (Bundled FULL multi-layer 39.3x at top-100; Bundled
RNA-only 16.9x; Held-out RNA-only 0) and the negative-control
housekeeping bottom-500 enrichment after atlas-defined
leakage annotations are applied (17.8x, p = 1.1e-33). Frames
the held-out RNA-only result as a "projection stress test",
not as definitive external multi-omics validation.These wording rules are in feedback_submission_framing.md.
Held-out PDAC validation + 3-way enrichment baseline added to methodology_validation vignette. Phase 2 of the locked roadmap. Documentation-only release; no API change.
vignettes/methodology_validation.Rmd Section D (NEW) -- held-out
PDAC cohort projection. Constructed by combining GSE253260
(397 PDAC primary tumour bulk RNA-seq, never used in atlas
construction; stage labels harmonised from GEO diseasestage:ch1)
with GTEx (360 normal pancreas) for the Normal stage. Cohort
confound (Normal samples entirely from GTEx, Tumour entirely
from GSE253260) is honestly disclosed; cohort_col was dropped
from the DESeq2 design as a result. ENSEMBL -> SYMBOL mapping
done at the SYMBOL level after per-cohort mapping (not at the
ENSG-intersect level which collapsed to 1166 genes); the fixed
pipeline gives anchor coverage 18 / 28 (vs. the broken
pipeline's 1 / 28).vignettes/methodology_validation.Rmd Section E (NEW) -- 3-way
baseline comparison of anchor enrichment by ranking source:
During the v0.99.12 work I initially proceeded with a broken ENSEMBL -> SYMBOL pipeline that gave 1166 / 17252 atlas overlap and 1 / 28 anchor coverage. The fix was to map per-cohort to SYMBOL first, then intersect at the SYMBOL level, then restrict to the atlas universe. The bug + fix is documented in this NEWS entry as a transparency item.
Submission framing hardening: anchor enrichment language softened to 'sanity check', and complementary negative-control depletion analysis added. Two coordinated changes for the BiB / Bioconductor reviewer audience.
R/model_card.R -- the validation_summary field renamed to
sanity_check_summary and reworded: "T1_validated anchors
land in the top decile by anchor_similarity in the bundled
atlas (post-freeze sanity check, not fully-blinded external
validation)". model_card() printer auto-picks up the new
field name.README.md -- every reference to the 39.3x anchor enrichment
now framed as a "post-freeze evaluation-only sanity check"
rather than "validation". Explicitly notes that anchor
curators and framework designers share domain expert input,
so the result is best interpreted as a sanity check pending
v1.0's held-out PDAC cohort run.vignettes/methodology_validation.Rmd -- intro reworded
from "two reviewer-facing methodology validations" to "two
reviewer-facing methodology sanity checks (post-freeze
evaluation, not fully-blinded external validation)".
Limitations section retitled and softened.vignettes/methodology_validation.Rmd Section C --
Negative control depletion analysis. The complement of the
Section B anchor enrichment: housekeeping (n=31) and
plasma_high_abundance (n=22) genes -- both intentionally
zeroed/halved by the leakage gate -- should be DEPLETED at
the top of the audit-score ranking and ENRICHED at the
bottom. Quantitative result: all 31 housekeeping genes land
in the bottom-500 (fold = 20.2, p = 1.3e-41); top-1000
housekeeping depletion p = 0.04. Paired with Section B's
anchor enrichment, this demonstrates the framework
discriminates in both directions: known signal goes up,
known noise goes down -- a circular score would not produce
both effects.These are submission-framing changes (not API changes). The
actual numeric outputs of audit_score, anchor_enrichment(),
and model_card() are unchanged; only the user-facing language
and the additional negative-control documentation are updated.
Methodology validation pass for the BiB / Bioconductor reviewer audience. No new public API; this release closes five documentation-and-validation gaps that the v0.99.9 self-audit flagged as the most likely BiB reviewer pushback points.
README.md "Audit scoring rule" section -- new "Why these
specific cutoffs?" subsection that documents the rationale
for every numeric in the framework: rho_cutoff = 0.85
(conservative four-point trajectory threshold),
3-axis weights 0.40 / 0.35 / 0.25 (priority order:
layer presence > biological coherence > translational
relevance), 2-gate multipliers (housekeeping 0.00 /
plasma-high 0.50; Higgins-Thompson I-squared boundaries
70 / 90 mapped to multipliers 1.00 / 0.70 / 0.30),
audit class boundaries 0.5 / 0.3, effect-size threshold
0.585 = log2(1.5), and a one-paragraph disclosure of
the Stouffer cohort-independence assumption (TCGA-PAAD
and CPTAC PDAC partial donor overlap, addressed via the
heterogeneity gate).vignette("cross_cancer_demonstration") (NEW) -- end-to-end
demonstration that the framework's R API is cancer-agnostic.
Uses a synthetic CRC-flavoured cohort (50 genes x 24 samples)
to walk project_user_cohort() through the same pipeline used
in Scenario 6a of the README. Includes a "what changes between
PDAC and non-PDAC" table making explicit which components are
PDAC-specific (bundled atlas, anchor evaluation set) and
which are framework-portable (12-template catalog, 3-axis +
2-gate audit, Evidence Math layer, Class A / B / C
translation discipline).vignette("methodology_validation") (NEW) -- two reviewer-
facing methodology validations on the bundled atlas:
rho_cutoff in {0.80, 0.85, 0.90} and re-evaluates top-100
anchor enrichment; perturbs the 3-axis weights across 5
profiles and shows the framework is not brittle to the
exact weight choice.audit_score ranking against simpler alternatives
(raw |beta|, -log10(padj), layer count,
signal-peptide-only) on the same anchor harness; the
multi-axis integration + leakage / heterogeneity gating
produces a specificity advantage no single feature
reaches.Imports: /
Suggests: change.These additions close the five highest-priority methodology gaps identified in the v0.99.9 final audit: P1.1 cohort independence disclosure; P1.2 cutoff justifications in the README; P1.3 cross-cancer transferability demonstration; P2.1 cutoff sensitivity analysis; P2.2 tool comparison.
Asymmetric user-data projection: serum needs only PDAC vs HC. The tissue side (RNA + tissue protein) requires stage-aware input (N/E/M/L 4-level) for the 12-template trajectory framework, but the serum side uses binary group contrasts -- which is exactly what most public PDAC serum DIA / TMT studies publish. Until now pdactrace had no user-facing helper for the serum side; this release adds one and explicitly closes the documentation / friendly-error gaps that left users with N vs T input confused.
project_user_serum_cohort(intensity, coldata, group_col, pdac_label, hc_label, pan_label, test, padj_cutoff, link_to_atlas) -- projects a user's serum proteomics matrix
through the binary-contrast pipeline. Computes
serum_log2fc_PDAC_vs_HC and (optionally)
serum_log2fc_Pan_vs_HC, runs a per-gene two-group test
(limma_eBayes / wilcox / t_test), BH-adjusts, joins the bundled
atlas RNA direction to assign translation_class (A / B / C),
and flags serum_detected. Output plugs straight into
assemble_user_evidence(serum_summary = ...). No stage labels
required; minimum 3 samples per group recommended.fit_stage_de() -- new pre-validation step that surfaces a
friendly error when the user provides binary c("Normal", "Tumor") instead of c("Normal", "Early", "Mid", "Late").
Previously the silent factor() coercion dropped Tumor samples
and the user got the misleading "Need at least 8 samples"
error downstream. The new error names which labels matched /
unmatched and points the user at three options
(clinical staging, project_user_serum_cohort() for serum,
or the user_cohort_extension vignette's TNM/AJCC mapping
table).vignettes/user_cohort_extension.Rmd -- two new appendices:
Appendix A is a TNM / AJCC -> Normal / Early / Mid / Late
harmonization table for users mapping their clinical staging
data; Appendix B walks project_user_serum_cohort() end-to-end
with a synthetic 50-gene x 24-sample (8 PDAC / 8 HC / 8
Pancreatitis) example that returns ready-to-assemble
serum_summary.README.md Scenario 6 -- restructured into 6a (tissue
projection, stage-aware), 6b (serum projection, binary), and
6c (combined tissue + serum -> single audit score). Adds an
explicit "Important data requirement" callout at the top of
Scenario 6 that documents the asymmetry and tells N vs T
users which path to take.tests/testthat/test-project-user-serum.R covering schema,
log2FC = mean(PDAC) - mean(HC), planted PDAC-up signal
detection, missing/wrong group labels (friendly errors),
link_to_atlas TRUE / FALSE, and translation_class
cross-checks (LTBP1 / LGALS3BP -> A; ALB -> B; GAPDH -> C).fit_stage_de().project_user_serum_cohort is a new export; no public API
removals. fit_stage_de() behaviour is strictly stricter (now
errors on N vs T instead of silently degenerating), but no
previously valid input changes outcome.
**viz_gene() expanded to a six-panel evidence-to-score canvas
plot_filter_trace() +
plot_serum_direction() exported.** The single-call composite
now shows the entire prioritisation flow on one page: four input
layers (RNA, tissue protein, scRNA cell origin, serum direction),
the 7-step tissue-to-serum filter trail that gates them, and the
6-axis hexagon that compresses all of the above into the final
audit-score components.plot_serum_direction(gene) -- exported standalone version of
the per-gene serum direction strip (PDAC vs HC and Pancreatitis
vs HC log2FC, faceted by contrast, coloured by translation
Class A / B / C). Previously available only as the strip
embedded above plot_filter_trace()'s grid.R/viz_gene.R -- panel layout expanded from four to six
(default ncol = 3, 2x3 grid):
TL bulk RNA per-stage forest; TM tissue protein per-stage
trajectory; TR scRNA cell-of-origin distribution;
BL serum direction (PDAC + Pancreatitis log2FC);
BM 7-step filter trail with pass-count badges;
BR 6-axis audit hexagon. Every panel-builder is wrapped in a
.vg_safe() helper so a NULL / error return becomes a
graceful "no data" placeholder, keeping the grid intact for
genes with sparse evidence layers. New ncol options: 3
(default), 2 (3x2), 1 (6x1 vertical). The previous RNA
per-cohort sign-vote panel remains available standalone via
[plot_per_cohort()].R/plot_filter_trace.R -- visual rewrite of the 7-step filter
grid and the auxiliary-routes panel. Step labels move from top
(rotated 45 degrees, 5.5 pt) to bottom (horizontal, 7 pt,
two-line) for higher legibility at smaller embeddings; tile
borders go from grey50 / 0.4 to white / 0.6 for a cleaner
separation; pass-fill upgraded from olive (#2E7D32) to teal
(#00796B) and fail-fill from white to soft blush (#FFE0E0)
for higher contrast at print size; coord_equal() keeps cells
square. Each gene row gains an inline pass-count badge
("X/7") in monospace. The serum direction strip header is
tightened (subtitle inlined into title; legend keys shrunk to
0.35 cm). Auxiliary routes panel mirrors the same compact
styling.R/plot_stage_effect.R -- protein-layer subtitle now states
explicitly that no per-stage SE is rendered because the
upstream phase34_protein_pooled_12template.csv is a limma
F-test (overall significance) rather than per-contrast Wald
(which would yield lfcSE_E/M/L). Per-contrast Wald is
deferred (would require an upstream limma rerun + atlas
rebuild).No public API removals; six-panel layout is additive (was 4 in
v0.99.7.1), and plot_serum_direction is a new export.
viz_gene() rebalanced to one panel per evidence layer +
plot_filter_trace() enriched with serum direction context.
The v0.99.7 canvas was RNA-heavy: two of the four panels (per-stage
forest + per-cohort sign-vote) read from the same RNA layer, while
tissue proteomics and serum proteomics had no dedicated visual
slot. This release rebalances so each of the four evidence layers
(bulk RNA, tissue protein, scRNA cell origin, serum + filter)
gets exactly one panel.
R/plot_stage_effect.R -- new layer = c("rna", "protein")
argument. The protein variant reads prot_beta_N/E/M/L from
the bundled [pdactrace_protein_betas] table and draws
per-stage point estimates. Per-stage SE is unavailable on the
protein side so no CI is drawn (the overall F-test padj is
reported in the subtitle instead). Genes absent from the
protein atlas render as a graceful "no data" placeholder.R/plot_filter_trace.R -- new show_serum = TRUE default
appends a serum direction strip above the 7-step phase60 grid
showing per-gene PDAC vs HC and Pancreatitis vs HC log2FC,
coloured by translation class (Class A blue, Class B red,
Class C grey, NA light grey). Existing callers see a richer
panel by default; pass show_serum = FALSE to recover the
v0.99.7 layout. Output type is unchanged
(inherits(., "ggplot") still TRUE for all combinations).R/viz_gene.R -- panel layout rebalanced to one-per-layer:
TL bulk RNA per-stage forest, TR tissue protein per-stage
trajectory (uses the new layer = "protein" arg), BL scRNA
cell-of-origin distribution, BR serum direction strip + 7-step
filter trace. The previous RNA per-cohort sign-vote panel
remains available standalone via [plot_per_cohort()].test_that blocks in tests/testthat/test-plots.R
covering: plot_filter_trace(show_serum = TRUE/FALSE),
plot_stage_effect(layer = "protein"), and graceful handling
for genes absent from pdactrace_protein_betas.No public API removals; layer and show_serum are additive
optional arguments. The default behaviour of
plot_filter_trace() now includes the serum strip; this is the
intended improvement, and a one-line show_serum = FALSE opt-out
is provided for callers who want the older bare grid.
Single-call visual evidence canvas + methodology-first positioning. Two coordinated changes for non-technical reviewers and reader audiences: (1) one new function that turns the entire per-gene evidence story into a single composite figure, and (2) a DESCRIPTION + README reframing that leads with the tissue-to-serum translation framework and demotes the bundled PDAC atlas to the demonstration cohort role.
viz_gene(gene_symbol, title, ncol) -- 2x2 patchwork canvas
composing per-stage trajectory forest, per-cohort sign-vote bar,
scRNA cell-of-origin distribution, and 7-step tissue-to-serum
filter trace, under a one-line headline naming the matched
template, audit class, and translation class. The visual analog
of summarize_gene_evidence() and the recommended first call
for a clinician or biologist who hands you a gene -- one plot,
no per-axis function names required. ncol = 1 for a vertical
strip suitable for narrow embedding.DESCRIPTION: Title: reframed from "Queryable Stage-Aware
PDAC Tissue-to-Serum Biomarker Reference Atlas" to "Transparent
Multi-Omics Tissue-to-Serum Biomarker Translation Framework
with PDAC Reference Atlas". Description: rewritten to lead
with the framework components (12-template catalog, 3-axis +
2-gate audit, Evidence Math layer, optional interpretable ML
layer, Class A / B / C translation discipline) and to position
the PDAC atlas explicitly as the demonstration cohort, not the
primary contribution.README.md opening: same reframe, plus a quantitative anchor
for the framework's evaluation harness (39.3x external-anchor
enrichment, p = 2.18e-10; LOO median 41.6x; bootstrap 95% CI
[20.2, 56.3]).README.md "What you get": now split into "Methodology
(transferable to any cancer)" and "PDAC demonstration cohort"
sub-sections; the four canonical case studies (LGALS3BP, LTBP1,
ALB, GAPDH) are listed equally as one-per-class
demonstrations, with no single gene treated as a flagship.README.md Scenario 1: now leads with viz_gene("LTBP1") as
the visual entry point; the existing query_gene("LTBP1")
text view is presented as the scripting / knitr-report
alternative.No public API removals; viz_gene() is purely additive.
Friendlier report_gene() failure when pandoc is missing. Patch
release for the one user-facing rough edge that surfaced during the
post-v0.99.6 install verification: report_gene() requires pandoc
(a system tool that powers rmarkdown::render()), but until now
the failure was reported as a generic rmarkdown error.
R/report_gene.R — pre-checks rmarkdown::pandoc_available("1.12.3")
and raises a friendly error pointing the user at install
instructions for RStudio / Debian / macOS / pandoc.org.README.md Scenario 4 — adds an explicit "System requirement"
callout naming pandoc as the dependency. Reaffirms that all
other pdactrace functions (query_gene, evidence_math,
plot_*, etc.) work without pandoc.No public API changes; nothing to migrate.
Optional interpretable ML layer + Bioconductor hygiene patch. Adds an opt-in machine-learning prioritisation layer on top of the v0.99.5 deterministic atlas. Per-axis-first by design: an ML-ready feature matrix, a descriptive feature-space similarity score that uses curated anchors without training a classifier, and a user-supplied supervised wrapper for callers who bring their own labels. The package still ships no pretrained predictor.
Deep learning is intentionally out of scope for the core Bioconductor package: PDAC biomarker discovery has limited samples, many features, and ambiguous labels — the regime where DL invites hard-to-defend reviewer questions about training labels, leakage, external validation, and Python / GPU dependencies. DL extensions belong in the manuscript-monorepo, not in the tool package.
make_evidence_features(genes, scale, impute, drop_na_rows) —
flat numeric data.table (genes × ~21 features) suitable for
glmnet, ranger, scikit-learn, etc. Computes the same
arithmetic that evidence_math() exposes per-axis but in a
tabular shape. scale ∈ {"none", "z", "robust"}; impute ∈
{"none", "mean", "zero"} for callers that need complete-case
numerics for ML fitting.score_anchor_similarity(genes, anchors, method, tier) —
descriptive cosine / inverse-Euclidean similarity in z-scored
feature space to the centroid of the bundled
pdactrace_external_anchors set. Reuses the same tier
partition (primary / secondary / all) as
evaluate_anchor_enrichment(). The bundled anchor labels define
the centroid only — they are never used as supervised training
labels for any shipped predictor.fit_user_evidence_model(features, labels, method = "elastic_net", alpha, nfolds, seed) — wraps glmnet::cv.glmnet(family = "binomial"). Requires user-supplied labels; errors politely on
NULL, single-class, or length-mismatched inputs. Returns an S3
pdactrace_user_model carrying CV AUC, coefficient table,
top-N positive / negative contributors, and a model card.
glmnet joins Suggests: (runtime-checked via
requireNamespace()).predict_user_evidence_model(model, new_features) — score new
genes from a fitted user model.explain_user_evidence_model(model, top_n) — print signed top-N
positive and top-N negative coefficients with feature names.
This is the user-facing rationale for the supervised score
("Main positive / negative contributors").model_card(source, model, verbose) — single point of
reviewer-facing metadata. For "anchor_similarity": feature set
version, anchor count, "no labels used for training", intended
use, leakage controls, limitations. For "user_model": same
shape, plus n_positives / n_train / CV AUC ± SD / lambda.min /
alpha / seed / top contributors..Rbuildignore: now excludes analysis/, data_raw/, figure/,
*.pptx, *.docx, *.xlsx, ..Rcheck, pdactrace_*.tar.gz,
pdactrace.Rcheck, pdactrace.BiocCheck, plus repo docs
(AGENTS.md, CHANGELOG.md, CLAUDE.md, BIOCONDUCTOR.md).
Without these, the next R CMD build could pull a 99 GB
analysis/ tree into the tarball.inst/extdata/multi_cohort_consistency.csv.xz (NEW; ~518 KB) —
bundles the Stouffer + per-cohort RNA consistency table that
data-raw/build_reference.R previously read from
analysis/transcriptomics/results/figure1/. The Layer 3
reproducibility claim ("rebuild from documented processed
inputs") now actually holds without the manuscript-monorepo.
data-raw/build_reference.R routes the read through the same
bundled-first lookup chain as the six existing phase CSVs.data-raw/bundle_multi_cohort_consistency.R — bundler script
mirroring data-raw/bundle_phase_csvs.R for this single file.test_that blocks): coverage for feature
matrix integrity (numeric, no duplicates, scale moments, NA
policy), anchor-similarity rank quality (T1 anchors enrich into
the top decile), label-leakage discipline (no training labels in
score_anchor_similarity(); fit_user_evidence_model() requires
user-supplied labels), and model card content.Suggests: gains glmnet (used by fit_user_evidence_model()
via runtime requireNamespace(); not a hard dependency for any
user who only wants the lookup / scoring / Evidence Math API).Evidence Math layer. Adds a third interpretability layer between
the existing plain-English provenance text (format_provenance()) and
the audit-score decomposition (explain_score()): the mathematical
evidence values that actually fed those decisions, exposed per axis.
Per-axis-first by design — there is no new black-box composite score.
evidence_math(gene_symbol) — returns a structured list with one
element per axis (trajectory_fit, effect_magnitude,
cohort_consistency, rna_protein_coupling, serum_bridge,
cell_specificity, filter_survival, clinical_role). All values are
read directly from the bundled atlas or derived by a single named
arithmetic operation. New derived quantities: delta_rho = rho_best - rho_runner_up (template specificity margin), ||beta||_2
(Euclidean norm of the per-stage beta vector over E,M,L) and
cosine(beta_RNA, beta_prot) (RNA-protein direction concordance).explain_gene(gene_symbol, view = c("evidence", "math", "both")) —
text formatter that prints either the plain-English provenance, the
Evidence Math sections, or both. Mirrors explain_score() in
pattern (verbose-print + invisible structured return).compare_genes(gene_symbols, axes, wide) — multi-gene tidy-table
pivot of evidence_math() output. Long form by default
(gene, axis, metric, value); wide = TRUE for one row per gene
with axis.metric columns suitable for manuscript tables.evidence_math("LTBP1"), explain_gene("LTBP1", view = "math"),
and compare_genes(...) with truncated example output.download_phase_csvs() is documented as not evaluated
during package checks.pdactraceData ExperimentHub package, planned for a future
release.Reproducibility vignette + on-demand phase33/34 fetcher. Closes
the v0.99.3 self-contained-rebuild story: the bundled inst/extdata
plus the new download_phase_csvs() helper plus a 4-layer
vignette("05_reproducibility") give end users a complete documented
path from the prebuilt atlas all the way back to the public
phase-CSV inputs, without cloning the manuscript-monorepo.
download_phase_csvs(target, ref, cache, verbose) — fetches the
two large upstream phase CSVs (phase33_deseq2_coef_12template.csv,
phase34_protein_pooled_12template.csv) on demand from
raw.githubusercontent.com/jibeomko/PDAC_biomarker (Zenodo
10.5281/zenodo.20067849) and caches them via
[BiocFileCache::BiocFileCache()]. Returns a named character
vector of cached file paths. BiocFileCache is a soft
(Suggests) dependency picked up at runtime via
requireNamespace() — no impact on packages that only need the
query / score / report API.vignettes/05_reproducibility.Rmd — 4-layer reproducibility
guide:
data/*.rda directly; no
network).project_user_cohort()).inst/extdata plus the two upstream CSVs cached via
download_phase_csvs().DESCRIPTION — Suggests: gains BiocFileCache for the new
helper. Version bumped 0.99.3 → 0.99.4. Imports / Depends are
unchanged.Self-contained reproducibility — small phase CSVs bundled in
inst/extdata. The package now ships the six small downstream
phase tables (phase2c / phase42 / phase77 / phase29 / phase60 /
phase80; ~52 KB compressed total) so that the full
build_reference.R re-derivation chain runs without the companion
manuscript-monorepo. Two large upstream CSVs (phase33 RNA fit,
phase34 protein fit) remain external because they push the tarball
over Bioconductor's 5 MB limit; the build scripts now fall through
a clean lookup chain (inst/extdata/ → $PDAC_BASE_DIR/... →
informative error pointing at the manuscript Zenodo archive
10.5281/zenodo.20067849).
inst/extdata/phase{2c,29,42,60,77,80}_*.csv.xz — bundled,
xz-compressed copies of the six small phase outputs that
build_reference.R joins onto the RNA/protein base. Total ~52 KB
added to the tarball; no impact on R CMD check or BiocCheck.data-raw/bundle_phase_csvs.R — bundler that re-creates the
inst/extdata/*.csv.xz set from the manuscript-monorepo when
PDAC_BASE_DIR is set. Strips phase33 to the 16 columns that
build_reference.R actually uses; everything else is a verbatim
trim + xz pass.data-raw/build_reference.R — adds an internal read_phase()
helper that prefers the bundled inst/extdata copy, falls back to
$PDAC_BASE_DIR/.../*.csv (and .csv.xz), and errors with a
clear "set PDAC_BASE_DIR or download from Zenodo
10.5281/zenodo.20067849" message if neither exists. Six of the
seven fread() calls in the script now route through this helper.
The two large CSVs (phase33, phase34) still come via
read_phase() but resolve via the fallback chain because the
tarball can't accommodate them.data-raw/build_protein_betas.R — same lookup chain via
.find_phase_csv() + xz-aware fread. Re-running the script now
works against the bundled CSV (set
data/pdactrace_protein_betas.rda rebuild path entirely
in-package once the phase34 input is available).inst/extdata chain and
the Zenodo download path for the two remaining external CSVs.Human-readable provenance + larger Arial-bold typography on all
plots. Two reviewer-facing polish passes: the phaseXX tags that
the bundled atlas carries in provenance are now relabelled to
plain-English evidence sources on the user-facing print path
(phase IDs are preserved verbatim as a Technical: footer for
reproducibility), and the NCS-grade ggplot theme that backs every
plot_*() function gains larger, sharper Arial-bold typography for
clearer single-column embedding.
format_provenance(provenance, style) (exported) — maps the
internal phase tags onto plain-English evidence-source labels.
Three styles: "compact" (one-line plus-separated summary),
"verbose" (multi-line bulleted list with explanations),
"raw" (the original phase tags, for the technical footer).
Mapping: phase33 → "RNA trajectory", phase34 → "Tissue
protein trajectory", stouffer_consistency → "Multi-cohort RNA
consistency", phase2c → "scRNA cell origin", phase42 →
"Serum / pancreatitis comparison", phase60 → "7-step serum
filter audit", phase77 → "Strict RNA-protein-serum bridge",
phase29 → "Resectable-stage marker screen", phase80 →
"Predeclared panel member". Unknown tags fall through unchanged
with an (unmapped) suffix in verbose mode.query_gene() print method — replaces the Provenance: line
with two lines: Evidence: (plus-separated human labels) and
Technical: (the raw phase IDs).query_gene_detailed() print method — surfaces the verbose
bulleted list so that for an interactive query, the reviewer
sees a per-source one-line explanation immediately, with the
raw IDs folded below.summarize_gene_evidence() — same two-line restructuring of the
trailing provenance block; the rest of the summary text is
unchanged.R/theme.R — pdactrace_axes_theme() and
pdactrace_panel_theme() switch font family to Arial with a
sans fallback, bump axis titles 6.5 → 8.5 pt (bold), axis text
5.8 → 7.5 pt (now also bold), plot title 8 → 10 pt, subtitle 5.5
→ 7.5 pt, legend text 5.4 → 7.0 pt, strip text 5.6 → 7.5 pt,
tighten the axis line / tick contrast (grey15 instead of
grey30). Plots render the same shape as before but at clearly
legible sizes for both single-column and double-column embedding.
No API change — every existing plot_*() function picks up the
new typography automatically.Per-template trajectory PDFs (RNA + protein). Two new exported
functions render the bundled atlas's 12-template trajectory
catalogue as compact, NCS-grade PDF panels — one panel per template
showing the cohort of genes / proteins that match it best
(z-scored Pearson-rho argmax across all 12 templates) as thin
translucent lines, a mean line, and a ±1 SD ribbon. Reproduces the
historical fig2C_RNA_*.pdf figures inside the package and extends
them to the four templates introduced in v0.4.0
(Late_Burst_Up, Late_Loss_Down, Monotonic_Up,
Monotonic_Down).
plot_template_atlas(layer, templates, output_dir, ...) —
atlas-wide reference, returns 12 ggplot panels (or a user-chosen
subset). When output_dir is set, writes one cairo-PDF per
template via pdactrace_save() and reports paths in
attr(out, "files").plot_gene_template(gene_symbol, layer, output_file, ...) —
per-gene overlay: identifies the gene's matched template via the
same 12-template Pearson-rho argmax that backs
classify_trajectory() / score_trajectory(), then draws that
template's cohort with the gene's own z-scored trajectory
highlighted on top. Genes whose best-match is a non-Early
template (i.e., pdactrace_reference$rna_pattern is NA because
only Early × 4 is surfaced) get a visible
"non-Early best-match" sub-title.pdactrace_protein_betas — bundled data.table (5,917 measurable
proteins × 8 columns) carrying per-stage tissue-protein effect
sizes (prot_beta_N/E/M/L), the full 12-template best-match
label, matched ρ, and BH-adjusted F-test padj. Generated by
data-raw/build_protein_betas.R from
phase34_protein_pooled_12template.csv. Drives the protein layer
of the two new plot functions; the main atlas
(pdactrace_reference) only carries categorical
prot_pattern / prot_tier, which is why this separate object
is needed for trajectory visualisation..plot_template_panel() (the private layout helper used by both
public functions) degrades gracefully on tiny cohorts: cohorts of
1 drop the SD ribbon, cohorts of 2–4 drop the ribbon but keep
individual lines, cohorts of ≥ 5 show the full thin-lines + mean +
ribbon. This keeps every one of the 12 panels renderable —
relevant for template_protein_Late_Loss_Down (n = 1 in the
current bundled data).
tests/testthat/test-plot-template-atlas.R — 6 blocks:
length-12 / named return shape (RNA + protein), every RNA cohort
non-empty, templates subsetting, invalid-name error, output_dir
writes one PDF per template.tests/testthat/test-plot-gene-template.R — 5 blocks: ggplot
return for an Early-surface gene, non-Early fallback subtitle for
GAPDH (housekeeping), PDF write-out, protein-layer round-trip,
missing-gene error.First Bioconductor submission. Per Bioconductor convention, new packages submit at 0.99.0; subsequent versions in the review queue go 0.99.1, 0.99.2, ... and on acceptance into the release branch the version becomes 1.0.0. The audit framework, the bundled atlas, the 12-template trajectory catalog, and the external anchor evaluation results are all carried forward unchanged from the v0.4.1 development line. v0.99.0 is the first version made visible to Bioconductor and consolidates everything below in a single release.
report_gene(gene_symbol, ...) — accepts either a single HGNC
symbol or a multi-gene character vector. Length 1 produces a
self-contained one-page HTML evidence report (audit-class tag,
audit-component table, six-axis evidence radar versus the
high_confidence_mean reference, stage-trajectory plot,
per-cohort breakdown, per-stage detail table, filter trace,
atlas-version provenance footer). Length 2+ produces a panel
template with a compare_candidates() table at the top, a
multi-gene evidence radar, and one explain_score()-derived
rationale card per gene. Both templates use a minimal inline
CSS (no Bootstrap) and weigh ~230–410 KB.
Templates: inst/rmd/gene_report.Rmd, inst/rmd/panel_report.Rmd.
rmarkdown and knitr are picked up at runtime from Suggests
via requireNamespace() — no hard dependency added.explain_score(gene_symbol, verbose = TRUE) — decomposes one
gene's audit_score into the three weighted evidence axes
(evidence_strength 40%, biological_coherence 35%,
translational_relevance 25%) and the two reliability gates
(leakage_gate, heterogeneity_gate). Returns a list with the
structured breakdown plus a one-paragraph plain-English rationale
derived from which gate state actually fired (housekeeping flag,
plasma-high-abundance flag, max meta I² bracket). E.g.,
"LTBP1 lands in supported_uncertain because the
heterogeneity_gate = 0.7 — max meta I² = 75% in [70%, 90%)".compare_candidates(gene_symbols) — one row per input gene with
audit class + score, RNA / protein trajectory pattern, translation
class, dominant scRNA cell origin, serum detectability, max meta
I², plus a redundancy_with column flagging genes that share both
rna_pattern and cell_origin_top in the input set. Sorted by
audit_score descending; missing genes returned as NA rows.project_user_cohort(rna, coldata, stage_col, cohort_col, ...) —
end-to-end wrapper around fit_stage_de() →
classify_trajectory() → assemble_user_evidence() →
compute_audit_score(). Accepts either a count matrix +
coldata, or a SummarizedExperiment whose colData() carries
the stage / cohort columns. Optional protein argument (matrix or
SE) layers in tissue-protein evidence on the same design.
Returns a pdactrace_user_projection list with each intermediate
object (rna_fit, rna_pattern, prot_fit, prot_pattern,
evidence, audit) plus a one-row summary of audit-class
counts. Designed to make "apply pdactrace to my own staged
cohort" a single line.align_patient_profile(rna_logfc, prot_logfc = NULL, ...) —
sample-level analog of score_trajectory(). Computes
audit-weighted Pearson rho between the patient's per-gene log2FC
vector and each of the three atlas stage axes (rna_beta_E,
rna_beta_M, rna_beta_L), with Fisher-z 95% CI, plus a
secondary audit-weighted vote share that surfaces
disagreement-with-rho as a diagnostic. Returns a
pdactrace_patient_alignment list with $rna (4-row data.table),
$prot (categorical concordance, optional), $summary
(one-line), and $attrs (provenance). Misalignment with all three
stage axes is a legitimate output and does not imply Normal.
Discipline-aligned: deliberately not a supervised classifier — an
RF / GLM trained on TCGA stage labels would break the package's
"no supervised fitting under limited ground truth" core principle.fit_stage_de(object, ...) and fit_stage_de_protein(object, ...)
are S4 generics with two methods each. The ANY method preserves
the original matrix / data.frame signature
(fit_stage_de(counts, stage, cohort)); a new
SummarizedExperiment method accepts
fit_stage_de(se, stage_col, cohort_col, assay_name = "counts")
(and assay_name = "intensity" for the protein side). Both paths
share the same DESeq2 LRT (RNA) / limma (protein) kernel and
produce numerically identical output (verified by
tests/testthat/test-se-input.R).as_summarized_experiment(reference = NULL) — converts the bundled
10,113-gene atlas into a SummarizedExperiment with two assays
(rna_beta, rna_lfcSE; both 10,113 × 4 stages), a 4-row
colData (stage, reference_level), a ~109-column rowData
(audit components, RNA / protein trajectory pattern, translation
class, scRNA cell origin, serum direction, meta-analysis I², ...),
and atlas-provenance metadata. The bundled object remains a
data.table for fast query-based use cases; this constructor is
the Bioc-native view on demand.toy_counts (50 × 24 integer matrix; 10 stage-progressive
rows), toy_coldata (24 rows: stage, cohort, sample), and
toy_protein (50 × 24 log2 matrix; 8 stage-progressive rows).
Generated by data-raw/build_toy_data.R with set.seed(2026).
The user-cohort vignette uses these in place of inline synthetic
generation so examples run end-to-end with no external download.pdactrace_data_sources — bundled data.table, one row per
public dataset (GEO / PRIDE / PDC / ICGC / GTEx / MassIVE / SRA)
contributing to the v0.99 atlas (26 rows: 6 RNA + 3 Protein +
10 scRNA + 3 Serum + 2 Pancreatitis + 2 Validation). Generated by
data-raw/build_data_sources.R from the manifest TSVs.list_data_sources(layer = NULL) — accessor for the data-source
table, with optional layer filter.atlas_provenance() — one-call provenance dossier returning
package version, atlas snapshot, both Zenodo DOIs, both repo URLs,
cohort count, and per-layer dataset count.Five exported aliases alongside their fully-spelled originals to reduce typing friction. Both forms refer to the same function and share one Rd page; existing scripts using the long names continue to work unchanged.
| Long name (kept) | Short alias (new) |
|---|---|
| evaluate_anchor_enrichment() | anchor_enrichment() |
| early_pattern_names() | early_patterns() |
| mid_pattern_names_excluded() | mid_patterns() |
| align_patient_profile() | align_patient() |
| classify_protein_trajectory() | classify_prot_trajectory() |
plot_gene_hexagon() migrated from bare theme_void() to
pdactrace_panel_theme() so all 10 plot functions now share the
same NCS-grade typography (single-column 88 mm,
NCS_W_15COL = 4.72 in, NCS_W_DOUBLE = 7.08 in).
geom_text sizes reduced to 1.7–2.2 mm (≈5–6.5 pt) so the
hexagon embeds cleanly at single-column width.pdactrace_save() replaces cat() with message() so package
diagnostics route through the standard message stream
(BiocCheck-compliant)..audit_mc_table() Monte-Carlo helper replaces the
manual set.seed() + on.exit() save/restore block with a
single withr::local_seed(seed) call. The seed parameter is
scoped to the helper and the global RNG state is restored on
function exit — same behaviour, BiocCheck-compliant.man/figures/pdactrace_overview.jpg, 1800 × 1344, 280 KB,
hand-drawn, license-clean): staged omics evidence → 12-template
trajectory matching → Early-onset atlas surface → multi-layer
evidence integration → 3-axis + 2-gate audit scoring → user
outputs (query_gene · explain_score · compare_candidates ·
trace_filters · project_user_cohort). Closing tagline:
"Transparent prioritization, not a supervised diagnostic
classifier."Version: 0.99.0. Authors@R is canonical; the redundant
Author: / Maintainer: lines are omitted.Depends: R (>= 4.5.0) (Bioconductor 3.22's minimum supported R).Imports: data.table, ggplot2, patchwork, glue, methods, stats,
utils, withr, SummarizedExperiment.Suggests: DESeq2, limma, S4Vectors, testthat (>= 3.0.0), knitr,
rmarkdown, pkgdown.LazyData: true, LazyDataCompression: xz, Roxygen: list(markdown = TRUE), Config/testthat/edition: 3.tests/testthat/test-se-input.R — matrix vs SummarizedExperiment
numerical equivalence for both fit_stage_de (DESeq2) and
fit_stage_de_protein (limma), plus informative-error coverage
on missing colData columns / assay_name.tests/testthat/test-explain-compare-se.R — explain_score()
structure + missing-gene error, compare_candidates() row count +
sort order + missing-gene padding, as_summarized_experiment()
shape + reference-column invariant.tests/testthat/test-marker-class-stability.R — pins LGALS3BP
(high_confidence), LTBP1 (supported_uncertain), ALB (penalized),
GAPDH (excluded); verifies compare_candidates() ordering on the
four case studies; round-trips toy_counts through
fit_stage_de() + classify_trajectory(); checks
list_data_sources() shape + filter and atlas_provenance()
Zenodo-DOI invariants.R CMD check --as-cran: 0 ERROR, 1 WARN, 6 NOTE.
The single WARN is qpdf needed for PDF size checks — env-only
(the Bioconductor build farm has qpdf installed); no substantive
WARN remains.BiocCheck(new-package = TRUE): 0 ERROR, 0 WARN, 15 NOTE.User-data extension track + dual-classification cleanup — additive, backwards-compatible API that lets a new user run the v0.3.0 audit framework on their own multi-omics cohort. The frozen 3-axis + 2-gate rule, the audit labels, and all v0.3.0 evaluation results remain unchanged.
confidence_tier,
early_onset_score, heterogeneity_factor) are dropped from the
bundled atlas. They were superseded by v0.3.0 audit_class and
retained as legacy in v0.3.0 for ablation; the dual-classification
was creating reviewer-grade ambiguity (e.g., LGALS3BP scoring
audit_class = high_confidence for strong multi-layer convergence
while the v0.2 tier flagged it ARTIFACT for low single-layer
effect size). v0.3.0 audit_class is now the canonical
per-gene classification.list_candidates() no longer accepts min_tier. Use the new
min_audit_class parameter instead. Default changed from
"SILVER" to "ALL" (no audit-class filter applied) — explicit
filtering by audit_class is the intended workflow.max_abs_beta_meta and
max_I2_meta are retained because they feed the
heterogeneity_gate and rescue-eligibility logic.plot_gene_hexagon(gene_symbol, comparison) — compact 6-axis
hexagonal radar chart of a gene's audit-feature profile
(Multi-layer / Direction / Stage-onset / Serum bridge / Leakage
safety / Cohort consistency). Multi-gene overlay and optional
comparison polygon (e.g., comparison = "high_confidence_mean")
are supported; designed as a high-quality NCS-grade per-gene
summary card.fit_stage_de_protein(intensity, stage, cohort) — limma-based
parallel of fit_stage_de for user-supplied tissue-protein
intensity matrices. Returns the same column schema so downstream
trajectory classification works for either layer.classify_protein_trajectory(fit, rho_cutoff) — protein-side
wrapper of classify_trajectory that renames the output column
from rna_pattern to prot_pattern for assembly downstream.assemble_user_evidence(rna_fit, prot_fit, scrna_summary, serum_summary, signal_peptide, cross_cohort_agreement, max_I2) —
combines optional per-layer user inputs into a per-gene evidence
table conforming to the schema columns the bundled atlas exposes;
layers the user does not supply are filled with NA and degrade
gracefully through the existing feature constructor.Late_Burst_Up, Late_Loss_Down — onset at Stage III/IV;
Peak/Trough/Plateau are structurally degenerate at the last stage)
and pan-stage Monotonic × 2 (Monotonic_Up, Monotonic_Down —
linear progression with maximum at Late, distinct from
Mid_Plateau_* which has its largest jump at Stage II). Atlas
surface (rna_pattern) still exposes only Early × 4 by design; the
other 8 templates compete in the matching step and are flagged via
excluded_mid_pattern, excluded_late_pattern,
excluded_monotonic_pattern. Effect on numbers: GAPDH and CDH13
correctly reclassified as Monotonic_Up and dropped from the Early
surface (housekeeping/leaky-plasma genes that previously contaminated
Early × 4); RNA × Protein 4-Early-concordant set 1,424 → 1,356; full
Tier 1 gold (any 12-template match) 1,449 → 1,375. Headline anchor
enrichment numbers are invariant (deterministic top-100 secondary:
7 hits / 39.3× / p = 2.18e-10 unchanged from v0.3.0; LOO median 41.6,
bootstrap 95% CI [20.2, 56.3]).rna_wald_padj_E/M/L — genuine
per-contrast Wald padj (Early/Mid/Late vs Normal) from a
nbinomWaldTest() refit of the same ~ dataset + stage_group model
used for the LRT. rna_padj_E/M/L remain in the schema for
back-compat but are LRT padj copies (DESeq2 LRT mode returns the
same omnibus padj for every per-contrast results() call). The
audit framework continues to use rna_lrt_padj as its significance
gate, so no v0.3.0 audit numbers change. query_gene_detailed()
$per_stage now exposes both lrt_padj and wald_padj columns;
plot_stage_effect() uses Wald padj for the per-stage * marks.compute_audit_score(gene_symbol, evidence = NULL) — new
evidence parameter accepts a user-supplied evidence table (e.g.,
the output of assemble_user_evidence). When NULL (default),
the bundled v0.3.0 reference atlas is used; behaviour and numbers
are bit-for-bit identical to v0.3.0.propagate_uncertainty(gene_symbol, n_mc, seed, evidence = NULL) —
same evidence override; stored MC summaries are unavailable for
user evidence and n_mc must be supplied in that case.evaluate_anchor_enrichment(top_n, tier, score_col, evidence = NULL, anchors = NULL) — both the evidence table and the anchor table
can be overridden so a user can run anchor enrichment against
their own evidence and their own anchor reference set..get_reference(reference = NULL) — internal helper now accepts
an optional reference override; default behaviour unchanged..audit_genes(genes, reference = NULL) — internal helper takes an
optional reference for membership checks against user evidence.user_cohort_extension.Rmd — five-step walkthrough on a small
synthetic example showing user RNA + protein → assemble_user_evidence
→ compute_audit_score → evaluate_anchor_enrichment with a
user-supplied anchor list. Runs in <60 s under
devtools::check().tests/testthat/test-user-extension.R — round-trip on a fixed
synthetic example: schema sanity for both fit functions, full
audit-score column schema after assemble_user_evidence, and a
backwards-compat assertion that
compute_audit_score(evidence = NULL) matches the bundled v0.3.0
result.The PDAC reference atlas remains the default reference; v0.4 does
not provide a build_user_atlas() function or layer plugin
architecture. Disease-agnostic atlas building is planned for v0.5
(see Discussion §6 of the BiB manuscript).
limma is added to Suggests so fit_stage_de_protein() can be
loaded conditionally; users who do not need protein input do not
need to install limma.Audit framework track — replaces opaque marker tiers with a
transparent, pre-specified evidence aggregation framework for PDAC
early-marker hypothesis prioritization. The deterministic rule
summarises each gene along three evidence axes
(evidence_strength, biological_coherence,
translational_relevance), applies two reliability gates
(leakage_gate, heterogeneity_gate), and assigns it to one of
interpretable audit labels (high_confidence, supported_uncertain,
penalized, excluded, low). This release does not train a
supervised biomarker predictor; external anchors are used only for
post-freeze enrichment evaluation.
build_evidence_graph(gene) — returns a descriptive evidence graph
for a gene, including layer presence, direction agreement,
early-pattern support, serum bridge, leakage gate, heterogeneity
gate, and final audit score.extract_graph_features(gene) — exposes the deterministic feature
components that compose the three evidence axes (mapping in
supplement Table S1).compute_audit_score(gene) — computes the frozen v0.3.0 score
audit_score = positive_score × leakage_gate × heterogeneity_gate
with positive_score = 0.40 × evidence_strength + 0.35 × biological_coherence + 0.25 × translational_relevance,
normalized to the atlas-wide maximum, and assigns an audit_class
label per gene.propagate_uncertainty(gene) — returns Monte Carlo score/rank
intervals and a confidence_class (stable_high, high_uncertain,
medium, low, excluded) reported alongside the deterministic
audit_class.evaluate_anchor_enrichment(top_n, tier) — evaluates top-N
enrichment of external PDAC biomarker anchors against the frozen
audit ranking; anchors are never used for training or weight tuning.case_study(genes) — combines v0.2 tier, deterministic
audit_class, MC uncertainty, anchor provenance, and the
composite pdactrace_call label for manuscript panels.27 populated audit_* columns:
audit_evidence_strength, audit_biological_coherence,
audit_translational_relevance.audit_leakage_gate,
audit_heterogeneity_gate.audit_class
(high_confidence / supported_uncertain / penalized /
excluded / low).audit_score_layer, audit_score_direction,
audit_score_early, audit_score_serum, audit_score_rescue,
audit_positive_score, audit_leakage_mult,
audit_heterogeneity_mult, audit_score_raw, audit_score,
audit_is_housekeeping, audit_is_plasma_high_abundance,
audit_rescue_eligible.audit_score_median,
audit_score_lo95, audit_score_hi95, audit_uncertainty_width,
audit_rank_median, audit_rank_lo95, audit_rank_hi95,
audit_confidence_class.audit_score ranking: secondary Tier 1+2
anchors show 7 hits in the top 100 (39.3×, hypergeometric
p = 2.2e-10; hits = MSLN, THBS2, CEACAM1, TIMP1, MUC16,
SERPINA1, ANPEP) — strengthened from the prototype 7-feature
flat-weight implementation (5 hits / 28.1× / p = 6.6e-07).audit_score_median) gives 5 hits / 28.1× and is reported as a
sensitivity ranking (Methods §7).leakage_gate = 0 (audit_class = excluded), and high-abundance
plasma proteins receive leakage_gate = 0.5
(audit_class = penalized).LGALS3BP and THBS2 are high_confidence, LTBP1 is
supported_uncertain (heterogeneity-gated), ALB is
penalized, and GAPDH is excluded.Granularity track — exposes hidden per-stage / per-cohort / per-celltype / per-filter-step detail that v0.1.0 only summarized at the headline level. No breaking changes: all v0.1.0 functions preserved; new functions are additive.
query_gene_detailed(gene) — returns 5-slot data.table list:
per_stage, per_cohort, per_celltype (all 11), filter_diag,
serum_per_cohort. Stouffer p, agreement %, specificity tau,
PDAC-vs-Pan t-pval exposed as table attributes.summarize_gene_evidence(detail = TRUE) — adds per-stage,
per-cohort, pancreatitis raw means, and filter underlying-metric
block to text summary.plot_stage_effect() — log2FC ± 95% CI forest with significance
asterisks per stage.plot_per_cohort() — TCGA / CPTAC / GSE224564 / GSE79668 trend
plot_filter_diagnostics() — 7-step filter bar with underlying
metric annotation (e.g., pool padj = NA, pan-vs-HC pval = 0.017).plot_celltype_full() — full 11-celltype expression bar with
PDAC-relevant cell types highlighted in red.13 new populated columns:
rna_padj_E/M/L, rna_lfcSE_E/M/L (per-stage)rna_stouffer_p, rna_stouffer_padjrna_per_cohort_trend, rna_per_cohort_monotonic (list-cols)cell_specificity_tauann_pan_vs_hc_logfc, ann_pan_vs_hc_pval,
ann_pan_excluded_phase60ann_pdac_mean, ann_pan_mean, ann_hc_mean,
ann_pdac_vs_pan_pvalEarly_Burst_Up label hides this.testthat passes (current 59 + 41 new).Initial public release of PDAC-TRACE — queryable PDAC stage-aware multi-omics gene-level lookup atlas.
Central message: PDAC tissue biomarker ≠ always serum-up biomarker. Tissue-derived candidates can preserve, invert, or decouple when projected into serum.
Originally introduced as a 4-Early-pattern trajectory framework
(v0.1.0). Widened in v0.4.0 to a 12-template competitive catalog
(Early × 4 + Mid × 4 + Late × 2 + Monotonic × 2) where each gene
must out-compete 11 alternatives before being surfaced as Early. The
atlas surface (rna_pattern) restricts visible calls to:
Early_Burst_Up — Normal low → Early up → sustainedEarly_Loss_Down — Normal high → Early down → sustainedEarly_Peak — Early peak → Mid/Late declineEarly_Trough — Early trough → Mid/Late recoveryMid / Late / Monotonic best-matches are flagged via
excluded_mid_pattern / excluded_late_pattern /
excluded_monotonic_pattern for transparent provenance.
pdactrace_reference (10,113 genes × 45
cols) bundling 8 source phase result CSVs across bulk RNA-seq,
tissue proteomics, scRNA cell origin, serum proteomics,
pancreatitis context, and phase60 7-step filter audit trail.query_gene(), query_panel(),
list_candidates() (multi-param), trace_filters(),
summarize_gene_evidence(), list_atlas_metadata().fit_stage_de(), classify_trajectory(),
score_trajectory() for users with their own bulk RNA-seq.plot_gene_evidence(), plot_filter_trace(),
plot_panel_heatmap(), plot_candidate_landscape().01_lookup_basics, 02_ltbp1_case_study.Early_Burst_Up (rho ≈ 1.0)Early_Burst_Up (Tier 1 gold concordant)phase77_classB route — passes phase77 strict +
Class B + manual curation, while phase60 strict 7-step funnel
only captures SignalPexcluded_*_pattern rather than surfaced —
see v0.4.0 entry above).phase60 strict vs phase77
strict) can disagree — trace_filters() shows both routes
honestly.predict_detectability()).